Error while overriding default z-wave door lock operation report

I am encountering some errors while trying to handle z-wave DoorLock operation report, can someone help me solve this.

I observed that the lock is throwing a operation report for every hour about the lock status and this event is not captured by the “Events” tab in the my.smartthings.com, So I thought to throw my own event inside the operations report handler but I ran into some errors.

Error:

min driver  AQ-1-Lock thread encountered error: [string "st/dispatcher.lua"]:267: Error encountered while processing event for <ZwaveDevice: f458afba-55a1-41be-a037-5d3627dfe5d5 [06] (AQ-1-Lock)>:
    arg1: {_module={CAPABILITIES_GET=7, CAPABILITIES_REPORT=8, CONFIGURATION_GET=5, CONFIGURATION_REPORT=6, CONFIGURATION_SET=4, CapabilitiesGet={construct=function: 0x262a660}, CapabilitiesGetV4={_defaults=function: 0x2618d30, _set_defaults=function: 0x25fce28, _set_reflectors=function: 0x25fcf70, _template=function: 0x25fcd98, deserialize=function: 0x25fbd68, init=function: 0x2612c90, serialize=function: 0x2617008}, CapabilitiesReport={construct=function: 0x262a618}, CapabilitiesReportV4={_defaults=function: 0x2619200, _set_defaults=function: 0x25fcc98, _set_reflectors=function: 0x261bdc0, _template=function: 0x2618da0, deserialize=function: 0x25fc3e8, init=function: 0x2624b38, serialize=function: 0x2619080}, ConfigurationGet={construct=function: 0x2615160}, ConfigurationGetV1={_defaults=function: 0x25fe028, _set_defaults=function: 0x2616c38, _set_reflectors=function: 0x25ff658, _template=function: 0x2616fe0, deserialize=function: 0x2616f00, init=function: 0x2616ba0, serialize=function: 0x25ffbb0}, ConfigurationReport={construct=function: 0x2625b38}, ConfigurationReportV1={_defaults=function: 0x25fdf30, _set_defaults=function: 0x26006a8, _set_reflectors=function: 0x2615e58, _template=function: 0x25fe5f8, deserialize=function: 0x25ff8f8, init=function: 0x2615ea0, serialize=function: 0x26030d8}, ConfigurationReportV4={_defaults=function: 0x2617898, _set_defaults=function: 0x2617810, _set_reflectors=function: 0x25f6070, _template=function: 0x25fbb10, deserialize=function: 0x2602c60, init=function: 0x26093c8, serialize=function: 0x2618af8}, ConfigurationSet={construct=function: 0x26151a8}, ConfigurationSetV1={_defaults=function: 0x25ffe30, _set_defaults=function: 0x25feb58, _set_reflectors=function: 0x26092f8, _template=function: 0x2616dd8, deserialize=function: 0x2617190, init=function: 0x25e2a48, serialize=function: 0x25f0790}, ConfigurationSetV4={_defaults=function: 0x25cfbb0, _set_defaults=function: 0x2600988, _set_reflectors=function: 0x2615b78, _template=function: 0x25ff2f8, deserialize=function: 0x2618bc8, init=function: 0x26134d0, serialize=function: 0x26182e8}, OPERATION_GET=2, OPERATION_REPORT=3, OPERATION_SET=1, OperationGet={construct=function: 0x2615088}, OperationGetV1={_defaults=function: 0x25f2048, _set_defaults=function: 0x25fd5b0, _set_reflectors=function: 0x2617618, _template=function: 0x25e3508, deserialize=function: 0x2607238, init=function: 0x2601f78, serialize=function: 0x260e938}, OperationReport={construct=function: 0x2614538}, OperationReportV1={_defaults=function: 0x25dc888, _set_defaults=function: 0x25fbee8, _set_reflectors=function: 0x260be30, _template=function: 0x25fc098, deserialize=function: 0x25f0980, init=function: 0x2603ba0, serialize=function: 0x25d9a28}, OperationReportV3={_defaults=function: 0x2618498, _set_defaults=function: 0x2600258, _set_reflectors=function: 0x2611d48, _template=function: 0x2618818, deserialize=function: 0x25fd400, init=function: 0x2615fc0, serialize=function: 0x25fbf70}, OperationSet={construct=function: 0x2624a18}, OperationSetV1={_defaults=function: 0x262ab38, _set_defaults=function: 0x260da10, _set_reflectors=function: 0x2611b38, _template=function: 0x26066d0, deserialize=function: 0x262a900, init=function: 0x2607380, serialize=function: 0x262b528}, _commands={"OPERATION_SET", "OPERATION_GET", "OPERATION_REPORT", "CONFIGURATION_SET", "CONFIGURATION_GET", "CONFIGURATION_REPORT", "CAPABILITIES_GET", "CAPABILITIES_REPORT"}, _lut={{RecursiveTable: OperationSet, RecursiveTable: OperationGet, RecursiveTable: OperationReport, RecursiveTable: ConfigurationSet, RecursiveTable: ConfigurationGet, RecursiveTable: ConfigurationReport, RecursiveTable: CapabilitiesGet, RecursiveTable: CapabilitiesReport}, {RecursiveTable: OperationSetV1, RecursiveTable: OperationGetV1, RecursiveTable: OperationReportV1, RecursiveTable: ConfigurationSetV1, RecursiveTable: ConfigurationGetV1, RecursiveTable: ConfigurationReportV1}, {RecursiveTable: OperationSetV1, RecursiveTable: OperationGetV1, RecursiveTable: OperationReportV1, RecursiveTable: ConfigurationSetV1, RecursiveTable: ConfigurationGetV1, RecursiveTable: ConfigurationReportV1}, {RecursiveTable: OperationSetV1, RecursiveTable: OperationGetV1, RecursiveTable: OperationReportV3, RecursiveTable: ConfigurationSetV1, RecursiveTable: ConfigurationGetV1, RecursiveTable: ConfigurationReportV1}, {RecursiveTable: OperationSetV1, RecursiveTable: OperationGetV1, RecursiveTable: OperationReportV3, RecursiveTable: ConfigurationSetV4, RecursiveTable: ConfigurationGetV1, RecursiveTable: ConfigurationReportV4, RecursiveTable: CapabilitiesGetV4, RecursiveTable: CapabilitiesReportV4}}, _reflect_door_lock_mode={"DOOR_UNSECURED", "DOOR_UNSECURED_WITH_TIMEOUT", "DOOR_UNSECURED_FOR_INSIDE_DOOR_HANDLES", "DOOR_UNSECURED_FOR_INSIDE_DOOR_HANDLES_WITH_TIMEOUT", "DOOR_UNSECURED_FOR_OUTSIDE_DOOR_HANDLES", "DOOR_UNSECURED_FOR_OUTSIDE_DOOR_HANDLES_WITH_TIMEOUT", "DOOR_LOCK_STATE_UNKNOWN", "DOOR_SECURED"}, _reflect_operation_type={"CONSTANT_OPERATION", "TIMED_OPERATION"}, _strict=false, door_lock_mode={DOOR_LOCK_STATE_UNKNOWN=254, DOOR_SECURED=255, DOOR_UNSECURED=0, DOOR_UNSECURED_FOR_INSIDE_DOOR_HANDLES=16, DOOR_UNSECURED_FOR_INSIDE_DOOR_HANDLES_WITH_TIMEOUT=17, DOOR_UNSECURED_FOR_OUTSIDE_DOOR_HANDLES=32, DOOR_UNSECURED_FOR_OUTSIDE_DOOR_HANDLES_WITH_TIMEOUT=33, DOOR_UNSECURED_WITH_TIMEOUT=1}, init=function: 0x25e21a8, operation_type={CONSTANT_OPERATION=1, TIMED_OPERATION=2}}, _reflect={cmd_class=function: 0x26c6b88, cmd_id=function: 0x26aa638, encap=function: 0x26aa658}, args={_reflect={door_lock_mode=function: 0x26c7b78}, door_condition=2, door_lock_mode=1, inside_door_handles_mode=0, lock_timeout_minutes=254, lock_timeout_seconds=254, outside_door_handles_mode=0}, cmd_class=98, cmd_id=3, dst_channels={}, encap=3, payload="\x01\x00\x02\xFE\xFE", src_channel=0, version=1}
