Secure Together SRT321/SSR303 or Horstmann ASR-ZW/HRT4-ZW (Updated DTH in post 61)

I’ve just raised a ticket with them. Thanks for the pointer.

I need to find out if this affects the Danfoss TRV which also uses a V1 heating setpoint z-wave command!

Appears to have also broken the Danfoss TRV as well for the same reason.

For info, I’ve got a brand new hub running the following firmware
Firmware Version 000.016.00014

I have the same issue, ST will not update the physical device however Temperature reports to ST and local thermostat changes report back to ST.

(Still waiting the firmware update …)

This might be a complete coincidence, but the timing looks to be the same:

1 Like

Yes it does, so it looks like they have broken returning Z Wave commands with a response, as that is what I am doing:

// Battery powered devices can be configured to periodically wake up and
// check in. They send this command and stay awake long enough to receive
// commands, or until they get a WakeUpNoMoreInformation command that
// instructs them that there are no more commands to receive and they can
// stop listening.
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
{
def map = [name:“thermostatWakeUp”, value: “${device.displayName} woke up”, isStateChange: true]
def event = createEvent(map)
def cmds = updateIfNeeded()

	cmds << zwave.wakeUpV2.wakeUpNoMoreInformation().format()
    
    log.debug "Wakeup $cmds"

    [event, response(delayBetween(cmds, 1000))]      

}

@meavydev

There is now a code discussion of the specifics of the problem that started a couple of days ago, including a possible workaround, in the following thread in the developers section of the forum:

Ah OK. The problem is that they appear to have broken the casting of HubMultiAction command list to a SendHubCommand.

I have managed to re-write the code to extract each cmd and send it with one SendHubCommand and it has finally worked… but seriously poor testing by SmartThings devs :frowning:

// Battery powered devices can be configured to periodically wake up and
// check in. They send this command and stay awake long enough to receive
// commands, or until they get a WakeUpNoMoreInformation command that
// instructs them that there are no more commands to receive and they can
// stop listening.
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
{
def map = [name:“thermostatWakeUp”, value: “${device.displayName} woke up”, isStateChange: true]
def event = createEvent(map)
def cmds = updateIfNeeded()

	cmds << zwave.wakeUpV2.wakeUpNoMoreInformation().format()
    
    log.debug "Wakeup $cmds"

	cmds.each 
    { zwaveCmd ->
            def hubCmd = []
            hubCmd << response(zwaveCmd)

            log.debug "HubCmds $hubCmd"

            sendHubCommand(hubCmd, 1000)

            log.debug "Sent hubcommand"
    };
    [event]      
    
    // [event, response(delayBetween(cmds, 1000))]

}

So if people edit the WakeUpNotifcationEvent code as above, then it should be a valid workaround

2 Likes

Thanks @meavydev really appreciate you sorting this.

Will you be updating your GitHub to reflect the change?

I’m not planning to update github, partly as SmartThings need to fix their code and partly because it’s a pain to have to copy over to the US servers as no UK integration…
After all, the code in github is correct and what SmartThings say you should do :wink:

All agreed. No arguments here.

Are you aware that GitHub integration is working for UK users? It’s been working for a while. It makes the DTH and SmartApp page load painful at times but it’s working.

Thanks again for sorting. I’ve got 3 of Horstmann HRT4-ZW using your code controlling 3 heating zones. The fact the weather is fairly mild and your quick resolution have saved me some pain :slight_smile:

GitHub integration doesn’t seem to be there for me in the IDE, but I am using Chrome on a Macbook.
I have no option to link to GitHub in the IDE and the documentation still says US only.
http://docs.smartthings.com/en/latest/tools-and-ide/github-integration.html?highlight=github

Glad I found something that helps, but it was lucky that SmartThings decided to break it in milder weather :wink:

The only positive aspect of this whole debacle is the weather!

I’m using OSX, from memory I enabled Github using Safari. It works well, like I said it just slows the load of the DTH page a little.

ST need to once again improve their release notification process. FW updates have been well publicised and handled much better than they have in the past (IMO). The fact they’ve changed something on the back end with no notification and broken what appears to be an increasing amount of devices will damage any of the good work done on the FW improvements. At the moment I don’t think they’ve even admitted there’s an issue, several people have contacted support only to be told that they won’t support them because the device in question is not on the HCL.

