jperkin / node-openzwave

node.js interface to libopenzwave
Other
110 stars 54 forks source link

Extending write support #13

Closed zonak closed 10 years ago

zonak commented 10 years ago

The current write support allows us to use binary and multilevel switches by utilizing switchOn, switchOff and setLevel. But these methods are tied to specific classes such as 0x20 and 0x26.

We have a lot of use cases where we need to write to other classes as well. A good simple example is configuration - a lot of the devices have configuration options that we cannot utilize without the write support for it. For example, the Aeotec Smart Energy Switch has the following configuration class (0x70):

<CommandClass id="112" name="COMMAND_CLASS_CONFIGURATION" version="1" request_flags="4">
  <Instance index="1" />
  <Value type="list" genre="config" instance="1" index="1" label="Report type" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="1" vindex="0" size="1">
    <Help>Defines the contents of Multilevel Sensor Report after Multilevel Sensor Get received.</Help>
    <Item label="Power" value="0" />
    <Item label="Voltage" value="1" />
  </Value>
  <Value type="short" genre="config" instance="1" index="2" label="Blinking behavior" units="" read_only="false" write_only="true" verify_changes="true" poll_intensity="0" min="0" max="65535" value="0">
    <Help>This is actually a double byte value. The LSB defines the total time the device needs to blink in seconds. The MSB defines the on/off interval of the blink in tenths of seconds.</Help>
  </Value>
  <Value type="list" genre="config" instance="1" index="80" label="Notification status" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="0" vindex="0" size="1">
    <Help>Enables automatic notifications to associated devices whenever there is a state change.</Help>
    <Item label="None" value="0" />
    <Item label="Hail" value="1" />
    <Item label="Basic" value="2" />
  </Value>
  <Value type="bool" genre="config" instance="1" index="90" label="Enable Wattage Reports" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="0" value="False">
    <Help>Enable/disable Wattage threshold and percent.</Help>
  </Value>
  <Value type="short" genre="config" instance="1" index="91" label="Wattage threshold" units="watts" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="32000" value="50">
    <Help>The minimum change in wattage for a report to be sent.</Help>
  </Value>
  <Value type="byte" genre="config" instance="1" index="92" label="Wattage threshold percent" units="%" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="99" value="10">
    <Help>Minimum change in percent of wattage to send a report.</Help>
  </Value>
  <Value type="button" genre="config" instance="1" index="100" label="Default Group Reports" units="" read_only="false" write_only="true" verify_changes="true" poll_intensity="0" min="0" max="0" affects="101,102,103">
    <Help>Set report types for groups 1, 2 and 3 to default. Reverts to 0 after set.</Help>
  </Value>
  <Value type="int" genre="config" instance="1" index="101" label="Report type G1" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="-2147483648" max="2147483647" value="8">
    <Help>Defines the type of report sent for reporting group 1. 2 is multisensor report. 4 is meter report for watts. 8 is meter report for kilowatts. Value 1 (msb) Reserved Value 2 Reserved Value 3 Reserved Value 4 (lsb) bits 7-4 reserved bit 3 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don&apos;t send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don&apos;t send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don&apos;t send(0) Multilevel Sensor Report Command(wattage) automatically.</Help>
  </Value>
  <Value type="int" genre="config" instance="1" index="102" label="Report type G2" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="-2147483648" max="2147483647" value="0">
    <Help>Defines the type of report sent for reporting group 2. 2 is multisensor report. 4 is meter report for watts. 8 is meter report for kilowatts. Value 1 (msb) Reserved Value 2 Reserved Value 3 Reserved Value 4 (lsb) bits 7-4 reserved bit 3 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don&apos;t send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don&apos;t send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don&apos;t send(0) Multilevel Sensor Report Command(wattage) automatically.</Help>
  </Value>
  <Value type="int" genre="config" instance="1" index="103" label="Report type G3" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="-2147483648" max="2147483647" value="0">
    <Help>Defines the type of report sent for reporting group 3. 2 is multisensor report. 4 is meter report for watts. 8 is meter report for kilowatts. Value 1 (msb) Reserved Value 2 Reserved Value 3 Reserved Value 4 (lsb) bits 7-4 reserved bit 3 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don&apos;t send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don&apos;t send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don&apos;t send(0) Multilevel Sensor Report Command(wattage) automatically.</Help>
  </Value>
  <Value type="button" genre="config" instance="1" index="110" label="Default Group Time" units="" read_only="false" write_only="true" verify_changes="true" poll_intensity="0" min="0" max="0" affects="111,112,113">
    <Help>Set time interval for sending reports for groups 1, 2 and 3 to default.</Help>
  </Value>
  <Value type="int" genre="config" instance="1" index="111" label="Send interval G1" units="seconds" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="65535" value="600">
    <Help>Defines the time interval when the defined report for group 1 is sent.</Help>
  </Value>
  <Value type="int" genre="config" instance="1" index="112" label="Send interval G2" units="seconds" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="65535" value="600">
    <Help>Defines the time interval when the defined report for group 2 is sent.</Help>
  </Value>
  <Value type="int" genre="config" instance="1" index="113" label="Send interval G3" units="seconds" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="65535" value="600">
    <Help>Defines the time interval when the defined report for group 3 is sent.</Help>
  </Value>
  <Value type="short" genre="config" instance="1" index="254" label="Device tag" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="65535" value="0">
    <Help>Device tag.</Help>
  </Value>
  <Value type="button" genre="config" instance="1" index="255" label="Reset device" units="" read_only="false" write_only="true" verify_changes="true" poll_intensity="0" min="0" max="0">
    <Help>Reset to the default configuration.</Help>
  </Value>
