Standard thermostat device service actions able to be overridden via the implementation file?

It’s a long time since i did any plugin hacking but I’m hoping someone can answer a simple question.

I’m looking to do basic interaction with an API-controlled thermostat and was hoping I could do this by creating a standard thermostat device (D_HVAC_ZoneThermostat1.xml) and then using a custom implementation file in the device advanced settings to define the needed services in place of the built-in ones.

Eg things like SetCurrentSetpoint from S_TemperatureSetpoint1.xml could have a specific implementation in my linked implementation file overriding whatever z-wave standard implementation that service has built in to vera,

This way I hoped to avoid having to duplicate and modify all the relevant D_ and S_ files (or start from scratch) and just write and substitute the actual actions implemented for desired services.

From what I’ve read and (vaguely) recall I thought that this should be possible but so far all attempts have been unsuccessful. Is this approach fundamentally wrong or do I just have problems with how I’ve made the changes?

Thanks for any help.

Yes, this is the way to go. What’s your problem, exactly?

Look at this plugin for more details:

Thanks, I thought that made sense but as far as I can see none of the code I put for an action in the implementation file (basically just a luup.log to test) ever gets implemented. It’s hard to tell but it seems as if the default actions are still getting run.

Any other tips welcome but I’ll check out the plugin you linked to see if that gives me a clue.

Try with a custom device file… they are very short to code. Use a different device type. It may be that the Vera implementation does not respect an implementation file. Service files are definitely reusable.

Thanks akbooer, it certainly seems as if that might be what’s happening. I wanted to use the standard device file so that things like Imperihome had a better chance of rendering the device as it should look like a standard thermostat, but perhaps I’ll have to give up on that.

Assuming I don’t need a custom device file, does this sound like it should work:

Device created using the standard D_HVAC_ZoneThermostat1.xml file, which picks up the corresponding json as expected.

Nothing changed other than editing Advanced/Params and pointing “impl_file” to my custom implementation file which currently contains just this:

<?xml version="1.0"?>
<implementation>
	<specVersion>
		<major>1</major>
		<minor>0</minor>
	</specVersion>
	<settings>
		<protocol>crlf</protocol>
	</settings>
	<incoming></incoming>
	<files></files>
	<startup></startup>
	<actionList>
		<action>
			<serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1</serviceId>
			<name>SetCurrentSetpoint</name>
			<run>
				luup.log ("change setpoint")
			</run>
		</action>
	</actionList>
</implementation>

Should I expect that I would get that message logged if I then change the setpoint from the UI (which I can see in the logs does result in a call to SetCurrentSetpoint for the device in question)?

Ok scratch, just tried again and all of a sudden I get a log message! I did remove all other code I had in the block even though it was equally trivial but perhaps that was causing a problem.

Anyway seems the basic mechanism of getting the action to link now works, thanks.

AFAIK, this should work. You’ll have to stick to what’s provided by the hard coded implementation and cannot add variations, but it should work. In fact, I have a lot of virtual devices like this myself (well, not for thermostats, that I know are very hard coded in terms of UI).
Reusing standard device files has the advantage that mobile apps (and I belevie Imperihome, too) will render the device in its fullness.

Thanks everyone for their help. Got the basics of how to do this working now.

One remaining problem though:

I’m putting lua in to a separate lua file for the usual quoting complexity reasons. However the function I’ve declared there, which is called from the action in the implementation file, seems not able to execute a global function declared in my overall startup lua. I would have expected the should be no scoping issues with the lua code either in the <run> blocks or in separate lua files seeing global functions, am i missing something basic?

I usually bridge them. Something like this:

function startupPlugin(devNum)
	luup.log("OpenSprinkler Controller Plug-In starting...")
	OpenSprinkler1 = require("L_OpenSprinkler1")
	return OpenSprinkler1.startPlugin(devNum)
end

function updateStatus()
	OpenSprinkler1.updateStatus()
end

Used when you need to call them with callbacks, delays, etc, but can also be used in other cases.

Thanks therealdb, that worked. Didn’t realise I had to explicitly link them within the plugin.

1 Like