Here's what I'm hearing:
-
delayBetween
is a HE-provided method that will insert necessary delays between commands.
-
delayBetweenLog
is a custom method that works in its place. It has a series of conditionals that selectively introduce only appropriate delays. It also logs information about the command set that results. It has special handling because the getRefreshCommands
are proprietary, and sent as HubActions rather than the usual strings.
-
getRefreshCommands
/addRefreshCommands
encapsulates the proprietary magic commands that tell the PE653 to refresh the controls. It's added to any commands that will result in a state change that needs to be reflected, thus:
delayBetweenLog(addRefreshCmds(someActionThatGeneratesCommands()))
Right so far?
If so, I'm considering the following:
- Create a
executeCommands
command that takes an optional refreshAfter
argument. It will take the incoming command set as a list of Strings (resulting from format()
, optionally append the refresh commands, log the result, and then call the stock delayBetween
.
It could take HubActions, but I’m not seeing the benefit (yet). Instead I make the commands generated in setChanState
get format()
ted before they get returned, so strings are the lingua franca. This captures what @chuck.schwer suggested, while still drawing nice lines around the proprietary stuff @keithriley has so carefully dug up, but using the stock methods.
I did this.
private List refreshCommandStrings() { ["910005400102870301", "910005400101830101"] }
private List refreshCommandHubitatActions() { refreshCommandStrings().collect { new hubitat.device.HubAction(it) } }
private List executeCommands(commands, refreshControls = false) {
log("DEBUG", 2, "+++++ executeCommands")
logCommandList(commands)
if (refreshControls) {
commands += refreshCommandStrings()
}
log("DEBUG", 2, "----- executeCommands final set:")
logCommandList(commands)
delayBetween(commands)
}
This means that off2
now looks like:
def List off2() { executeCommands(setChanState(2, 0), true) }
This works, sort of! In that it generates a list of commands, including the refresh commands. A whole lot of things happen! Unfortunately, turning off is not one of them.
executeCommands
correctly inserts the ‘refresh’ commands (the below, reading from the bottom, shows the original command set to turn off switch 2, and the final result, with the additional 'refresh' commands):
dev:1302018-10-11 21:06:50.492: debug - Events as sent:
0: 600625010200
1: 910005400102870301
2: 910005400101830101
dev:1302018-10-11 21:06:50.490: debug ----- executeCommands final set:
dev:1302018-10-11 21:06:50.488: debug - Events as sent:
0: 600625010200
And then a whole ton of events get sent back into the DTH, meaning the controller actually did something!
However, note how the code decides “event UNNECESSARY” - the state is already set correctly. But, it’s not. The response in the 84 command from the device is that the switch is still on. But the command transmitted was to turn it off.
…
dev:1302018-10-11 21:06:50.969: debug <<<<< Event unnecessary. name:switch2 evt: "on" ==> dev:(on)
dev:1302018-10-11 21:06:50.966: trace - 1: Map: [name:switch2, value:on, isStateChange:true, displayed:true, descriptionText:(switch2 set to on)]
dev:1302018-10-11 21:06:50.965: trace - l -> [name:switch2, value:on, isStateChange:true, displayed:true, descriptionText:(switch2 set to on)]
dev:1302018-10-11 21:06:50.964: debug <<<<< Event unnecessary. name:switch1 evt: "off" ==> dev:(off)
dev:1302018-10-11 21:06:50.959: trace - 0: Map: [name:switch1, value:off, isStateChange:true, displayed:true, descriptionText:(switch1 set to off)]
dev:1302018-10-11 21:06:50.958: trace - l -> [name:switch1, value:off, isStateChange:true, displayed:true, descriptionText:(switch1 set to off)]
dev:1302018-10-11 21:06:50.951: debug +++++ delayBetweenLog parm[9] dly=1000 responseFlg=true
…
dev:1302018-10-11 21:06:50.832: debug ..... createMultipleEvents( endpoint:2, name:switch2, externalParm:255, myParm:on)
dev:1302018-10-11 21:06:50.831: debug <<<<< Child Event unnecessary. name:07-ep1:switch1 evt: "off" ==> dev (off)
dev:1302018-10-11 21:06:50.800: debug ..... createMultipleEvents( endpoint:1, name:switch1, externalParm:0, myParm:off)
dev:1302018-10-11 21:06:50.793: debug ManufacturerProprietary event, [1]:40 [4]:84 payload: 05 40 02 02 84 00 00 00 02 00 00 01 5B 00 00 14 38 00 00 00 00 03 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
dev:1302018-10-11 21:06:50.786: trace <<< Incoming: [zw device: 07, command: 9100, payload: 05 40 02 02 84 00 00 00 02 00 00 01 5B 00 00 14 38 00 00 00 00 03 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
Here we see createMultipleEvents
reporting that the externalParm
of switch2 is on, despite 'off' having just been sent.
I interpret this as the 84 command reporting that switch 2 is on (which is correct, the pump is running; payload[SWITCHES_84] & 2
is 1
) - which is unfortunate, because I told it to turn off.
From here unsurprisingly nothing else happens.
I think I interpret this as 600625010200
not being the correct code to turn off switch2
.
# off
setChanState(5, 0) 0: 600625010500
setChanState(4, 0) 0: 600625010400
setChanState(3, 0) 0: 600625010300
setChanState(2, 0) 0: 600625010200
setChanState(1, 0) 0: 600625010100
# on
setChanState(5, 255) 0: 6006250105FF
setChanState(4, 255) 0: 6006250104FF
setChanState(3, 255) 0: 6006250103FF
setChanState(2, 255) 0: 6006250102FF
setChanState(1, 255) 0: 6006250101FF
These are refreshingly consistent and therefore plausible. But they don't make anything happen.
So now I find myself wondering - is v3.3 of the firmware my problem? Because this feels like solid communication, which falls apart when it hits the device.
Just to be thorough, here's what setChanState
looks like:
private List setChanState(ch, on) {
log("DEBUG", 2, "+++++ setChanState($ch, $on)")
def cmds =[
zwave.multiInstanceV1.multiInstanceCmdEncap(instance: ch).encapsulate(zwave.switchBinaryV1.switchBinarySet(switchValue: (on ? 0xFF : 0))).format() ,
]
}
Oh! And, when I manually switch the device off, I get an 84 command reporting that switch2
is now off
.:
dev:1302018-10-11 21:47:18.069:debug - Events as sent:
0: [name:switch2, value:off, isStateChange:true, displayed:true, descriptionText:(switch2 set to off)]
1: [name:airTempFreeze, value:0, unit:F, displayed:true, isStateChange:true]
2: [name:airTempSolar, value:0, unit:F, displayed:true, isStateChange:true]
3: [name:clock, value:21:37, displayed:false, descriptionText:PE653 Clock: 21:37]
So the issue really appears to be the command that's being sent to the device.