</CommandClass>

where a lot of the values have writing enabled.

Configuration is just one example, but the support to writing to different classes would be very useful in a lot of other cases.

Is there a way to extend the write support by implementing a more generic solution. Something like a method that would accept the following parameters:

All the values even have attributes that can validate whether writing is allowed or what type of value is expected that can be used for a validation step. This can obviously be done as a second phase but the basic write support would add great value.

If we have something like this in place then methods like switchOn can be modified as abstraction over the generic write support.

mrose17 commented 10 years ago

just to chime in - @zonak is doing the heavy lifting on the zwave support for @TheThingSystem and its turning out pretty well. my hope is that we'll have a dozen or so classes implemented by year's end!

but, we need a more generic call to avoid a proliferation of device-specific calls, e.g., meterThis(), meterTat(), windowShadesScrollLeft(), windowShadesUpAndDownUntilAnnoyed(), etc.

jperkin commented 10 years ago

Ok, try 0.0.29 with e.g. zwave.setValue(nodeid, 0x70, 90, true);

zonak commented 10 years ago

Hi Jonathan,

I was able to test with 0.0.29 and use setValue to turn a device on and off but going through the device data I stumbled upon a case like this:

<CommandClass id="39" name="COMMAND_CLASS_SWITCH_ALL" version="1" request_flags="4">
  <Instance index="1" />
  <Value type="list" genre="system" instance="1" index="0" label="Switch All" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="0" vindex="3" size="1">
    <Item label="Disabled" value="0" />
    <Item label="Off Enabled" value="1" />
    <Item label="On Enabled" value="2" />
    <Item label="On and Off Enabled" value="255" />
  </Value>
</CommandClass>

which is of a type list where we are not setting a value attribute but a vindex one.

This led me to look around a little bit more and saw these combinations of value types and attribute names:

For the most part, they all have value attributes with the exception of list which has a vindex attribute and button which I am not sure how to handle, I guess we can try and do some research.

zonak commented 10 years ago

I think we should reopen this issue just so we have something to go by ...

In addition to vindex not being supported for writing, the propagation of this field when reading out information from a device is not being handled as well.

For example, if we peek into zwcfg.xml for an example we can see the following:

<CommandClass id="39" name="COMMAND_CLASS_SWITCH_ALL" version="1" request_flags="4">
  <Instance index="1" />
  <Value type="list" genre="system" instance="1" index="0" label="Switch All" units="" read_only="false" write_only="false" verify_changes="true" poll_intensity="0" min="0" max="0" vindex="3" size="1">
    <Item label="Disabled" value="0" />
    <Item label="Off Enabled" value="1" />
    <Item label="On Enabled" value="2" />
    <Item label="On and Off Enabled" value="255" />
  </Value>
</CommandClass>

this is an example of a list type value with a vindex field, but when there is a value changed event fired, the information we are getting is:

{ type: 'list',
  genre: 'system',
  instance: 1,
  index: 0,
  label: 'Switch All',
  units: '',
  read_only: false,
  write_only: false,
  min: 0,
  max: 0,
  value: 0 }

As we can see in the example we are getting a default value of 0 but what we really need to get is a value of 3 for vindex or maybe something like the label from the list.

Hope this information helps.

ekarak commented 10 years ago

We also need the _instance part (for multi-instance devices such as the double-relay Fibaro FGS-221) in values...