Possible to pass physicalgraph.device.HubAction object into zwave.securityV1.securityMessageEncapsulation().encapsulate() method?

Hopefully, you shouldn’t need to do this anymore if you’ve seen my reply here.

However, the solution to this problem is easily discovered with a simple experiment:

def cmd = zwave.associationV2.associationRemove(groupingIdentifier:2, nodeId: [])
log.debug ("Command: ${cmd.format()}") 
// Outputs: "Command: 850402"
def secCmd = zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd)
log.debug ("Secure Command: ${secCmd.format()}")
// Outputs: "Secure Command: 988100850402"

Again, with another type of command:

def cmd = zwave.basicV1.basicSet(value: 0xFF)
log.debug ("Command: ${cmd.format()}") 
// Outputs: "Command: 2001FF"
def secCmd = zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd)
log.debug ("Secure Command: ${secCmd.format()}")
// Outputs: "Secure Command: 9881002001FF"

We can see that securityMessageEncapsulation() merely adds three bytes (98 81 00) to the front of the raw command. Looking up the definition of COMMAND_CLASS_SECURITY in the Z-Wave public spec…

… we can guess the meaning of the bytes:

  • 0x98 = COMMAND_CLASS_SECURITY
  • 0x81 = SECURITY_MESSAGE_ENCAPSULATION
  • 0x00 = Presumably this is a placeholder for the ‘Initialization Vector’ bytes…?
  • The remaining bytes are then the encapsulated command. I’m guessing the actual security encapsulation must only occur after the raw command is returned from parse().

In conclusion, if you want to build a raw command string and send it securely, simply prepend “988100” to the beginning of the raw command before passing to HubAction(). E.g. :

def unsecuredCmd = "8E0101000101"
cmds << physicalgraph.device.HubAction( "988100" + unsecuredCmd )

HTH, Z