It would just be nice if there was some commentary to acknowledge the fact there is an issue, known to be caused by a change implemented on what I believe was 19th April?

@Duncan are you tracking this issue and do you have any ETA for a fix?

Can any confirm that all is working as expected please?

I can’t seem to get my stat to heat?

Thanks

@meavydev

All I can say is it’s fine for me, but my hub is still on 17.12 due to no internet when they did the last update, thanks to lightning taking out BT socket, router and 3G dongle backup…

Lucky old you, I’m sure there’s a few out there that would rather have no internet than FW18 :slight_smile:

I’ve just reset a couple of things and it’s actually working. Apologies!

Another quick question for you if you have 5? I’m trying to get around an issue that I’m having in relation to the states that the DTH reports.

I want to create a state called:
capability.thermostatOperatingState

As documented here:
http://docs.smartthings.com/en/latest/capabilities-reference.html#thermostatoperatingstate

Would you have any idea how to create a state called operatingState in the DTH that was derived from the mode? So for:

mode=heat operatingstate=heating
mode=off operatingstate = idle

this would really help me out with ActionTiles if possible?

Cheers

P

Hi guys just got myself a ST hub and been hoping to get this all working with my Horstmann HRT4-ZW thermostat and receiver. I’ve read through all this and others post to learn how to publish handlers etc… I’ve got both devices included in Hub and mostly working. The main issues I have are:

  1. When setting a temp from the app it is not transferring to the device. I waited the 10mins as this is the default wakeup time. I even tried reducing this in the code for testing purposes with no joy. Temperature setting is reported back when I adjust setting on the device no problem. Used @meavydev DTH and also the his updated code to fix what a firmware update broke.

  2. On the boiler receiver switch I can switch it on and off ok via the app but the status of the switch does not update unless I press the refresh button tile. I’m using @brumster modded boiler switch DTH.

Many thanks for your work on the code and any help to get this working world be much appreciated. I may be doing something wrong or missed something or is this broken again. My hub basically got the latest firmware update today so don’t know if this has broken anything again

Have you modified @meavydev 's code with the last update as shown couple of posts above? There was an ST release a couple of months ago that broke the code and the mod was required.

Mine are all working fine. My code pasted below. Let us know how you get on.

Befor you try this is the stat changing the actuator (boiler switch) from on to off? Make sure that all works before you pair the stat with ST.

Here the code (all credit goes to @meavydev).

/*
 * SRT321 Thermostat by MeavyDev
 * With support for an associated switch set by the SRT321 helper app
 */
