Help required as I develop an Edge driver for my Secure SRT323 Thermostat

So, my Secure Thermostats (SRT323 and SRT321), which require custom Groovy drivers and cloud execution will stop working in about 3 weeks, just as the temperature drops here in the UK.
By cut and paste, trial and error, and copious logging, I have an Edge driver 75% working but only alpha quality.
I am stuck on capabilities.thermostatOperatingState, specifically:
local function operating_state_report_handler(self, device, cmd)
local event = nil
local state = cmd.args.operating_state"operating_state_report_handler state: ", state)

if state == 0 then – IDLE“operating_state_report_handler - IDLE”)
event = capabilities.thermostatOperatingState.thermostatOperatingState.idle()
elseif state == 1 then – HEATING“operating_state_report_handler - HEATING”)
event = capabilities.thermostatOperatingState.thermostatOperatingState.heating()
else“operating_state_report_handler - UNKNOWN → IDLE”)
event = capabilities.thermostatOperatingState.thermostatOperatingState.idle()
end“operating_state_report_handler - ready to set_field”)
device:set_field(OPERATING_STATE, state, {persist = true})“operating_state_report_handler - set_field done”)

if (event ~= nil) then"operating_state_report_handler event: ", event)

Any help appreciated.

Hello, @jaidank

As I understand, operating_state_report_handler is a handler for the attribute, right?

Are you getting an error in the logs?

If it is regarding the commands you defined like this one:

Please, check if this one works:

event = capabilities.thermostatOperatingState.thermostatOperatingState("idle")

In the Default libraries, it uses idle as a command because it imports st.zwave.CommandClass.ThermostatOperatingState. In this case, you’re calling “capabilities” and by checking the capability’s definition, we see it doesn’t have a command called idle, so, the command must point to assigning a value to the attribute thermostatOperatingState:

