Help needed writing test for Alarms commands ResetAllCommands and ResetAlarm

Hi,

I am writing an edge driver for a switch with integrated temperature control.
The temperature is provided by ‘DeviceTemperatureConfiguration.attributes.CurrentTemperature’. When the temperature is higher than 70°C, ‘Alarm.client.commands.Alarm’ sends code ‘0x86’ for overheating alarm. When I receive this alarm, I use the temperatureAlert capability to change it to the ‘heat’ state otherwise the state is ‘cleared’. Unfortunately, the alarm_code is not cleared automatically, so I have to reset it with ResetAlarm() or ResetAllAlarms(), which I do in the function below. If the value is below 70°C and the TamperAlert is still ‘heat’ then send a ResetAlarm() or ResetAllAlarms().

local alarm_handler = function(driver, device, zb_rx)
  if (zb_rx.body.zcl_body.alarm_code.value == 0x86) then
    device:emit_event(capabilities.temperatureAlarm.temperatureAlarm('heat'))
  else
    device:emit_event(capabilities.temperatureAlarm.temperatureAlarm('cleared'))
  end
end

local temperature_handler = function(driver, device, value, zb_rx)
  local temp_alarm = device:get_latest_state("main", capabilities.temperatureAlarm.ID,
    capabilities.temperatureAlarm.temperatureAlarm.NAME, 'cleared')
  device:emit_event(capabilities.temperatureMeasurement.temperature({ value = value.value, unit = 'C' }))
  if value.value < 70 and temp_alarm == 'heat' then
    device:send(Alarm.server.commands.ResetAllAlarms(device))
    --device:send(Alarm.commands.ResetAlarm(device,0x86, 0x0702))
  end
end

// Zigbee handlers

zigbee_handlers = {
    cluster = {
      [Alarm.ID] = {
        [Alarm.client.commands.Alarm.ID] = alarm_handler
      }
    },
    attr = {
[...]={},
      [DeviceTemperatureConfiguration.ID] = {
        [DeviceTemperatureConfiguration.attributes.CurrentTemperature.ID] = temperature_handler
      }
    }
  },

The part of the test is like this

test.register_coroutine_test(
  "Temperature handled",
  function()
    test.socket.zigbee:__queue_receive({
      mock_device.id,
      DeviceTemperatureConfiguration.attributes.CurrentTemperature:build_test_attr_report(mock_device, 44)
    })
    test.socket.capability:__expect_send(
      mock_device:generate_test_message("main",
        capabilities.temperatureMeasurement.temperature({ value = 44, unit = "C" }))
    )
  end
)

test.register_coroutine_test(
  "Temperature handled",
  function()
    test.socket.zigbee:__queue_receive({
      mock_device.id,
      DeviceTemperatureConfiguration.attributes.CurrentTemperature:build_test_attr_report(mock_device, 70)
    })
    test.socket.capability:__expect_send(
      mock_device:generate_test_message("main",
        capabilities.temperatureMeasurement.temperature({ value = 70, unit = "C" }))
    )
    test.socket.zigbee:__queue_receive({
      mock_device.id,
      Alarm.client.commands.Alarm.build_test_rx(mock_device, 0x86, 0x0702)
    })
    test.socket.capability:__expect_send(
      mock_device:generate_test_message("main", capabilities.temperatureAlarm.temperatureAlarm.heat())
    )

    test.wait_for_events()

    test.socket.zigbee:__queue_receive({
      mock_device.id,
      DeviceTemperatureConfiguration.attributes.CurrentTemperature:build_test_attr_report(mock_device, 65)
    })
    test.socket.capability:__expect_send(
      mock_device:generate_test_message("main",
        capabilities.temperatureMeasurement.temperature({ value = 65, unit = "C" }))
    )
    --[[ test.socket.zigbee:__expect_send({
      mock_device.id,
      Alarm.server.commands.ResetAlarm.build_test_rx(mock_device, 134, 0x0702)
    }) ]]

    test.socket.zigbee:__expect_send({
      mock_device.id,
      Alarm.server.commands.ResetAllAlarms.build_test_rx(mock_device)
    })
  end
)

