Page 1 of 1

SOLVED: Virtual Thermostat not flipping switch on HTTP POST

Posted: 28 Jan 2016 04:07
by Roemy
Hi,

I'm using Raspberry Pi 2 with RaZberry module.
I've been using openremotehelpers module for HTTP POST to get or set values.

I have created Virtual Thermostat, the default module that came with z-way-server.
Virtual thermostat is linked to a switch and a sensor that turns my cv/boiler on or off, depending on the temperature.

Now I wanted to set the level of this virtual thermostat with HTTP POST commands, that part is working.
All i have to do is opening the following url:

Code: Select all

http://192.168.1.30:8083/OpenRemote/SetVirtualThermostatLevel/ThermostatDevice_11/22
Now the virtual thermostat will be set to 22 Celsius.

Here is the URL i've added to set the level of the virtual device.
File: /opt/z-way-server/automation/modules/OpenRemoteHelpers/index.js

Code: Select all

case "SetVirtualThermostatLevel":
  var level = I;
  return this.controller.devices.get(N).set("metrics:level",level);
Now comes my problem.
When firing that URL it changes my virtual thermostats temperature but doesn't flip a switch, only after a few minutes.
I've found the reason why but i can't seem to figure this this part out.

File: /opt/z-way-server/automation/modules/ThermostatDevice/index.js has the following method ( self.checkTemp(); ) that runs when the level of the virtual thermostat has changed, sadly it only fires this method when you're changing it inside the UI of Z-way OR when you wait for a few minutes (2-8 min).

The method i'm talking about is called: self.checkTemp(); like i mentioned before.

Code: Select all

ThermostatDevice.prototype.checkTemp = function () {
    var vDevSwitch = this.controller.devices.get(this.config.switch),
        vDevSensor = this.controller.devices.get(this.config.sensor),
        vDev = this.vDev;
    
    if (vDevSwitch && vDevSensor && vDev) {
        if ((vDevSensor.get('metrics:level') + this.config.hysteresis < vDev.get('metrics:level')) && (vDevSwitch.get('metrics:level') == "off" && this.config.heaton || vDevSwitch.get('metrics:level') == "on" && !this.config.heaton)) {
            vDevSwitch.performCommand(this.config.heaton ? "on" : "off");
        }
        if ((vDevSensor.get('metrics:level') - this.config.hysteresis > vDev.get('metrics:level')) && (vDevSwitch.get('metrics:level') == "on" && this.config.heaton || vDevSwitch.get('metrics:level') == "off" && !this.config.heaton)) {
            vDevSwitch.performCommand(this.config.heaton ? "off" : "on");
        }
    }
}

What i'm trying to do is get the checkTemp() method to trigger from inside the OpenRemoteHelpers/index.js file.
Is it even possible for a method/function to be called from inside another module?

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 28 Jan 2016 13:49
by pz1
It doesn't seem appropriate to me to "abuse" OpenRemoteHelpers for this. OpenRemoteHelpers is intended and designed as a simplified interface to Z-Wave devices.
IMHO the functionality that you are seeking should be implemented in the VirtualThermostat and controlled via the ZAutomation API

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 28 Jan 2016 13:58
by Roemy
pz1 wrote:It doesn't seem appropriate to me to "abuse" OpenRemoteHelpers for this. OpenRemoteHelpers is intended and designed as a simplified interface to Z-Wave devices.
IMHO the functionality that you are seeking should be implemented in the VirtualThermostat and controlled via the ZAutomation API
I'm using OpenRemote on my iPad with a fully customized UI.
No abuse here cause the button that increase/decrease virtual thermostat are on openremote.
The fact I use openremotehelpers module is that I use all HTTP command from openremotehelpers.
Shouldn't be appropriate to use different module for HTTP url only for my virtual thermostat, cause every switch, sensor or label is all coming from the openremotehelpers module and are used on openremote.

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 29 Jan 2016 00:29
by pz1
Looked into this again and compared with the ORHelper code. I wasn't aware one could do the construct get(N).set("metrics:level",level). What you propose looks like the 'setter' counterpart of the existing metrics-command

