Devices are added to pimatic by first providing a config for it. Every device needs an entry in the devices-Section of the config.json
file
A device config looks like that:
{
"id": "light",
"class": "MySwitch",
"name": "Kitchen Light"
}
You must first register your new Device by calling the registerDeviceClass
function of the deviceManager
. The framework reads every device config on startup and calls the provided createCallback
function for all registered device of the registered class. The callback gets the device-config from the config file and should construct and return the instance of the device:
module.exports = (env) ->
class MyPlugin extends env.plugins.Plugin
init: (app, @framework, config) =>
# ...
deviceConfigDef = require("./device-config-schema")
@framework.deviceManager.registerDeviceClass("MySwitch", {
configDef: deviceConfigDef.MySwitch,
createCallback: (config) => new MySwitch(config)
})
class MySwitch extends env.devices.PowerSwitch
# ...
myPlugin = new MyPlugin
return myPlugin
Any device must be subclass of the device class. A device has Attributes and Actions
Attributes are properties of the device like the state of a switch or sensor values like temperature. For Sensor-Devices these are displayed at the frontend as values. For other devices the display type depends on the device type. For example the state of a switch is displayed as an switch button.
Attributes are defined by adding defining the attributes
property of the Device
class:
class MyDevice extends env.devices.Device
attributes:
temperature:
description: "the messured temperature"
type: Number
unit: '°C'
getTemperature: -> Promise.resolve(30)
Each attribute must have a getter function that returns a Promise fulfilled with the current attribute value. The getter must be named like the attribute prefixed with get
and Uppercase first letter of the attribute name.
If an attribute changes an event with the attribute name should be emitted that contains the new value:
inSomeFunctionOfMyPlugin: =>
# Got a new value, so emit it to the framework:
@emit "temperature", 20
For more attribute examples take a look at the predefined Devices.
In additional to attributes a device can have Actions. Actions are functions that can be called by the framework. Actions are defined like attributes:
class MyDevice extends env.devices.Device
actions:
turnOn:
description: "turns the switch on"
turnOff:
description: "turns the switch off"
changeStateTo:
description: "changes the switch to on or off"
params:
state:
type: Boolean
# Returns a promise
turnOn: -> @changeStateTo on
# Retuns a promise
turnOff: -> @changeStateTo off
# Retuns a promise that is fulfilled when done.
changeStateTo: (state) -> #...
view raw
For each Action there should be a function with the same name that executes the action and returns a promise which gets fulfilled when done.
For more actions examples take a look at the predefined Devices.
Your constructor function must assign a name and id to the device (typical from the device config).
class MyDevice extends env.devices.Device
# ####constructor()
# Your constructor function must assign a name and id to the device.
constructor: (@config) ->
@name = @config.name
@id = @config.id
# ...
super()
The destroy function is called when the device is deleted or modified. It must unregister event handlers and clear timers typically used for polling updates. Finally, the super()
function must be called.
If you don't want to define an exotic device try to use a predefined Device as base class.
For Switch devices you can use the PowerSwitch
class as base and you have to define the changeStateTo
and getState
function.
class MySwitch extends env.devices.PowerSwitch
# ####constructor()
# Your constructor function must assign a name and id to the device.
constructor: (@config) ->
@name = @config.name
@id = @config.id
# ...
An full example for an switch device can be found in the with-switch-device branch
A Temperature sensor can use the TemperatureSensor
class as base. You must define a getTemperature
function and emit the "temperature" attribute event, if a new value was read.
class YourTemperatureSensor extends env.devices.TemperatureSensor
temperature: null
constructor: (@config) ->
@name = "some name or from config"
@id = "some-id"
# update the temperature every 5 seconds
setInterval( ( =>
@doYourStuff()
), 5000)
doYourStuff: () ->
# temperature = ...
@temperature = temperature
@emit "temperature", temperature
getTemperature: -> Promise.resolve(@temperature)