metadata 
{
	definition (name: "SRT321 Thermostat", namespace: "meavydev", author: "MeavyDev") 
    {
    	capability "Actuator"
		capability "Temperature Measurement"
		capability "Thermostat"
		capability "Configuration"
		capability "Polling"
		capability "Sensor"

		command "switchMode"
        command "quickSetHeat"
		command "setTemperature"
		command "setTempUp"
		command "setTempDown"
        
		command "setupDevice" 
        		
		// fingerprint deviceId: "0x0800", inClusters: "0x25, 0x31, 0x40, 0x43, 0x70, 0x72, 0x80, 0x84, 0x85, 0x86, 0xef"
		fingerprint deviceId: "0x0800" 
        fingerprint inClusters: "0x72,0x86,0x80,0x84,0x31,0x43,0x85,0x70,0x40,0x25"
	}

	// simulator metadata
	simulator 
    {
	}

	tiles (scale: 2)
    {
        multiAttributeTile(name:"heatingSetpoint", type: "thermostat", width: 6, height: 4, canChangeIcon: true)
        {
            tileAttribute ("device.heatingSetpoint", key: "PRIMARY_CONTROL") 
            {
                attributeState("default", unit:"dC", label:'${currentValue}°')
            }
            
            tileAttribute("device.heatingSetpoint", key: "VALUE_CONTROL") 
            {
                attributeState("VALUE_UP", action: "setTempUp")
                attributeState("VALUE_DOWN", action: "setTempDown")
//                attributeState("default", action: "setTemperature")
            }
            
            tileAttribute("device.temperature", key: "SECONDARY_CONTROL") 
            {
            	attributeState("default", label:'${currentValue} C', unit:"C")
            }
            
            tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") 
            {
                attributeState("off", label:'${name}')
                attributeState("heat", label:'${name}')
            }
            
  			tileAttribute("device.heatingSetpoint", key: "HEATING_SETPOINT") 
            {
    			attributeState("default", label:'${currentValue}', unit:"C")
			}
            
            tileAttribute("device.thermostatMode", key: "OPERATING_STATE") 
            {
                attributeState("off", backgroundColor:"#44b621")
                attributeState("heat", backgroundColor:"#ffa81e")
            }
        }  

        valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) 
        {
            tileAttribute ("device.battery", key: "PRIMARY_CONTROL")
            {
                state "battery", label:'${currentValue}% battery', unit:""
            }
        }
        
        standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat", width: 2, height: 2)
        {
			state "default", action:"polling.poll", icon:"st.secondary.refresh"
		}
        
		standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) 
        {
			state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
		}
	}

	main "heatingSetpoint"
    details(["heatingSetpoint", "battery", "refresh", "configure", "temperature", "mode"])

    preferences 
    {
        input "userWakeUpInterval", "number", title: "Wakeup interval...", description: "Wake Up Interval (seconds)", defaultValue: 3600, required: false, displayDuringSetup: false

        // This is the "Device Network Id" displayed in the IDE
        input "userAssociatedDevice", "string", title:"Associated z-wave switch network Id...", description:"Associated switch ZWave network Id (hex)", required: false, displayDuringSetup: false
    }
}

def parse(String description)
{
//	log.debug "Parse $description"

	def result = zwaveEvent(zwave.parse(description, [0x72:1, 0x86:1, 0x80:1, 0x84:2, 0x31:1, 0x43:1, 0x85:1, 0x70:1, 0xEF:1, 0x40:1, 0x25:1]))
	if (!result) 
    {
    	log.warn "Parse returned null"
		return null
	}
    
//	log.debug "Parse returned $result"
	result
}

def updated() 
{
	log.debug "preferences updated"

	state.configNeeded = true
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev1.ThermostatModeSet cmd)
{
	def map = [:]
	switch (cmd.mode) {
		case physicalgraph.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_OFF:
			map.value = "off"
			break
		case physicalgraph.zwave.commands.thermostatmodev1.ThermostatModeSet.MODE_HEAT:
			map.value = "heat"
	}
	map.name = "thermostatMode"
	createEvent(map)
}

// Event Generation
def zwaveEvent(physicalgraph.zwave.commands.thermostatsetpointv1.ThermostatSetpointReport cmd)
{
	def map = [:]
	map.value = cmd.scaledValue.toString()
	map.unit = cmd.scale == 1 ? "F" : "C"
	map.displayed = false
	switch (cmd.setpointType) {
		case 1:
			map.name = "heatingSetpoint"
			break;
		default:
			return [:]
	}
	// So we can respond with same format
	state.size = cmd.size
	state.scale = cmd.scale
	state.precision = cmd.precision
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd)
{
	def map = [:]
	map.value = cmd.scaledSensorValue.toString()
	map.unit = cmd.scale == 1 ? "F" : "C"
	map.name = "temperature"
	createEvent(map)
}

//OLD code - removed by PH
/*
// Battery powered devices can be configured to periodically wake up and
// check in. They send this command and stay awake long enough to receive
// commands, or until they get a WakeUpNoMoreInformation command that
// instructs them that there are no more commands to receive and they can
// stop listening.
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
{
		def map = [name:"thermostatWakeUp", value: "${device.displayName} woke up", isStateChange: true]       
        def event = createEvent(map)
		def cmds = updateIfNeeded()
        
		cmds << zwave.wakeUpV2.wakeUpNoMoreInformation().format()
        
        log.debug "Wakeup $cmds"

        [event, response(delayBetween(cmds, 1000))]      
}
*/

// New code added by PH