For both cases ResetAlarm() and ResetAllAlarms() I seem to get the same error in the CLI:

ResetAllAlarms()

Running test "Temperature handled" (1 of 2)
-------------------------------------------
TRACE || Setup driver zigbee_switch with lifecycle handlers:
DeviceLifecycleDispatcher: zigbee_switch
  default_handlers:
    doConfigure:
    driverSwitched:
    infoChanged:
    init:
...
TRACE || Zigbee Device: 00000000-1111-2222-3333-000000000001
Manufacturer: AEOTEC Model: ZGA002
        [1]: OnOff
DEBUG || driver device thread event handled
TRACE || Received event with handler _resync
TRACE || Found DeviceLifecycleDispatcher handler in zigbee_switch -> Switch
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: DeviceTemperatureConfiguration >, lqi: 0x00, rssi: 0, body_length: 0x0008, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x00, seqno: 0x00, ZCLCommandId: 0x0A >, < ReportAttribute || < AttributeRecord || AttributeId: 0x0000, DataType: Int16, CurrentTemperature: 44 > > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterAttributeValueHandler: cluster: DeviceTemperatureConfiguration, attribute: CurrentTemperature
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"unit":"C","value":44},"capability_id":"temperatureMeasurement","attribute_id":"temperature"}
DEBUG || Switch device thread event handled
PASSED


Running test "Temperature handled" (2 of 2)
-------------------------------------------
TRACE || Setup driver zigbee_switch with lifecycle handlers:
DeviceLifecycleDispatcher: zigbee_switch
  default_handlers:
    doConfigure:
    driverSwitched:
    infoChanged:
    init:
...
TRACE || Zigbee Device: 00000000-1111-2222-3333-000000000001
Manufacturer: AEOTEC Model: ZGA002
        [1]: OnOff
DEBUG || driver device thread event handled
TRACE || Received event with handler _resync
TRACE || Found DeviceLifecycleDispatcher handler in zigbee_switch -> Switch
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: DeviceTemperatureConfiguration >, lqi: 0x00, rssi: 0, body_length: 0x0008, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x00, seqno: 0x00, ZCLCommandId: 0x0A >, < ReportAttribute || < AttributeRecord || AttributeId: 0x0000, DataType: Int16, CurrentTemperature: 70 > > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterAttributeValueHandler: cluster: DeviceTemperatureConfiguration, attribute: CurrentTemperature
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"unit":"C","value":70},"capability_id":"temperatureMeasurement","attribute_id":"temperature"}
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: Alarms >, lqi: 0x00, rssi: 0, body_length: 0x0006, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x09, seqno: 0x00, ZCLCommandId: 0x00 >, < Alarm || alarm_code: 0x86, cluster_identifier: SimpleMetering > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterCommandHandler: cluster: Alarms, command: ResetAlarm
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"value":"heat"},"capability_id":"temperatureAlarm","attribute_id":"temperatureAlarm"}
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: DeviceTemperatureConfiguration >, lqi: 0x00, rssi: 0, body_length: 0x0008, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x00, seqno: 0x00, ZCLCommandId: 0x0A >, < ReportAttribute || < AttributeRecord || AttributeId: 0x0000, DataType: Int16, CurrentTemperature: 65 > > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterAttributeValueHandler: cluster: DeviceTemperatureConfiguration, attribute: CurrentTemperature
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"unit":"C","value":65},"capability_id":"temperatureMeasurement","attribute_id":"temperature"}
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> sending Zigbee message: < ZigbeeMessageTx || Uint16: 0x0000, < AddressHeader || src_addr: 0x0000, src_endpoint: 0x01, dest_addr: 0x0001, dest_endpoint: 0x01, profile: 0x0104, cluster: Alarms >, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x01, seqno: 0x00, ZCLCommandId: 0x01 >, < ResetAllAlarms ||  > > >
Failed with message:
Zigbee message channel send was expecting:
ZigbeeMessageRx:
        Uint8: 0x00
        AddressHeader:
            src_addr: 0x0001
            src_endpoint: 0x01
            dest_addr: 0x0000
            dest_endpoint: 0x01
            profile: 0x0104
            cluster: Alarms
        Uint8: 0x00
        Int8: 0
        Uint16: 0x0003
        ZCLMessageBody:
            ZCLHeader:
                frame_ctrl: 0x01
                seqno: 0x00
                ZCLCommandId: 0x01
            ResetAllAlarms:
