Custom Devices - implemented externally or in p44script

What are "Custom Devices"?

"Custom devices" are devices that behave in the system (Digital Strom with P44-DSB-xx) exactly like other devices, but can be implemented by the user in a simple way. In this way, special hardware can also be easily integrated into the Smart Home, for example via an http API or (e.g. on P44-DSB-X) via direct hardware extensions (RaspberryPi shields, chips connected to GPIO, etc.).

How are "Custom Devices" created?

"Custom Devices" can be implemented in two different ways:

  • Starting with firmware version 2.6.0 directly in the P44-xx device as p44script. This kind of external devices can be created completely from the web interface of P44-xx devices, and are also saved in the configuration backups as part of the device configuration. p44script provides a lot of convenient functions to control different kinds of devices: from functions for accessing HTTP APIs (geturl, posturl, puturl), direct access to digital (digitalio) and analog (analogio) inputs and outputs, to motors with limit switches and current monitoring (dcmotor), to the graphics subsystem lrgraphics for SmartLED chains, a lot is possible. Here are easy to implement/extend examples to find.

  • Already since firmware 1.5.0.8 there is the external device API. With this API an external script or application can connect to a P44-xx device via a TCP socket and easily integrate devices into the smarthome system. This way is useful e.g. to establish connections between different systems, or to integrate devices with very complex implementation that would go beyond the scope of p44Script performance. Here are several examples to find how the external device API can be used.

These two possible implementation types work almost identically in concept, the only difference is where the implementation runs (inside the P44-xx device as p44script, or outside and connected via TCP socket). In both cases, however, the communication "language" of the device implementation with the system is the same, namely the external device API. For p44script implementations, the message() function is used to receive and send external device API messages. For fully external devices, messages are exchanged over TCP/IP.

Similarities between p44script and external implementations

  • The device is described to the system by the so-called init message, which takes the form of a JSON object.
  • In the init-message you can choose between a very simple text variant and a more detailed JSON variant for further communication. By default JSON is used, which is very easy to read and write in p44Script.
  • The implementation only has to take care of passing output values given by the system to the hardware and reporting input values to the system. All the complexity of scenes, room assignments, click detection, dimming behavior, sensor value filters, etc. is handled by the p44-xx device.

Differences between p44script and external implementations

  • For p44script implementations, the init message is entered once when the device is created in the web interface. For external devices, the init message must be submitted at the beginning of communication (each time the TCP connection is re-established).
  • For p44script implementations, the init message may be written on multiple lines and may even contain C-style comments /* ... */. For external implementations, the whole init-message must be sent on a single line and as pure JSON without comments (because the end of line is taken as a message separator).
  • In external implementations, it is possible to run multiple devices over a single TCP connection; the messages are then assigned to different devices via so-called tags. In p44script implementations there is no such multiple device mechanism, and therefore no tags. The references to tag parameters in the following description of the external device API are therefore irrelevant for p44script implementations.
  • In p44script implementations the messages initvdc, log and bye are not available.

Using the external device API from p44script implementations

Creating p44script based devices

To create a p44script based device, use the "+ Scripted" button in the P44-xx web interface. You can then enter a init message (specification below), which is then immediately used to create a device.

Operation of p44script implemented devices

The device must be implemented in a script that basically does the following

  • initialize the device (set-up hardware, initialize parameters etc.)

  • If the device has outputs, make sure to have a handler processing incoming messages, like:

    on (message()) as m {
      // check the message and act upon channel changes etc.
      if (m.message="channel") {
        // ...update the channel in the hardware
      }
    }
    
  • If the device has buttons, inputs or sensors, make sure to use message(msg_to_send) to report to the system when inputs change. This can be done from a permanently running main loop (but do not forget to include enough delay() to avoid using excessive CPU time and slow down the entire device!), or on() {...} handlers based on input events or regular timing (e.g. using the every() function), for example

    on (every(0:05)) {
      // every 5 minutes, poll a sensor
      var s = getmysensorvalue()
      var m = { 'message': 'sensor', 'index':0 }
      m.value = s;
      message(m)
    }
    
  • either keep running (e.g. in a loop) or return true. Note that returning true (or keep running) is essential because all other ways a script ends is treated as a possibly temporary problem, which means the script is re-started. Only if the implementation scripts returns true, this is treated as an OK signal meaning that the device can operate without a script running permanently (i.e. only via on(...) {} handlers that trigger some code when needed)

For more information, see the examples.

Using the external device API via TCP-IP

To host external devices, vdcd must be started with the --externaldevices option, providing a port number or absolute unix socket path for device implementation to connect to. For security reasons, it is recommended to run the scripts and programs implementing devices on the same device as vdcd itself. However for development purposes the --externalnonlocal command line option can be specified to allow device API connections from non-local clients.