// Battery powered devices can be configured to periodically wake up and
// check in. They send this command and stay awake long enough to receive
// commands, or until they get a WakeUpNoMoreInformation command that
// instructs them that there are no more commands to receive and they can
// stop listening.
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
{
def map = [name:"thermostatWakeUp", value: "${device.displayName} woke up", isStateChange: true] 
def event = createEvent(map)
def cmds = updateIfNeeded()

	cmds << zwave.wakeUpV2.wakeUpNoMoreInformation().format()

    log.debug "Wakeup $cmds"

	cmds.each 
    { zwaveCmd ->
            def hubCmd = []
            hubCmd << response(zwaveCmd)

            log.debug "HubCmds $hubCmd"

            sendHubCommand(hubCmd, 1000)

            log.debug "Sent hubcommand"
    };
    [event]      
    
    // [event, response(delayBetween(cmds, 1000))]
}


def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) 
{
    def map = [ name: "battery", unit: "%" ]
    if (cmd.batteryLevel == 0xFF) 
    {  // Special value for low battery alert
            map.value = 1
            map.descriptionText = "${device.displayName} has a low battery"
            map.isStateChange = true
    } 
    else 
    {
            map.value = cmd.batteryLevel
            log.debug ("Battery: $cmd.batteryLevel")
    }
    // Store time of last battery update so we don't ask every wakeup, see WakeUpNotification handler
    state.lastbatt = new Date().time
    createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev1.ThermostatModeReport cmd) 
{
	def map = [:]
	switch (cmd.mode) {
		case physicalgraph.zwave.commands.thermostatmodev1.ThermostatModeReport.MODE_OFF:
			map.value = "off"
			break
		case physicalgraph.zwave.commands.thermostatmodev1.ThermostatModeReport.MODE_HEAT:
			map.value = "heat"
			break
	}
	map.name = "thermostatMode"
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpIntervalCapabilitiesReport cmd) 
{
    def map = [ name: "defaultWakeUpInterval", unit: "seconds" ]
	map.value = cmd.defaultWakeUpIntervalSeconds
	map.displayed = false
	state.defaultWakeUpInterval = cmd.defaultWakeUpIntervalSeconds
    createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpIntervalReport cmd)
{
	def map = [ name: "reportedWakeUpInterval", unit: "seconds" ]
	map.value = cmd.seconds
	map.displayed = false
    createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 
{
	log.debug "Zwave event received: $cmd"
}

def zwaveEvent(physicalgraph.zwave.Command cmd) 
{
	log.warn "Unexpected zwave command $cmd"
    
    delayBetween([
		zwave.sensorMultilevelV1.sensorMultilevelGet().format(), // current temperature
		zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
		zwave.thermostatModeV1.thermostatModeGet().format(),
		zwave.thermostatFanModeV3.thermostatFanModeGet().format(),
		zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
	], 1000)

}

// Command Implementations

def configure() 
{
	log.debug "configure"
	state.configNeeded = true
    
    // Normally this won't do anything as the thermostat is asleep, 
    // but do this in case it helps with the initial config
	delayBetween([
		zwave.thermostatModeV1.thermostatModeSupportedGet().format(),
		zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format(),
        // Set hub to get battery reports / warnings
        zwave.associationV1.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format(),
        // Set hub to get set point reports
        zwave.associationV1.associationSet(groupingIdentifier:4, nodeId:[zwaveHubNodeId]).format(),
        // Set hub to get multi-level sensor reports (defaults to temperature changes of > 1C)
        zwave.associationV1.associationSet(groupingIdentifier:5, nodeId:[zwaveHubNodeId]).format(),
        // set the temperature sensor On
		zwave.configurationV1.configurationSet(configurationValue: [0xff], parameterNumber: 1, size: 1).format()
	], 1000)
}

def poll() 
{
	log.debug "poll"

	// Normally this won't do anything as the thermostat is asleep, 
    // but do this in case it helps with the initial config
	delayBetween([
		zwave.sensorMultilevelV1.sensorMultilevelGet().format(), // current temperature
		zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: physicalgraph.zwave.commands.thermostatsetpointv1.ThermostatSetpointSet.SETPOINT_TYPE_HEATING_1).format(),
		zwave.thermostatModeV1.thermostatModeGet().format(),
		zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
	], 1000)
}