So that could be made more generic to not only use the default level, but also other metric types.

Code: Select all

http://raspberryIP:8083/OpenRemote/SetMetrics/vDevName/metric/value

or in OpenRemote call notation

SetMetrics/N/I/S
all three parameters will be compulsary!
and in your case

Code: Select all

http://192.168.1.30:8083/OpenRemote/SetMetrics/ThermostatDevice_11/level/22
I'll look into this in more detail tomorrow and discuss with the Zway developers if we'll add this to ORHelpers in a future release.

I am aware this does not solve your problem with the on switch, but it does look like a good addition to the helpers.

Thanks for the inspiration

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 29 Jan 2016 03:24
by Roemy
I'm glad i've inspired you.
No worries, i'll wait for my answser sooner or later. :D

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 29 Jan 2016 14:59
by pz1
This is the first release of SetMetrics command for virtualDevices to automation/modules/OpenRemoteHelpers

Code: Select all

// Your "case" statements may go after this line, but before keyword default:  !

            case "SetMetrics":
               // All three parameters (N,I,S) are compulsory
               var S = params.shift();
               attrib = "metrics:" + I;
               this.controller.devices.get(N).set(attrib,S);
               return S;
Sofar I only tested thus on a DummyDevice of type SwitchMultilevel. Hope some more people are willing to test this.
I do hope it can be included in the next full release

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 30 Jan 2016 16:46
by Roemy
Solved my problem with using the same URL commands from the OpenRemoteHelpers module.
Here is what I did, if somebody is interested.

Just below this code in the following file:
/opt/z-way-server/automation/modules/ThermostatDevice/index.js

Code: Select all

    this.controller.devices.on(this.config.sensor, 'change:metrics:level', function() {
        self.checkTemp();
    });
Paste the following code:

Code: Select all

	//-----------------------------------------------------------------
	// Customized
	//-----------------------------------------------------------------
    ThermostatRemote = function(url, request) {
        var params = url.split("/");
        params.shift(); // shift empty string before first /
        var cmd = params.shift();
        var N = params.shift();
        var I = params.shift();

        switch(cmd) {
			case "CheckTemp":
				self.checkTemp();
                return "test";
				
			default:
				return "Error: Function " + cmd  + " is not defined in ThermostatDevice";
		}
	};
	ws.allowExternalAccess("ThermostatRemote", this.controller.auth.ROLE.USER); // login required
	//-----------------------------------------------------------------
Make sure it's in the ThermostatDevice.prototype.init = function (config) { function just before the }; of that function.