"[string "st/capabilities/init.lua"]:235: Invalid value for Lock.lock value: {value=1} error: Given number for LockState. Required type is a string"
zwave_handlers = {
    [cc.DOOR_LOCK] = {
      [DoorLock.OPERATION_REPORT] = handle_operation_report
    }
}

Use :pretty_print() or utils.stringify to dump the cmd.

Also you won’t see the events in the history unless the values change or they’re forced to be printed. Why would you want to print duplicate statuses?

In some cases the device is shown online event when it’s not connected to the hub. I wanted to keep track of these events which were being emitted in one hour intervals in order to determine if my device is truly online or not. Is there any other way to check?

Hi, @Akhil_Changal
You mentioned it was an operation report. So, is it about the device sending a report on its current state every hour?

I got confused about your other description of:

By “not connected to the hub”, do you mean it doesn’t have batteries to operate? If so, the device will be marked offline when it doesn’t respond to the pings from the hub. So it might take a while to be marked as offline.

Sorry for taking so long to reply back. I really appreciate that the community is replying back so quick.

As @RBoy pointed out the issue was with the print statement. Now I am able to emit my event from operation report handler as expected. Thanks for the help.

@nayelyz yes it is an operation report of DoorLock command class in z-wave libs that is occurring at 1hr intervals.