def refresh()
{
	log.debug "refresh"

	state.refreshNeeded = true
    
    // Normally this won't do anything as the thermostat is asleep, 
    // but do this in case it helps with the initial config
	delayBetween([
		zwave.sensorMultilevelV1.sensorMultilevelGet().format(), // current temperature
		zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: physicalgraph.zwave.commands.thermostatsetpointv1.ThermostatSetpointSet.SETPOINT_TYPE_HEATING_1).format(),
		zwave.thermostatModeV1.thermostatModeGet().format(),
		zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
	], 1000)
}

def quickSetHeat(degrees) 
{
	setHeatingSetpoint(degrees)
	log.debug("Degrees at quicksetheat: $degrees")
}

def setTempUp() 
{ 
    def newtemp = device.currentValue("heatingSetpoint").toInteger() + 1
    log.debug "Setting temp up: $newtemp"
    quickSetHeat(newtemp)
}

def setTempDown() 
{ 
    def newtemp = device.currentValue("heatingSetpoint").toInteger() - 1
    log.debug "Setting temp down: $newtemp"
    quickSetHeat(newtemp)
}

def setTemperature(temp)
{
	log.debug "setTemperature $temp"
    quickSetHeat(temp)
}

def setHeatingSetpoint(degrees) 
{
	setHeatingSetpoint(degrees.toDouble())
	log.debug("Degrees at setheatpoint: $degrees")
}

def setHeatingSetpoint(Double degrees) 
{
	log.trace "setHeatingSetpoint($degrees)"
    sendEvent(name: 'heatingSetpoint', value: degrees)

	def deviceScale = state.scale ?: 1
	def deviceScaleString = deviceScale == 2 ? "C" : "F"
    def locationScale = getTemperatureScale()
    def p = (state.precision == null) ? 1 : state.precision

    def convertedDegrees
    if (locationScale == "C" && deviceScaleString == "F") 
    {
        convertedDegrees = celsiusToFahrenheit(degrees)
    } 
    else if (locationScale == "F" && deviceScaleString == "C") 
    {
        convertedDegrees = fahrenheitToCelsius(degrees)
    } 
    else 
    {
        convertedDegrees = degrees
    }

	log.trace "setHeatingSetpoint scale: $deviceScale precision: $p setpoint: $convertedDegrees"
	state.deviceScale = deviceScale
    state.p = p
    state.convertedDegrees = convertedDegrees
    state.updateNeeded = true
    
    thermostatMode
}

private getStandardDelay() 
{
	1000
}

def updateIfNeeded()
{
	def cmds = []
    
    // Only ask for battery if we haven't had a BatteryReport in a while
    if (!state.lastbatt || (new Date().time) - state.lastbatt > 24*60*60*1000) 
    {
    	log.debug "Getting battery state"
    	cmds << zwave.batteryV1.batteryGet().format()
    }
        
	if (state.refreshNeeded)
    {
        log.debug "Refresh"
        cmds << zwave.sensorMultilevelV1.sensorMultilevelGet().format() // current temperature
		cmds << zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: physicalgraph.zwave.commands.thermostatsetpointv1.ThermostatSetpointSet.SETPOINT_TYPE_HEATING_1).format()

		cmds << zwave.thermostatModeV1.thermostatModeGet().format()
		cmds << zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
        cmds << zwave.thermostatModeV1.thermostatModeSupportedGet().format()
       	state.refreshNeeded = false
    }
    
    if (state.updateNeeded)
    {
        log.debug "Update"

		cmds << zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: physicalgraph.zwave.commands.thermostatsetpointv1.ThermostatSetpointSet.SETPOINT_TYPE_HEATING_1, scale: state.deviceScale, precision: state.p, scaledValue: state.convertedDegrees).format()
        state.updateNeeded = false
    }
    
    if (state.configNeeded)
    {
        log.debug "Config"
    	state.configNeeded = false
        
        // Nodes controlled by Thermostat Mode Set - not sure this is needed?
        cmds << zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()
        
         // Set hub to get battery reports / warnings
        cmds << zwave.associationV1.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
        
         // Set hub to get set point reports
        cmds << zwave.associationV1.associationSet(groupingIdentifier:4, nodeId:[zwaveHubNodeId]).format()
        
         // Set hub to get multi-level sensor reports (defaults to temperature changes of > 1C)
        cmds << zwave.associationV1.associationSet(groupingIdentifier:5, nodeId:[zwaveHubNodeId]).format()
        
        // set the temperature sensor On
		cmds << zwave.configurationV1.configurationSet(configurationValue: [0xff], parameterNumber: 1, size: 1).format()

		log.debug "association $state.association user: $userAssociatedDevice"
		int nodeID = getAssociatedId(state.association)
        // If user has changed the switch association, send the new assocation to the device 
    	if (nodeID != -1)
        {
            log.debug "Setting associated device $nodeID"
            cmds << zwave.associationV1.associationSet(groupingIdentifier: 2, nodeId: nodeID).format()
        }
        
        def userWake = getUserWakeUp(userWakeUpInterval)
        // If user has changed userWakeUpInterval, send the new interval to the device 
    	if (state.wakeUpInterval != userWake)
        {
       		state.wakeUpInterval = userWake
            log.debug "Setting New WakeUp Interval to: " + state.wakeUpInterval
        	cmds << zwave.wakeUpV2.wakeUpIntervalSet(seconds:state.wakeUpInterval, nodeid:zwaveHubNodeId).format()
       		cmds << zwave.wakeUpV2.wakeUpIntervalGet().format()
    	}  
		cmds << zwave.thermostatModeV1.thermostatModeSupportedGet().format()
    }
    
    if (cmds.size() > 0)
    {
    	cmds << "delay 2000"
    }
    cmds
}