The plan44.ch Digital Strom products P44-DSB-xx and P44-DSB-xx support the external device API from version 1.5.0.8 onwards. Multiple devices sharing a single connection is supported from version 1.5.2.0 onwards. Single device support is supported from 1.6.0.2 onwards. However, the external device API is active by default only for P44-DSB devices enabled for "testing"/beta (available upon request), or for devices with userlevel set to 1 or higher (default for production devices is 0, can be set to 1 via remote support upon request). In the free "P44-DSB-X" plan44.ch image for RaspberryPi, the external device API is always enabled. By default, vdcd uses port 8999 for the external device API

Operation of TCP-IP connected external devices

Each external device implementation needs to

  • open a connection to the TCP port or unix socket specified with the --externaldevices vdcd command line option (default is port 8999).
  • optionally, send a initvdc message to adjust vdc-level data (like vdc model name and icon)
  • send a init message declaring the properties of the device (specifying outputs, inputs, names, default group membership etc.). The init message uses JSON syntax. However, no JSON support is actually needed in a device implementation, because the init message can specify to use a extremely simple text protocol for any communication beyond the init message itself. And the init message is usually a constant string that can be sent easily using any programming language. (Note that for single devices, which have complex actions and events, and for some advanced features like output transition times, only the JSON syntax is supported).
  • enter a loop, waiting for messages from the vdcd indicating output channel changes, or sending messages to the vdcd indicating input changes.
  • When connection closes (due to error or when vdcd explicitly closes it), the device implementation should restart, see first bullet point. This can be achieved within the device implementation itself, or by having the device implementation run as a daemon under control of a daemon supervisor like runit or procd or systemd, which re-start daemons when they terminate.
  • from version 1.5.2.0 onwards, multiple devices can be created on the same TCP connection. To distinguish them, each one must be assigned a tag in the init message, which must/will then be used in all further messages to/from that device.

Message Format over TCP/IP

Messages consist of strings, delimited by a single LF (0x0A) character. The init message must always be in JSON format. Further messages are either JSON or simple text messages, depending on the protocol option in the init message (see below).

Initvdc Message (only for external devices over TCP/IP)

The optional initvdc message can be sent by an external device implementation to set some vdc-global parameters:

Field Type Description
message string identifies the message type, must be initvdc for the initvdc message
modelname optional string a string describing the vdc model. This will be displayed by the dSS as "HW Info". By default, the vdc has a model name like "P44-DSB-X external"
modelVersion optional string a string providing version information about the hardware device governing the access to a device bus/network such as a KNX bridge.
iconname optional string a string that is used to construct a file name of the icon to be displayed for the vdc.Default for iconname is "vdc_ext".
configurl optional string a URL that will be shown in the context menu of the vdc in the dSS configurator (i.e. the contents of the "configURL" vdc property in the vDC API).If not specified, this will default to the vdchost's default URL (if any).
alwaysVisible optional boolean if set to true, the vdc will announce itself to the vDC API client even if it does not (yet) contain any devices.
name optional string the default name the external vDC will have in the Digital Strom system. Note that this can be changed by the user via dSS Web interface.

Sending the Init Message over TCP/IP

The init message is sent by a external device implementation as the first message after opening the socket connection. It needs to be formatted as a single line JSON object.

To initialize multiple devices sharing the same connection, multiple init messages can be put into a JSON array. This is required in particular to create multiple devices that are meant to communicate via the simple text API - because after the first message, the protocol will be switched to simple text and would not allow further JSON init messages.

A simple init message for a light dimmer might look like (on a single line):

{'message': 'init','protocol':'simple','output':'light','name':'ext dimmer','uniqueid':'myUniqueID1234'}

A init message for two light dimmers on the same connection might look like (on a single line):

[{'message': 'init', 'tag':'A', 'protocol':'simple', 'output':'light', 'name':'ext dimmer A', 'uniqueid':'myUniqueID1234_A'}, {'message': 'init', 'tag':'B', 'protocol':'simple', 'output':'light', 'name':'ext dimmer B', 'uniqueid':'myUniqueID1234_B'}]

For more information, see the examples.

External device API specification

The rest of this document specifies the external device API protocol and applies to both p44script implemnented devices (where messages are exchanged via the message() function) and externally running implenmentations communicating via TCP/IP.

Init message structure

The following tables describes all possible fields of the init message JSON object:

Field Type Description
message string identifies the message type, must be init for the init message
protocol optional string Can be set to simple to use the simple text protocol for all further communication beyond the init message. This allows implementing devices without need for any JSON parsing.If set to json (default), further API communication are JSON messages.
Note: protocol can be specified only in the first init message. It is ignored if present in any subsequent init messages.
Note that single devices (those that use actions, events, properties or states) must use the JSON protocol.
tag optional string When multiple devices are created on the same connection, each device needs to have a tag assigned. The tag must not contain '=' or ':'. The tag is used to identify the device in further communication.
uniqueid string (optional for p44script devices, required for external API devices) This string is optional for p44script implemented devices, but required for external API devices. If specified, it must uniquely define the device at least among all other external devices connected to the same vdcd, or even globally.To identify the device globally, use a UUID string (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) or a valid 34 hex digit Digital Strom dSUID. To identify the device uniquely among all other devices in the same vdcd, use any other string. From firmware 2.7 onwards: If the uniqueid has the form of an URN like schema:hardwareID, then the dSS will display the hardwareID part, which must then be globally unique within the schema (as an example, your device might have a mac-address, then an unique id of the form macaddress:xx:xx:xx:xx:xx would be useful. Similarily, if your device has its proprietary id scheme, use something like typeofid:xxxx).
subdeviceindex optional integer This can be used to create multiple devices with the same base dSUID (i.e. same uniqueid passed in the init message), which is recommended for composite devices like fan coil units, which have a heater/cooler subdevice and a fan subdevice, or for multiple buttons that can be combined to form 2-way buttons.
colorclass optional integer defines the device's color class (if not specified, a default color is derived from group and/or output)
  • 1: yellow/light
  • 2: grey/shadow
  • 3: blue/climate
  • 4: cyan/audio
  • 5: magenta/video
  • 6: red/security
  • 7: green/access
  • 8: black/joker
  • 9: white/single device
group optional integer defines the group of the device's output (if not specified, the output type determines a default group)
  • 1: yellow/light,
  • 2: grey/shadow
  • 3: blue/heating
  • 4: cyan/audio
  • 5: magenta/video
  • 6: red/security
  • 7: green/access
  • 8: black/variable
  • 9: blue/cooling
  • 10: blue/ventilation
  • 11: blue/windows
  • 12: blue/air recirculation
  • 48: room temperature control
  • 49: room ventilation control
output optional string Defines the type of output:
  • light: dimmer output with light behaviour
  • colorlight: 6-channel Digital Strom color light (brightness, hue, saturation, colortemp, cieX, cieY).
  • ctlight: 2-channel tunable white light with only 2 channels (brightness, colortemp) exposed in vDC API.
  • movinglight: color light with additional X and Y position channels.
  • heatingvalve: 0..100% heating valve.
  • ventilation: device with airflow intensity, airflow direction and louver position channels, according to ds-ventilation specification. Also see the kind field.
  • fancoilunit: device with 0..100% fan output channel, receiving set point and current room temperature values via control message for regulation.
  • shadow: jalousie type device with position and angle channel. Also see move and kind fields.
  • action: For single devices only: this creates a scene table with scenes having a command field which can be used to assign device actions to scenes.
  • basic: basic 0..100% output with no special behaviour. Can be used for relay outputs.
Default is: no output.
kind optional string for shadow and ventilation output type Defines the kind of device.
For shadow:
  • roller: simple roller blind, no angle
  • sun: sunblind
  • jalousie: jalousie with blade angle control
For ventilation:
  • ventilation: air supply/exhaust
  • recirculation: air (re)circulation within rooms