but received:
ZigbeeMessageTx:
        Uint16: 0x0000
        AddressHeader:
            src_addr: 0x0000
            src_endpoint: 0x01
            dest_addr: 0x0001
            dest_endpoint: 0x01
            profile: 0x0104
            cluster: Alarms
        ZCLMessageBody:
            ZCLHeader:
                frame_ctrl: 0x01
                seqno: 0x00
                ZCLCommandId: 0x01
            ResetAllAlarms:

FAILED


Passed 1 of 2 tests

ResetAlarm()

Running test "Temperature handled" (1 of 2)
-------------------------------------------
TRACE || Setup driver zigbee_switch with lifecycle handlers:
DeviceLifecycleDispatcher: zigbee_switch
  default_handlers:
    init:
    driverSwitched:
    doConfigure:
    infoChanged:
  child_dispatchers:
    DeviceLifecycleDispatcher: zigbee_switch -> Zigbee Hanssem Switch
      default_handlers:
        init:
...
TRACE || Zigbee Device: 00000000-1111-2222-3333-000000000001
Manufacturer: AEOTEC Model: ZGA002
        [1]: OnOff
TRACE || Received event with handler _resync
DEBUG || driver device thread event handled
TRACE || Found DeviceLifecycleDispatcher handler in zigbee_switch -> Switch
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: DeviceTemperatureConfiguration >, lqi: 0x00, rssi: 0, body_length: 0x0008, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x00, seqno: 0x00, ZCLCommandId: 0x0A >, < ReportAttribute || < AttributeRecord || AttributeId: 0x0000, DataType: Int16, CurrentTemperature: 44 > > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterAttributeValueHandler: cluster: DeviceTemperatureConfiguration, attribute: CurrentTemperature
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"unit":"C","value":44},"attribute_id":"temperature","capability_id":"temperatureMeasurement"}
DEBUG || Switch device thread event handled
PASSED


Running test "Temparture Alarm Reset handled" (2 of 2)
-------------------------------------------
TRACE || Setup driver zigbee_switch with lifecycle handlers:
DeviceLifecycleDispatcher: zigbee_switch
  default_handlers:
    init:
    driverSwitched:
    doConfigure:
    infoChanged:
  child_dispatchers:
    DeviceLifecycleDispatcher: zigbee_switch -> Zigbee Hanssem Switch
      default_handlers:
        init:
...
Manufacturer: AEOTEC Model: ZGA002
        [1]: OnOff