I have two locks say L1 and L2 and a hub say H. Initially these 3 devices are connected from same physical location and network A. so these 3 devices are under the same location in the smartthings app. Now L1 is at physical location A and L2 is at physical location B. When I plug the hub at physical location A the L1 is shown online and L2 is shown offline(the expected behavior). When I disconnect the hub 3 devices are shown offline. Now when I plug the same hub at physical location B the L1 is shown online and L2 is shown online(L1 should be offline).

This shows the uncertainty in the online status shown by the smartthings app. I wanted to leverage the default behavior of the lock that it receives operation report and emits lock status at 1hr intervals but these emitted events are not found in the events tab of my.smarthings.com. So I am trying to emit my custom event whenever there is a operation report.

At the end what I wanted to know is is there a better way to know or detect if my device is online or not?

Once again I want to thank you for the replies.

Are the L1 and L2 locks the exact same model?
If the L1 lock is never going offline even though the Hub is no longer in the network, it might be because it isn’t enrolled for a health check for some reason.
About the event every hour, you mentioned you defined a new handler in a Custom driver, right? Are you sending a capability event from it or you’re currently only printing the event?

In the log you sent above, I don’t see a specific value, for example, the SmartThings default handler checks the “Lock mode”:

local function door_lock_operation_report_handler(driver, device, cmd)
  local event
  if (cmd.args.door_lock_mode == DoorLock.door_lock_mode.DOOR_SECURED) then
    event = capabilities.lock.lock.locked()
  elseif (cmd.args.door_lock_mode == DoorLock.door_lock_mode.DOOR_UNSECURED_WITH_TIMEOUT) then
    event = capabilities.lock.lock.unlocked_with_timeout()
  elseif (cmd.args.door_lock_mode == DoorLock.door_lock_mode.DOOR_LOCK_STATE_UNKNOWN) then
    event = capabilities.lock.lock.unknown()
  else
    -- fail to unlocked just to be safe
    event = capabilities.lock.lock.unlocked()
  end

The event won’t appear in the “Events” tab unless there’s a status change in a capability.

Yes, both L1 and L2 are of same models.

As you said the events aren’t appearing in the Events tab as the status is same. So whenever there is a operation report I am emitting a event for my custom capability status like beat 1, beat 2 and so on. So that when I stop receiving these beats I know the lock is offline.

ok, it seems you found a workaround.
If it helps, we can force an event to be considered a status change in a capability even though the attribute value hasn’t changed with the property state_change=true (here’s more info about this).

1 Like