diff --git a/README.md b/README.md index a276380..a9d99d6 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,41 @@ Pimatic Plugin for WebSolarLog (WSL), an open-source data logger for PV systems - . +Note, this is an early version of the plugin provided for testing purposes. Please provide feedback via +[github](https://github.com/mwittig/node-websolarlog/issues) or +[pimatic-forum](http://forum.pimatic.org/category/13/plugins). + ## Configuration -TBD. +You can load the plugin by editing your `config.json` to include the following in the `plugins` section. The property +`interval` specifies the time interval in seconds for updating the data set. For debugging purposes you may set +property `debug` to true. This will write additional debug messages to the pimatic log. The values +properties `interval` and `debug` represent the the default values. + + { + "plugin": "websolarlog", + "interval": 30, + "debug": false + }, + +Then you need to add a device in the `devices` section. Currently, only the following device type is supported: + +* WebSolarProduction: This type is for solar power production devices. It provides attributes for the current + power produced, + +As part of the device definition you need to provide the `deviceName` which is the name of the Production Device +as it has been set via WebSolarLog Admin. You also need to provide the `url` for the Live page of your WebSolarLog +server. + + { + "id": "wsl1", + "class": "WebSolarLogProduction", + "name": "WSL Test", + "deviceName": "Diehl", + "url": "http://diehl-inverter-demo.websolarlog.com/api.php/Live", + } ## History -TBD. +* 20150417, V0.0.1 + * Initial Version diff --git a/device-config-schema.coffee b/device-config-schema.coffee new file mode 100644 index 0000000..ad141be --- /dev/null +++ b/device-config-schema.coffee @@ -0,0 +1,20 @@ +module.exports = { + title: "pimatic-websolarlog device config schemas" + WebSolarLogProduction: { + title: "WebSolarLog Production Device" + description: "Provides energy earnings and current power values of a production device" + type: "object" + extensions: ["xConfirm"] + properties: + deviceName: + description: "The name of the Production Device which has been set via WebSolarLog Admin" + type: "string" + url: + description: "URL of the WebSolarLog Server Live page" + type: "string" + interval: + description: "Polling interval for switch state in seconds" + type: "number" + default: 0 + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..4c02367 --- /dev/null +++ b/package.json @@ -0,0 +1,53 @@ +{ + "name": "pimatic-websolarlog", + "description": "Pimatic Plugin for WebSolarLog (WSL), an open-source data logger for PV systems", + "author": { + "name": "Marcus Wittig", + "url": "https://github.com/mwittig/pimatic-websolarlog" + }, + "main": "websolarlog", + "files": [ + "websolarlog.coffee", + "README.md", + "websolarlog-config-schema.coffee", + "device-config-schema.coffee", + "LICENSE" + ], + "version": "0.0.1", + "homepage": "https://github.com/mwittig/pimatic-websolarlog", + "keywords": [ + "pimatic", + "SolarView", + "Solar Energy", + "Photovolatics", + "SmartHome", + "SmartMeter", + "Volkszaehler", + "Monitoring", + "Metering" + ], + "repository": { + "type": "git", + "url": "git://github.com/mwittig/pimatic-websolarlog.git" + }, + "bugs": { + "url": "https://github.com/mwittig/pimatic-websolarlog/issues" + }, + "licenses": [ + { + "type": "GPLv2", + "url": "https://github.com/mwittig/pimatic-websolarlog/blob/master/LICENSE" + } + ], + "configSchema": "websolarlog-config-schema.coffee", + "dependencies": { + "node-websolarlog": ">=0.0.1" + }, + "peerDependencies": { + "pimatic": ">0.8.19" + }, + "engines": { + "node": ">0.8.x", + "npm": ">1.1.x" + } +} \ No newline at end of file diff --git a/websolarlog-config-schema.coffee b/websolarlog-config-schema.coffee new file mode 100644 index 0000000..43e26cf --- /dev/null +++ b/websolarlog-config-schema.coffee @@ -0,0 +1,13 @@ +module.exports = { + title: "pimatic-websolarlog plugin config options" + type: "object" + properties: + interval: + description: "Polling interval for switch state in seconds" + type: "number" + default: 30 + debug: + description: "Debug mode. Writes debug message to the pimatic log" + type: "boolean" + default: false +} \ No newline at end of file diff --git a/websolarlog.coffee b/websolarlog.coffee new file mode 100644 index 0000000..8eca770 --- /dev/null +++ b/websolarlog.coffee @@ -0,0 +1,139 @@ +# #WebSolarLog plugin + +module.exports = (env) -> + + # Require the bluebird promise library + Promise = env.require 'bluebird' + + # Require the nodejs net API + net = require 'net' + + url = require 'url' + + wsl = require 'node-websolarlog' + + # ###WebSolarLogPlugin class + class WebSolarLogPlugin extends env.plugins.Plugin + + # ####init() + # The `init` function is called by the framework to ask your plugin to initialise. + # + # #####params: + # * `app` is the [express] instance the framework is using. + # * `framework` the framework itself + # * `config` the properties the user specified as config for your plugin in the `plugins` + # section of the config.json file + # + # + init: (app, @framework, @config) => + # register devices + deviceConfigDef = require("./device-config-schema") + + @framework.deviceManager.registerDeviceClass("WebSolarLogProduction", { + configDef: deviceConfigDef.WebSolarLogProduction, + createCallback: (config) => + return new WebSolarLogProductionDevice(config, this) + }) + + + class WebSolarLogBaseDevice extends env.devices.Device + # Initialize device by reading entity definition from middleware + constructor: (@config, @plugin) -> + @debug = plugin.config.debug; + env.logger.debug("WebSolarLogBaseDevice Initialization") if @debug + @id = config.id + @name = config.name + + parts = url.parse(config.url, false, true) + if !parts.hostname? + env.logger.error("Device URL must contain a hostname") + @deviceConfigurationError = true; + + @options = {} + @options.name = config.deviceName || config.name + @options.host = parts.hostname + @options.path = parts.path if parts.path? + @options.port = parts.port if parts.port? + @options.protocol = parts.protocol if parts.protocol? + @interval = 1000 * (config.interval or plugin.config.interval) + super() + + if !@deviceConfigurationError + @_scheduleUpdate() + + + # poll device according to interval + _scheduleUpdate: () -> + if typeof @intervalObject isnt 'undefined' + clearInterval(=> + @intervalObject + ) + + # keep updating + if @interval > 0 + @intervalObject = setInterval(=> + @_requestUpdate() + , @interval + ) + + # perform an update now + @_requestUpdate() + + _requestUpdate: -> + id = @id + wsl.getProductionDeviceData(@options).then((values) => + @emit "productionData", values + ).catch((error) -> + env.logger.error("Unable to get production data form device id=" + id + ": " + error.toString()) + ) + + _setAttribute: (attributeName, value) -> + if @[attributeName] isnt value + @[attributeName] = value + @emit attributeName, value + + + class WebSolarLogProductionDevice extends WebSolarLogBaseDevice + # attributes + attributes: + currentPower: + description: "AC Power (Phase 1)" + type: "number" + unit: 'W' + acronym: 'GP' + currentAmperage: + description: "AC Amperage (Phase 1)" + type: "number" + unit: 'A' + acronym: 'GA' + currentVoltage: + description: "AC Voltage (Phase 1)" + type: "number" + unit: 'V' + acronym: 'GV' + + currentPower: 0.0 + currentAmperage: 0.0 + currentVoltage: 0.0 + + # Initialize device by reading entity definition from middleware + constructor: (@config, @plugin) -> + env.logger.debug("WebSolarLogProductionDevice Initialization") if @debug + + @on 'productionData', ((values) -> + if (values.data?) + @_setAttribute('currentPower', Number values.data.GP) if values.data.GP? + @_setAttribute('currentAmperage', Number values.data.GA) if values.data.GA? + @_setAttribute('currentVoltage', Number values.data.GV) if values.data.GV? + ) + super(@config, @plugin) + + getCurrentPower: -> Promise.resolve @currentPower + getCurrentAmperage: -> Promise.resolve @currentAmperage + getCurrentVoltage: -> Promise.resolve @currentVoltage + + # ###Finally + # Create a instance of my plugin + myPlugin = new WebSolarLogPlugin + # and return it to the framework. + return myPlugin \ No newline at end of file