Now add the following code in the same file in the following function:
ThermostatDevice.prototype.stop = function () { just before ThermostatDevice.super_.prototype.stop.call(this);

Code: Select all

	//-----------------------------------------------------------------
	// Customized
	//-----------------------------------------------------------------
	ws.revokeExternalAccess("ThermostatRemote");
	ThermostatRemote = null;
	//-----------------------------------------------------------------
Now your file should be like this:

Code: Select all

/*** ThermostatDevice Z-Way HA module *******************************************

Version: 1.0.0
(c) Z-Wave.Me, 2014
-----------------------------------------------------------------------------
Author: Poltorak Serguei <ps@z-wave.me>
Description:
    Implements thermostat device based on temperature sensor and switch
******************************************************************************/

// ----------------------------------------------------------------------------
// --- Class definition, inheritance and setup
// ----------------------------------------------------------------------------

function ThermostatDevice (id, controller) {
    // Call superconstructor first (AutomationModule)
    ThermostatDevice.super_.call(this, id, controller);
}

inherits(ThermostatDevice, AutomationModule);

_module = ThermostatDevice;

// ----------------------------------------------------------------------------
// --- Module instance initialized
// ----------------------------------------------------------------------------

ThermostatDevice.prototype.init = function (config) {
    ThermostatDevice.super_.prototype.init.call(this, config);
	
    var self = this;

    this.vDev = this.controller.devices.create({
        deviceId: "ThermostatDevice_" + this.id,
        defaults: {
            deviceType: "thermostat",
            metrics: {
                scaleTitle:  this.config.scale === 'C' ? '°C' : '°F',
                level: this.config.scale === 'C' ? 18 : 65,
                min: this.config.scale === 'C' ? 5 : 41,
                max: this.config.scale === 'C' ? 40 : 104,
                icon: '',
                title: 'Thermostat Device ' + this.id
            }
        },
        overlay: {},
        handler: function (command, args) {
            self.vDev.set("metrics:level", args.level);
            self.checkTemp();
        },
        moduleId: this.id
    });
    
    this.controller.devices.on(this.config.sensor, 'change:metrics:level', function() {
        self.checkTemp();
    });
	
	//-----------------------------------------------------------------
	// Customized
	//-----------------------------------------------------------------
    ThermostatRemote = function(url, request) {
        var params = url.split("/");
        params.shift(); // shift empty string before first /
        var cmd = params.shift();
        var N = params.shift();
        var I = params.shift();

        switch(cmd) {
			case "CheckTemp":
				self.checkTemp();
                return "test";
				
			default:
				return "Error: Function " + cmd  + " is not defined in ThermostatDevice";
		}
	};
	ws.allowExternalAccess("ThermostatRemote", this.controller.auth.ROLE.USER); // login required
	//-----------------------------------------------------------------
};

ThermostatDevice.prototype.stop = function () {
    var self = this;

    this.controller.devices.off(this.config.sensor, 'change:metrics:level', function() {
        self.checkTemp();
    });

    if (this.vDev) {
        this.controller.devices.remove(this.vDev.id);
        this.vDev = null;
    }

	//-----------------------------------------------------------------
	// Customized
	//-----------------------------------------------------------------
	ws.revokeExternalAccess("ThermostatRemote");
    ThermostatRemote = null;
	//-----------------------------------------------------------------
	
    ThermostatDevice.super_.prototype.stop.call(this);
};

// ----------------------------------------------------------------------------
// --- Module methods
// ----------------------------------------------------------------------------

ThermostatDevice.prototype.checkTemp = function () {
    var vDevSwitch = this.controller.devices.get(this.config.switch),
        vDevSensor = this.controller.devices.get(this.config.sensor),
        vDev = this.vDev;
    
    if (vDevSwitch && vDevSensor && vDev) {
        if ((vDevSensor.get('metrics:level') + this.config.hysteresis < vDev.get('metrics:level')) && (vDevSwitch.get('metrics:level') == "off" && this.config.heaton || vDevSwitch.get('metrics:level') == "on" && !this.config.heaton)) {
            vDevSwitch.performCommand(this.config.heaton ? "on" : "off");
        }
        if ((vDevSensor.get('metrics:level') - this.config.hysteresis > vDev.get('metrics:level')) && (vDevSwitch.get('metrics:level') == "on" && this.config.heaton || vDevSwitch.get('metrics:level') == "off" && !this.config.heaton)) {
            vDevSwitch.performCommand(this.config.heaton ? "off" : "on");
        }
    }
}
Run http://zway_ip:8083/ThermostatRemote/CheckTemp/ and you'll see the text: "test" as output.
What this will do is fire the method checkTemp(), handy when changing the virtual thermostat temp remotely and checks temp immediately.

For as in OpenRemote create a command (HTTP) and select POST. ( Naming Example: CMD_CHECK_TEMP )
now fire the rule like: execute.command("CMD_CHECK_TEMP");

Re: Virtual Thermostat not flipping switch on HTTP POST

Posted: 30 Jan 2016 18:13
by pz1
Roemy wrote:Solved my problem with using the same URL commands from the OpenRemoteHelpers module.
Did you use the new OpenRemoteHelpers SetMetrics command that I posted here?
We are working on the release of an updated OpenRemoteHelpers very soon. In the future more modules will be available via the new On-line Apps mechanism instead of being packaged with the distro.