smartthings capabilities thermostatOperatingState -j
    "id": "thermostatOperatingState",
    "version": 1,
    "status": "live",
    "name": "Thermostat Operating State",
    "ephemeral": false,
    "attributes": {
        "thermostatOperatingState": {
            "schema": {
                "type": "object",
                "properties": {
                    "value": {
                        "title": "ThermostatOperatingState",
                        "type": "string",
                        "enum": [
                            "fan only",
                            "pending cool",
                            "pending heat",
                            "vent economizer"
                "additionalProperties": false,
                "required": [
            "enumCommands": []
    "commands": {}

Does this help? If not, please provide the error log you see in the logcat

1 Like

Thank you @nayelyz nayelyz for your prompt reply.
I think my error was:
device:set_field(OPERATING_STATE, state, {persist = true})
I have been experimenting with this but, at 1am, I changed it back to the original (below) and went to bed:
device:set_field(STATE, state, {persist = true})
This morning I found everything worked.
Next, I need to get my other thermostat working (Secure SRT321).
This is almost identical but reports a swtich state instead of thermostatOperatingState.
I am hoping to handle it with the same driver with an additional response handler.
All going well, my final step will be to figure out how best to share with the community.
Thanks, Aidan

Yes, subdrivers are very helpful for this kind of case, they allow a single driver to support different device models.
You can find some references on how to use them in the official SmartThings drivers in this repo: SmartThingsEdgeDrivers/drivers/SmartThings at main · SmartThingsCommunity/SmartThingsEdgeDrivers · GitHub

You can easily share your driver with others thanks to Channels because you can publish it there and invite people to them. Here’s a document about the sharing process:

1 Like

Hi @nayelyz
I am now working on my Secure SRT321 and am having problems.
My biggest issue is that manual heating set points done on the thermostat are not being sent to my device handler.
The documentation says this is sent to Assocition Group 4, but my driver is not seeing them.
I am seeing Thermostat Mode changes (see below, I have pretty-printed it), but my handler is not being called. Does the ‘version=3’ mean that Secure have implemented a different version to SmartThings?

2022-09-12T18:30:02.652234291+00:00 TRACE Secure SRT321 Thermostat Received event with handler unnamed
2022-09-12T18:30:02.665253416+00:00 INFO Secure SRT321 Thermostat
<ZwaveDevice: 7c7286af-12a1-43c9-ad04-50e25637e0e7 [2A] (Secure SRT321 Thermostat)>
received Z-Wave command:
2022-09-12T18:30:02.670440082+00:00 DEBUG Secure SRT321 Thermostat Secure SRT321 Thermostat device thread event handled
2022-09-12T18:30:05.422002540+00:00 TRACE Secure SRT321 Thermostat Received event with handler unnamed
2022-09-12T18:30:05.426776123+00:00 INFO Secure SRT321 Thermostat
<ZwaveDevice: 7c7286af-12a1-43c9-ad04-50e25637e0e7 [2A] (Secure SRT321 Thermostat)>
received Z-Wave command:
2022-09-12T18:30:05.431957957+00:00 DEBUG Secure SRT321 Thermostat Secure SRT321 Thermostat device thread event handled.

I don’t want to use up your bandwidth or good will on this.
I am able to send heating set point to the SRT321, and get the room temperature back (albeit by sending a GET on wake up), so I guess we will not freeze this winter.
But if you have any ideas.
So far, I am liking Edge; if only the device manufacturers would be consistent in their implementations.

Here is some excerpts from my driver:

local ThermostatMode = (require “st.zwave.CommandClass.ThermostatMode”)({ version = 3 })

local function thermostat_mode_report_handler(self, device, cmd)
local event = nil

local mode = 0 – cmd.args.mode"thermostat_mode_report_handler mode: ", mode)

[ThermostatMode.REPORT] = thermostat_mode_report_handler

Cheers, Aidan

Have you added the hub node to the thermostat’s association group 4?

The logs that you posted show the hub received ThermostatMode.SET commands:

The code excerpt you posted only defines a handler for ThermostatMode.REPORT, not ThermostatMode.SET:

1 Like

Many thanks @philh30,
I will add ThermostatMode.SET handler this evening and give it a go.
I had tried to add the hub node the thermostat’s association group 4, via an Association.Set in the device_init code, but my handler did not receive any set point reports.
I am very much a newbie, I’m afraid. I can post the code if that is helpful.

Thanks again @philh30
My ThermostatMode is now working, with the app instantly updating Mode to either Off or Heat as expected.
The big thing remaining is the Association of Group 4 so I can receive handle ThermostatSetpoint.REPORT
(Group 5, for unsolicited temperature readings would also be nice, and save me having to do a Get every other wakep).
The SRT321 does have an ‘A’ (Association) but I have only managed to get that to work to associate the SSR303 (Relay) with Group 2 (Switch Binary).
As things stand, I have an SRT323 and SRT321 working well enough to manage our heating for a winter of crazy energy prices.
Thanks @philh30 and @nayelyz for your help.
Cheers, Aidan

1 Like

If you post your driver to GitHub then it will be easier to recommend changes to get your association groups set. You’ll essentially need to include something like below to be called on wakeup (ideally this code will only run once, and not on every wake up going forward). If you watch your logs, you should see the device return an Association:Report with node 1 (the hub) included in the association group.

    local hubnode = device.driver.environment_info.hub_zwave_id
    device:send(Association:Set({grouping_identifier = 4, node_ids = {hubnode}}))
    device:send(Association:Get({grouping_identifier = 4}))
    device:send(Association:Set({grouping_identifier = 5, node_ids = {hubnode}}))
    device:send(Association:Get({grouping_identifier = 5}))
1 Like

Well, @philh30 , what a result; your suggestion worked perfectly (I do the Associations on the first Wake Up only).
I am now getting SetPoint changes and unsolicited temperature changes from the SRT321.
I had previously (unsuccessfully) tried Association:Set (without a Get) in device_init.
I have a GitHub account but have never really used it. I guess now is the time to learn.
I should warn you that I chickened out of implementing the SRT323 and SRT321 as sub-handlers of the more genaral community ZWave Thermostat. My two are individual standalone handlers (not ideal, I know) based on copy and paste of the community handler.

1 Like

Good job!

The Get isn’t actually necessary, but it triggers the device to send an Association:Report to confirm that the association was set properly.