dimmable optional boolean This can be used to set the output operation mode of a device between continuously dimmable (true) or on/off (false). Note that this does not make sense for all output types. All output types have a default operation mode. This option makes most sense for the generic basic output type
positional optional boolean This can be used to set the output operation mode of a device to positional (similar to dimmable, but not controlling an intensity, but a physical position, e.g. of a blind, window motor etc.). Note that this does not make sense for all output types. All output types have a default operation mode. This option makes most sense for the generic basic output type
endcontacts optional boolean for shadow output type If set to true, device implementation must report reaching top and bottom positions by updating channel value to 100 or 0, resp. (using the "channel" message). Otherwise, the shadow behaviour uses move time settings to derive actual positions from timing alone.
move optional boolean If set to true, the device must support the "move" or "MV" message (see below), which is issued by the device to start or stop a movement (increase, decrease) of the output value. The relative move semantic might be more useful for blind type devices than absolute channel output values. Default is false (no move semantics)
sync optional boolean if set to true, the device must support the "sync" message and must respond to "sync" with the "synced" message. "sync" is issued by the vdcd when it needs to know current output values (e.g. for a saveScene operation). "synced" is sent by the device when updated output channel values have been sent to the vdcd.Default is false (no output value sync requests)
controlvalues optional boolean If set to true, control values (such as room temperature set points and actual values) are forwarded to the external device using the "control"/CTRL message.
scenecommands optional boolean If set to true, the vDC will send the "scenecommand"/SCMD message to devices for some special scene commands that may have additional semantics beyond changing channel values.
groups optional array of integers can be used to explicitly indicate membership of one or more output groups. This overrides all other group affiliations derived from colorclass, group and output. The group numbers are the same as for group, see above.
hardwarename optional string a string describing the type of output hardware, such as "dimmer" or "relay" etc.Default is the string specified in output.
modelname optional string a string describing the device model. This will be displayed by the dSS as "HW Info".
modelversion optional string a string describing the device's firmware version. This will be displayed by the dSS as "Firmware Version". When this string is empty, the software version of the vdc host is used instead (representing the device's vdc-side implementation version).
vendorname optional string the vendor name
oemmodelguid optional string the GUID that is used to identify devices (in particular: single devices) in the Digital Strom server side database to provide extended information. Usually this is a GS1 formatted GTIN like:'gs1:(01)76543210123'
iconname optional string a string that is used as a base to construct a file name of the icon to be displayed for the device. vdcd will first try to load a icon named "iconname_groupcolor" (with groupcolor being the color of the device). If such a file does not exist, vdcd tries to load "iconname_other". The default value for iconname is "ext" for external devices and "scpt" for scripted devices.
configurl optional string a URL that will be shown in the context menu of the device in the dSS configurator (i.e. the contents of the "configURL" device property in the vDC API).If not specified, this will default to the vdchost's default URL (if any).
typeidentifier optional string an identifier specifying the (hardware implementation) type of this device. By default, it is just "external". This identifier is not used in Digital Strom, but it is exposed as "x-p44-deviceType" for local Web-UI, and it is used to load type-specific scene tables/properties from .csv files.
deviceclass optional string a device class intended to group functionally equivalent single devices (washing machines, kettles, ovens, etc.). This must match a Digital Strom-defined device class, and the device must provide the actions/states/events/properties as specified for that class.
deviceclassversion optional integer a version number for the device class.
name optional string the default name the device will have in the Digital Strom system. Note that this can be changed by the user via dSS Web interface.
buttons optional array of objects Defines the buttons of the device. See table below for fields in the button objects
inputs optional array of objects Defines the binary inputs of the device. See table below for fields in the input objects
sensors optional array of objects Defines the sensors of the device. See table below for fields in the sensor objects
configurations optional object containing named configurations Defines the device configurations (such as two-way button vs. two separate one-way buttons) possible for this device. Note that devices must use the JSON protocol to use configurations.The configurations object can contain 1..n configuration objects, see table below
currentConfigId string For devices with multiple configurations (see above), this field must contain the current configuration's id.
actions optional object containing named actions Defines the device actions of the device (for 'single' devices). Note that single devices must use the JSON protocol.The actions object can contain 1..n action objects, see table below
dynamicactions optional object containing dynamic actions by their id Defines ainitial set of dynamic actions of the device (for 'single' devices). Note that single devices must use the JSON protocol.The dynamicactions object can contain 1..n dynamicaction objects, see table below. If no dynamic actions are known at the time of device instantiation, dynamicactions can be omitted.Note that dynamic actions (unlike normal actions) can als be added, changed and deleted during device operation using the dynamicAction message, see below.
standardactions optional object containing standard actions by their id Defines the standard actions of the device (for 'single' devices). Note that single devices must use the JSON protocol.The standardactions object can contain 1..n standardaction objects, see table below.
autoaddstandardactions optional boolean If set to true, a standard action is created automatically for each defined action using the action's name prefixed by "std."
noconfirmaction optional boolean Can be set to true when the device implementation does not want to confirm action completion
states optional object containing states by their id Defines the states of the device (for 'single' devices). Note that single devices must use the JSON protocol.The states object can contain 1..n state objects, see table below
events optional object containing events by their id Defines the events of the device (for 'single' devices). Note that single devices must use the JSON protocol.The events object can contain 1..n event objects, see table below
properties optional object containing properties by their id Defines the device properties of the device (for 'single' devices). Note that single devices must use the JSON protocol.The properties object can contain 1..n property objects, see table below

Button object in the buttons field of the init message