DEBUG || driver device thread event handled
TRACE || Received event with handler _resync
TRACE || Found DeviceLifecycleDispatcher handler in zigbee_switch -> Switch
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: DeviceTemperatureConfiguration >, lqi: 0x00, rssi: 0, body_length: 0x0008, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x00, seqno: 0x00, ZCLCommandId: 0x0A >, < ReportAttribute || < AttributeRecord || AttributeId: 0x0000, DataType: Int16, CurrentTemperature: 70 > > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterAttributeValueHandler: cluster: DeviceTemperatureConfiguration, attribute: CurrentTemperature
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"unit":"C","value":70},"attribute_id":"temperature","capability_id":"temperatureMeasurement"}
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: Alarms >, lqi: 0x00, rssi: 0, body_length: 0x0006, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x09, seqno: 0x00, ZCLCommandId: 0x00 >, < Alarm || alarm_code: 0x86, cluster_identifier: SimpleMetering > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterCommandHandler: cluster: Alarms, command: ResetAlarm
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"value":"heat"},"attribute_id":"temperatureAlarm","capability_id":"temperatureAlarm"}
DEBUG || Switch device thread event handled
TRACE || Received event with handler zigbee
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x0001, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: DeviceTemperatureConfiguration >, lqi: 0x00, rssi: 0, body_length: 0x0008, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x00, seqno: 0x00, ZCLCommandId: 0x0A >, < ReportAttribute || < AttributeRecord || AttributeId: 0x0000, DataType: Int16, CurrentTemperature: 65 > > > >
TRACE || Found ZigbeeMessageDispatcher handler in zigbee_switch -> Switch
INFO  || Executing ZclClusterAttributeValueHandler: cluster: DeviceTemperatureConfiguration, attribute: CurrentTemperature
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> emitting event: {"component_id":"main","state":{"unit":"C","value":65},"attribute_id":"temperature","capability_id":"temperatureMeasurement"}
INFO  || <ZigbeeDevice: 00000000-1111-2222-3333-000000000001 [0x0001] (Switch)> sending Zigbee message: < ZigbeeMessageTx || Uint16: 0x0000, < AddressHeader || src_addr: 0x0000, src_endpoint: 0x01, dest_addr: 0x0001, dest_endpoint: 0x01, profile: 0x0104, cluster: Alarms >, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x01, seqno: 0x00, ZCLCommandId: 0x00 >, < ResetAlarm || alarm_code: 0x86, cluster_identifier: SimpleMetering > > >
Failed with message:
Zigbee message channel send was expecting:
ZigbeeMessageRx:
        Uint8: 0x00
        AddressHeader:
            src_addr: 0x0001
            src_endpoint: 0x01
            dest_addr: 0x0000
            dest_endpoint: 0x01
            profile: 0x0104
            cluster: Alarms
        Uint8: 0x00
        Int8: 0
        Uint16: 0x0006
        ZCLMessageBody:
            ZCLHeader:
                frame_ctrl: 0x01
                seqno: 0x00
                ZCLCommandId: 0x00
            ResetAlarm:
                alarm_code: 0x86
                cluster_identifier: SimpleMetering
but received:
ZigbeeMessageTx:
        Uint16: 0x0000
        AddressHeader:
            src_addr: 0x0000
            src_endpoint: 0x01
            dest_addr: 0x0001
            dest_endpoint: 0x01
            profile: 0x0104
            cluster: Alarms
        ZCLMessageBody:
            ZCLHeader:
                frame_ctrl: 0x01
                seqno: 0x00
                ZCLCommandId: 0x00
            ResetAlarm:
                alarm_code: 0x86
                cluster_identifier: SimpleMetering

FAILED


Passed 1 of 2 tests

What am I doing wrong in expect_send or in my function? I dont get it …

Thank you in advance!

Try without that build_test_rx bit. I’m not seeing that in the examples I’m looking at, plus the errors are saying your test expects a message from the device to the hub when what’s happening is a message from the hub to the device.

Also, in the commented out ResetAlarm line there’s a missing server in Alarm.server.commands.... Maybe that’s not an issue though - I never really messed with zigbee too much.

@philh30 Indeed! :man_facepalming:
searching for “build_test_rx” shows me that it is only used to build queues that receive messages … But I didn’t really notice that until now :man_facepalming:

Much to learn, I still have.

If you address the command without ‘server’, as it actually says in the definition, the test still doesn’t seem to fail. I noticed an ‘Alarms.command_direction_map’ in Alarms/init.lua, but didn’t go into it further. Maybe the command handler in the library somehow picks it up and then directs it in the right direction?

1 Like