pimatic-unieq-box
Version:
Pimatic plugin for the UNIEQ-Box smart meter
163 lines (137 loc) • 5.53 kB
text/coffeescript
# #UnieqBox plugin
module.exports = (env) ->
Promise = env.require 'bluebird'
rest = require('restler-promise')(Promise)
_ = env.require 'lodash'
util = require 'util'
events = require 'events'
commons = require('pimatic-plugin-commons')(env)
class UnieqBoxPlugin extends env.plugins.Plugin
init: (app, , ) =>
# register devices
deviceConfigDef = require("./device-config-schema")
= .debug || false
= commons.base @, "UnieqBoxPlugin"
.deviceManager.registerDeviceClass("UnieqBox", {
configDef: deviceConfigDef.UnieqBox,
createCallback: (config, lastState) =>
return new UnieqBoxDevice config, @, lastState
})
class UnieqBaseDevice extends env.devices.Device
# Initialize device by reading entity definition from middleware
constructor: (, , ) ->
= .config.debug ? false
= commons.base @, .class unless ?
.debug("Device Initialization")
= .id
= .name
= 1000 * .normalize .interval, 10, 86400
= .host
= .port
super()
process.nextTick () =>
destroy: () ->
.cancelUpdate()
super()
_requestUpdate: (command) ->
if ?
rest.get("http://#{@host}:#{@port}/hook/unieq-json/")
.then (result) =>
if result.data?.registers?
.debug "Response: #{util.inspect(result.data, { showHidden: true, depth: 4 })}"
"data", null, result.data.registers
else
throw new Error "Invalid response data"
.catch (errorResult) =>
.error if errorResult instanceof Error then errorResult else errorResult.error
.finally () =>
.scheduleUpdate ,
else
.error "Invalid configuration. Property host is undefined"
_has: (obj, path) ->
return false if not _.isObject obj or not _.isString path
keys = path.split '.'
for key in keys
if not _.isObject(obj) or not obj.hasOwnProperty(key)
return false
obj = obj[key]
return true
class AttributeContainer extends events.EventEmitter
constructor: () ->
= {}
class UnieqBoxDevice extends UnieqBaseDevice
attributeTemplates =
activePowerSupply:
type: "number"
register: "1-0:1.4.0*255"
unit: "W"
description: "Active power+"
acronym: "P+"
activeEnergySupply:
type: "number"
register: "1-0:1.8.0*255"
unit: "Wh"
description: "Active energy+"
acronym: "E+"
powerFactor:
type: "number"
register: "1-0:13.4.0*255"
description: "Power factor"
acronym: "PF"
supplyFrequency:
type: "number"
register: "1-0:14.4.0*255"
unit: "Hz"
description: "Supply frequency"
acronym: "F"
# Initialize device by reading entity definition from middleware
constructor: (, , lastState) ->
= .config.debug ? false
= commons.base @, .class unless ?
= new AttributeContainer()
= _.cloneDeep()
= {}
for attributeName in .attributes
do (attributeName) =>
if attributeTemplates.hasOwnProperty attributeName
properties = attributeTemplates[attributeName]
[attributeName] =
description: properties.description || () ->
return attributeName.replace /(^[a-z])|([A-Z])/g, ((match, p1, p2, offset) =>
(if offset>0 then " " else "") + match.toUpperCase())
type: properties.type
unit: properties.unit if properties.unit?
acronym: properties.acronym if properties.acronym?
.values[attributeName] = 0
[properties.register] = attributeName
.on attributeName, ((value) =>
.debug "Received update for", attributeName, value
if value?
.values[attributeName] = value
attributeName, value
)
else
.error "Configuration Error. No such attribute: #{attributeName} - skipping."
super(, , "GetPowerFlowRealtimeDataData")
'data', ((error, values) =>
if error or not values
if error
.error error
else
for item in values
.debug JSON.stringify(item),
if .hasOwnProperty item.register
.debug "Matched", [item.register]
.emit [item.register], item.value
)
destroy: () ->
super()
# ###Finally
# Create a instance of my plugin
myPlugin = new UnieqBoxPlugin
# and return it to the framework.
return myPlugin