private getUserWakeUp(userWake) 
{
    if (!userWake)  
    { 
    	userWake = '3600' // set default 1 hr if no user preference 
    } 
    // make sure user setting is within valid range for device 
    if (userWake.toInteger() < 60)
    { 
    	userWake = '600'   // 10 minutes - Mininum
    }
    if (userWake.toInteger() > 36000)
    {
    	userWake = '36000' // 10 hours - Maximum
    }  
    return userWake.toInteger()
}

// Get the Z-Wave Id of the binary switch the user wants the thermostat to control
// -1 if no association set
int getAssociatedId(association)
{
	int associatedState = -1
	int associatedUser = -1
    log.debug "getAssociatedId $association"
	if (association != null && association != "")
    {
    	associatedState = association.toInteger()
        log.debug "State $association $associatedState"
    }
    if (userAssociatedDevice != null && userAssociatedDevice != "")
    {
    	try
        {
       		associatedUser = Integer.parseInt(userAssociatedDevice, 16)
        }
        catch (Exception e)
        {
        }
        log.debug "userDev $userAssociatedDevice $associatedUser"
    }
    
    // Use the app associated switch id if it exists, otherwise the device preference  
    return associatedState != -1 ? associatedState : associatedUser
}

// Called from the SRT321 App with the Z-Wave switch network ID
// How long before SmartThings realises that having device preferences 
// with input "*" "capability.switch" is reasonable????
void setupDevice(value)
{
	state.association = "$value"
    int val = Integer.parseInt(value)
    String hex = Integer.toHexString(val)
    log.debug "Setting associated device Id $value Hex $hex"
    settings.userAssociatedDevice = hex
    state.configNeeded = true
}

Thanks for the quick response. Something very strange happened. While I was out of the house and weirdly about the time I posted this, the Thermostat suddenly started to wake up every 10 mins and accept commands as of 1930hrs tonight​:grin::grin:. I checked my @meavydev file against yours anyway just to double check and they were the same as I had made the update previously. It’s working perfect now. :crossed_fingers:

The only minor issue I have now is that the boiler switch status doesn’t update automatically in the app. I have to press refresh to get it to update. Do you use a horstmann asr-zw/secure ssr303 boiler switch aswell? If so does it update its status automatically?

Are you using the boiler switch on its own or with a stat?

Yeah ASR-ZW boiler controller being controlled by the HRT4-ZW thermostat. I also have the modified DTH you put up for the controller on another thread to act as a relay rather than a thermostat.

I would have hoped the status of the the boiler switch would be instantly updated seeing that it is mains powered and not battery operated like the Thermostat.