Field Type Description
id optional string string id, unique within the device to reference the button via vDC API.
buttonid optional integer Note: this field can also be set as "id" for backward compatibility with earlier versions of this API. Identifies the hardware button this button input belongs to. Two-way or multi-way buttons will have multiple button definitions with the same id. Defaults to 0
buttontype optional integer Defines the type of button:
  • 0: kind of button not defined by device hardware
  • 1: single pushbutton
  • 2: two-way pushbutton or rocker (Note: if you use this, the first button must be the the down element and the second button must be the up element.
  • 3: 4-way navigation button
  • 4: 4-way navigation with center button
  • 5: 8-way navigation with center button
  • 6: On-Off switchDefaults to 1 (single pushbutton)
element optional integer Defines which element of a multi-element button is represented by this button input:
  • 0: center element / single button
  • 1: down, for 2,4,8-way
  • 2: up, for 2,4,8-way
  • 3: left, for 2,4,8-way
  • 4: right, for 2,4,8-way
  • 5: upper left, for 8-way
  • 6: lower left, for 8-way
  • 7: upper right, for 8-way
  • 8: lower right, for 8-wayDefault is 0 (single button)
group optional integer defines the primary color (group) of the button:
  • 1: yellow/light,
  • 2: grey/shadow
  • 3: blue/heating
  • 4: cyan/audio
  • 5: magenta/video
  • 6: red/security
  • 7: green/access
  • 8: black/variable
  • 9: blue/cooling
  • 10: blue/ventilation
  • 11: blue/windows
  • 48: roomtemperature control
Defaults to primary device group
combinables optional integer if set to a multiple of 2, this indicates that there are other devices with same uniqueid but different subdeviceindex, which can be combined to form two-way buttons. In this case, each of the combinable devices must have a single button only, and the subdeviceindex must be in the range n..n+combinable-1, with n=subdeviceindex MOD combinable
localbutton optional boolean If set to true, this button acts as a local button for the device (directly switches and dims the output)
hardwarename optional string a string describing the button element, such as "up" or "down" etc. Default is "button_idX_elY" where X is the buttonid and Y is the element

Input object in the inputs field of the init message

Field Type Description
id optional string string id, unique within the device to reference the binary input via vDC API.
inputtype optional integer Defines the type of input:
  • 0: no system function
  • 1: Presence
  • 2: Light
  • 3: Presence in darkness
  • 4: twilight
  • 5: motion
  • 6: motion in darkness
  • 7: smoke
  • 8: wind
  • 9: rain
  • 10: solar radiation (sun light above threshold)
  • 11: thermostat (temperature below user-adjusted threshold)
  • 12: device has low battery
  • 13: window is closed
  • 14: door is closed
  • 15: window handle (0=closed, 1=open, 2=tilted)
  • 16: garage door is closed
  • 17: protect against too much sunlight
  • 19: heating system activated
  • 20: heating system change over
  • 21: not all functions are ready yet
  • 22: malfunction/needs maintainance; cannot operate
  • 23: needs service soon; still functional at the moment
Defaults to 0 (no system function)
usage optional integer Defines usage:
  • 0: undefined
  • 1: room (indoors)
  • 2: outdoors
  • 3: user interaction
Default is 0 (undefined)
group optional integer defines the primary color (group) of the input:
  • 1: yellow/light,
  • 2: grey/shadow
  • 3: blue/heating
  • 4: cyan/audio
  • 5: magenta/video
  • 6: red/security
  • 7: green/access
  • 8: black/joker
Defaults to primary device group
updateinterval optional double defines the expected update interval of this input, i.e. how often the actual state is reported by the device. Defaults to 0, which means no fixed interval
alivesigninterval optional double defines after what time with no input state update the input should be considered offline/invalid, in seconds. Defaults to 0 (meaning: no guaranteed alive reports)
hardwarename optional string a string describing the input, e.g. "door contact" or "glass break" etc. Default is "input_tyX" where X is the numeric inputtype

Sensor object in the sensors field of the init message

Field Type Description
id optional string string id, unique within the device to reference the sensor via vDC API.
sensortype optional integer Defines the type of sensor:
  • 0: undefined
  • 1: temperature in degrees celsius
  • 2: relative humidity in %
  • 3: illumination in lux
  • 4: supply voltage level in Volts
  • 5: CO (carbon monoxide) concentration in ppm
  • 6: Radon activity in Bq/m
  • 7: gas type sensor
  • 8: dust, particles <10µm in μg/m3
  • 9: dust, particles <2.5µm in μg/m3
  • 10: dust, particles <1µm in μg/m3
  • 11: room operating panel set point, 0..1
  • 12: fan speed, 0..1 (0=off, <0=auto)
  • 13: wind speed in m/s
  • 14: Power in W
  • 15: Electric current in A
  • 16: Energy in kWh
  • 17: Electric Consumption in VA
  • 18: Air pressure in hPa
  • 19: Wind direction in degrees
  • 20: Sound pressure level in dB
  • 21: Precipitation in mm/m2
  • 22: CO2 (carbon dioxide) concentration in ppm
  • 23: gust speed in m/S
  • 24: gust direction in degrees
  • 25: Generated power in W
  • 26: Generated energy in kWh
  • 27: Water quantity in liters
  • 28: Water flow rate in liters/minute
  • 29: Length in meters
  • 30: mass in grams
  • 31: time in seconds
Defaults to 0 (undefined)
usage optional integer Defines usage:
  • 0: undefined
  • 1: room (indoors)
  • 2: outdoors
  • 3: user interaction
Default is 0 (undefined)
group optional integer defines the primary color (group) of the sensor:
  • 1: yellow/light,
  • 2: grey/shadow
  • 3: blue/heating
  • 4: cyan/audio
  • 5: magenta/video
  • 6: red/security
  • 7: green/access
  • 8: black/joker
Defaults to primary device group
updateinterval optional double defines the time precision of the sensor, i.e. how quickly it reports relevant changes. For sensors with a regular polling mechanism, this actually is the expected update interval. For sensors that update only when change is detected, this denotes the timing accuray of the update.Defaults to 5 seconds
alivesigninterval optional double defines after what time with no sensor update the sensor should be considered offline/invalid, in seconds.Defaults to 0 (meaning: no guaranteed alive reports)
changesonlyinterval optional double defines the minimum time interval between reporting the same sensor value again, in seconds.Defaults to 5 minutes (300 seconds)Note that this value is only a default used for new devices. The vDC API allows to change this value later.
hardwarename optional string a string describing the sensor, e.g. "indoor temperature" or "water level" etc. Default is "sensor_tyX" where X is the numeric sensor type
min optional double minimal value, defaults to 0
max optional double maximal value, defaults to 100
resolution optional double sensor resolution, defaults to 1

Action object in actions field of the init message

Field Type Description
description optional string description text (for logs and debugging) of the action
params optional object defines the parameters of the device action

Standardaction object in standardactions field of the init message

Field Type Description
action string name of the action this standardaction is based on
title optional string title text for the standard action
params optional object defines the parameters to be used when calling action

Configuration object in configurations field of the init message

Field Type Description
id string configuration id
description string description text for the configuration

Dynamicaction object in dynamicactions field of the init message and in the dynamicAction message

Field Type Description
title string The title (device-side user-assigned string in user language) for the dynamic action
description optional string description text (for logs and debugging) of the action
params optional object defines the parameters of the device action

State object in states field of the init message

Field Type Description
description optional string description text (for logs and debugging) of the state
type, siunit, min, max... fields definition of the state, see value description fields below

Event object in events field of the init message

Field Type Description
description optional string description text (for logs and debugging) of the state
type, siunit, min, max... fields definition of the state, see value description fields below

Property object in properties field of the init message

Field Type Description
readonly optional boolean can be set to make the property read-only (from the vDC API side - the device implementation can use updateProperty to update/push the value)
type, siunit, min, max... fields definition of the property, see value description fields below

value description fields (for action parameters, states, properties)

Field Type Description
type string must be one of "numeric", "integer", "boolean", "enumeration" or "string"
siunit optional string defines the SI-unit of numeric type
default optional numeric default value according to type (not for enumerations)
min optional double minimal value for numeric and integer types
max optional double minimal value for numeric and integer types
resolution optional double resolution for numeric types
values array of strings possible values for enumeration type, default value prefixed with an exclamation mark (!).

Messages from vdcd to device(s)

vdcd sends (depending on the features selected in the init message) the messages shown in the table below.

If devices were created with a tag (which is required when creating multiple devices on a single connection), all JSON protocol messages will include the tag field, and all simple text protocol messages will be prefixed by tag plus a colon.

JSON protocol Simple protocol Description
{ 'message': 'status', 'status': s, 'errorcode': e, 'errormessage': m, 'errordomain':d, 'tag': t } OK
or
`ERROR= m
Status for init message.If ok, s is the string "ok" in the JSON protocol. m is a textual error message e is the vdcd internal error code d is the vdcd internal error domain t is the tag (only present if device was created with a tag in the init message)
{ 'message': 'channel','index': i , 'id':id , 'type':ty,'value': v, 'transition': ttime, 'dimming': dim, 'tag':t} C i = v
or with tag:
t :C i = v
Output channel index i has changed its value to v.v is a double value. The device implementation should forward the new channel value to the device's output. The JSON variant of this message additionally reports the transition time as ttime (in Seconds), a boolean dim flag indicating if the output change is due to dimming, the channel's name/idstring as id and the channel type as ty :
  • 0: undefined
  • 1: brightness for lights
  • 2: hue for color lights
  • 3: saturation for color lights
  • 4: color temperature for lights with variable white point
  • 5: X in CIE Color Model for color lights
  • 6: Y in CIE Color Model for color lights
  • 7: shade position (blinds, outside)
  • 8: shade position (curtains, inside)
  • 9: shade angle (blinds, outside)
  • 10: shade angle (curtains, inside)
  • 11: permeability (smart glass)
  • 12: airflow intensity
  • 13: airflow direction (0=undefined, 1=supply/down, 2=exhaust/up)
  • 14: airflow flap position
  • 15: ventilation louver position
t is the tag (only present if device was created with a tag in the init message)
{ 'message': 'move', 'index': i, 'direction': d, 'tag': t } MV i = d
or with tag:
t :MV i = d
When the init message has specified move=true, the vdcd can request starting or stopping movement of channel i as follows:
  • 0: stop movement
  • 1: start movement to increase channel value
  • -1: start movement to decrease channel value
t is the tag (only present if device was created with a tag in the init message)
{ 'message': 'control', 'name': n, 'value': v, 'tag': t } CTRL. n = v
or with tag:
t :CTRL. n = v
When the init message has specified controlvalues=true, the vdcd will forward control values received for the device. n is the name of the control value (such as "heatingLevel", "TemperatureZone", "TemperatureSetPoint" etc.) v is a double value t is the tag (only present if device was created with a tag in the init message)
{ 'message': 'sync', 'tag': t } SYNC
or with tag:
t :SYNC
When the init message has specified sync=true, the vdcd can request updating output channel values by sending sync. The device is expected to update channel values (using the "channel"/"C" message, see below) and then sending the synced message. t is the tag (only present if device was created with a tag in the init message)
{ 'message': 'scenecommand', 'cmd': c, 'tag': t } SCMD=c
or with tag:
t :SCMD= c
When the init message has specified scenecommands=true, the vdcd will send this message for some "special" scene calls, because not all scene call's semantics are fully represented by channel value changes alone.Currently, c can be one of the following values:
  • OFF
  • SLOW_OFF
  • MIN
  • MAX
  • INC
  • DEC
  • STOP
  • CLIMATE_ENABLE
  • CLIMATE_DISABLE
  • CLIMATE_HEATING
  • CLIMATE_COOLING
  • CLIMATE_PASSIVE_COOLING
Note that in most cases, the scene commands are already translated into channel value changes at the vDC level (e.g. MIN, MAX), so there's usually no need to do anything at the device level. STOP is a notable exception for devices that need significant time to apply values (like blinds). These should respond to the STOP scene command by immediately stopping movement and then synchonizing the actual position back using "channel"/C messages.

Operations related to multiple device configurations are only available in the JSON protocol as follows:

JSON protocol Description
{ 'message': 'setConfiguration', 'id': configid , 'tag':t } The device is requested to the configuration identified by id configid.The device implementation MUST disconnect all devices affected by the configuration change (using the bye message), and then re-connect the device(s) with new init messages describing the new configuration (number of buttons, sensors, etc.) and containing configid in the currentConfigId field.

Operations related to 'single' devices are only available in the JSON protocol as follows:

JSON protocol Description
{ 'message': 'invokeAction', 'action': a, 'params':p, 'tag': t } The action a has been invoked with parameters p.The device implementation must perform the action and then must return a confirmAction message (unless confirming actions is disabled by including the noconfirmaction field in the init message) t is the tag (only present if device was created with a tag in the init message)
{ 'message': 'setProperty', 'property': p, 'value': v, 'tag': t } The property p has been changed to value v.The device implementation should update its internal value for this property.

Messages from device(s) to vdcd

the device(s) can send (depending on the features selected in the init message) the messages shown in the table below.

If devices were created with a tag (which is required when creating multiple devices on a single connection), all JSON protocol messages must include the tag field, and all simple text protocol messages must be prefixed by tag plus a colon to identify the device.

JSON protocol Simple protocol Description
{ 'message': 'bye', 'tag': t } BYE
or with tag:
t :BYE
(external devices via TCP/IP only) The device can send this message to disconnect from the vdcd, for example when it detects its hardware is no longer accessible. Just closing the socket connection has the same effect as sending bye (in case of multiple tagged devices, closing socket is like sending bye to each device) t is the tag (only needed when device was created with a tag in the init message)
{ 'message': 'log', 'level': n , 'text':logmessage, 'tag': t } L n = logmessage
or with tag:
t :L n = logmessage
(external devices via TCP/IP only) The device can send a logmessage to the vdcd log. n is the log level (by default, levels above 5 are not shown in the log - 7=debug, 6=info, 5=notice, 4=warning, 3=error, 2=critical, 1=alert, 0=emergency) t is the tag (only needed when device was created with a tag in the init message)
{ 'message': 'channel', 'index': i, 'type': ty ,'id':id, 'value': v , 'tag':t} C i = v
or with tag:
t :C i = v
The device should send this message when its output channel with index i (or named id or typed ty , see below) has changed its value to v for another reason than having received a channel message (e.g. after initialisation, or for devices than can be controlled directly).Devices that cannot immediately detect output changes can specifiy sync=true in the init message, so the vdcd will request updating output channel values by sending sync only when these values are actually needed. The JSON variant of this message additionally allows selecting the channel by name/idstring id or type ty (instead of index i ). t is the tag (only needed when device was created with a tag in the init message)
{ 'message': 'channel_progress', 'index': i, 'type': ty ,'id':id, 'value': v , 'tag':t} P i = v
or with tag:
t :P i = v
The device can optionally send this message to report progress of a hardware transition (such as a moving blind) for its output channel with index i (or named id or typed ty , see below). The JSON variant of this message additionally allows selecting the channel by name/idstring id or type ty (instead of index i ). t is the tag (only needed when device was created with a tag in the init message)
{ 'message': 'button', 'index': i, 'id':id, 'value': v, 'tag':t} B i = v
or with tag:
t :B i = v
The device should send this message when the state of its button at index i (or named id , see below) has changed. If the button was pressed, v must be set to 1, if the button was released, v must be set to 0.
To simulate a button press+release with a single message, set v to the press duration in milliseconds.
To directly simulate a single, double, triple, or quadruple click, -1, -2, -3, or -4 can be passed for v, as well as -11 for start of holding down the button and -10 for releasing the button. Note that mixing direct clicks (negative values) and button state reporting (positive values) should not be mixed in use for the same button!
t is the tag (only needed when device was created with a tag in the init message)The JSON variant of this message allows selecting the button by name/idstring id (instead of index i ).
{ 'message': 'input', 'index': i, 'id': id, 'value': v , 'tag': t } I i = v
or with tag:
t :I i = v
The device should send this message when the state of its input at index i (or named id , see below) has changed. If the input has changed to active v must be set to 1, if the input has changed to inactive, v must be set to 0. To explicitly signal that the value is unknown/not available at this time, set v to the string undefined (simple) or to the NULL value (JSON). t is the tag (only needed when device was created with a tag in the init message). The JSON variant of this message allows selecting the input by name/idstring id (instead of index i ).
{ 'message': 'sensor', 'index': i, 'id':id, 'value': v ,'tag':t } S i = v
or with tag:
t :S i = v
The device should send this message when the value of its sensor at index i (or named id , see below) has changed. v is the new value (double) and should be within the range specified with min and max in the init message. To explicitly signal that the value is unknown/not available at this time, set v to the string undefined (simple) or to the NULL value (JSON). t is the tag (only needed when device was created with a tag in the init message). The JSON variant of this message allows selecting the sensor by name/idstring id (instead of index i ).
{ 'message': 'synced', 'tag': t } SYNCED
or with tag:
t :SYNCED
The device must send this message after receiving sync and having updated output channel values. t is the tag (only needed when device was created with a tag in the init message)

Some more specialised operations, e.g. those relating to 'Single Devices', are only available in the JSON protocol as follows:

JSON protocol Description
{ 'message': 'opstate', 'level': lvl , 'text':txt } Sets the operation state of the device. lvl is the "health" level, from -1 (unknown) to 0 (bad) to 100 (perfect). txt is a short keyword for the operating status, e.g. "Low Bat". Only one of the two pieces of information can be specified. t is the tag (only present if the device was created with a tag in the init message)
{ 'message': 'confirmAction', 'action': a , 'errorcode': ec, 'errortext': et , 'tag':t } Unless confirming actions is disabled by including the noconfirmaction field in the init message, the device must send this message to confirm the execution (or failure) of action a that has been invoked before.It can return a status code in ec , which must be 0 for successful execution or another value indicating an error. et can be used to supply an error text. t is the tag (only present when device was created with a tag in the init message)
{ 'message': 'updateProperty', 'property': p, 'value':v, 'push':push, 'tag': t } The device can send this message to update the value v of the property p , as seen from the vdc API.If the optional push boolean value is set, the property change will also be pushed upstream.Note it is possible to just push the current property value without changing its value by omitting value, only specifying push. t is the tag (only present when device was created with a tag in the init message)
{ 'message': 'pushNotification', 'statechange':{ s:v }, 'events': [e1,e2,...], 'tag': t } The device can use this message to push state changes and events.The statechange field is an optional object assinging a new value v to a state s , the events field is an optional array of event ids ( e1,e2,... ) to be pushed along the state change (or by themselves if the statechange field is missing). t is the tag (only present when device was created with a tag in the init message)
{ 'message': 'dynamicAction', 'changes': { id:actiondesc, ... }, 'tag': t } The device can use this message to add, change or remove dynamic actions while the device is already operating.The changes field is a JSON object, containing one or multiple actions identified by their id s and described by an actiondesc (same format as dynamicAction in the init message, see above). If a dynamic action is to be removed, pass null for actiondesc. t is the tag (only present when device was created with a tag in the init message)