Guys,
I've spent the weekend looking a various C++ libraries for setting up web services.
Wow! Nightmare
Not sure I have a decent way forward yet, some are very elaborate and look like they may bring challenges down the line when cross compiling.
Still, leave it with me and don't expect anything too soon
Anyway, I've just realised that I'd coded up a bit of bi-directional code without sharing it.
The code below monitors a Domoticz dummy switch and overrides all the radiators when the switch is on.
May help someone.
I use it to drive all the radiators to ON when using my woodburner and the hot water tank is full of hot water.
Prevents overheating the water.
Code: Select all
/*
V0.1.10, 14/09/2015 - MAX!Buddy Script: Check for Domoticz virtual switch being operated and force all radiators on and send a warning eMail
The Domoticz ID for the 'Override Radiators ON' virtual switch is 168 - will be different for each system
**** WARNING - relies on the correct Date / Time being held on the Cube (worth checking)
**** there can be errors if you are using in a non German country due to the time difference
**** I've added a Time Difference variable to help keep the times in sync.
Uses a file written to disc to record the last time the On command was sent to the cube.
Too many commands sent in an hour will prevent subsequent commands being sent.
*/
function getInfo(info) {
info.name = 'Domoticz Radiator Override v2.0';
info.description = 'Open all radiators when the monitored Domoticz switch is ON';
info.interval = 300; // 300 (5 mins)
}
// Declare variables
var IP = '192.168.1.14'; // IP address of Domoticz
var Port = '8080'; // Port of Domoticz
var domoticzID = 168; // ID of Domoticz switch called 'Override Radiators ON' that will be monitored for change
var domoticzSwitch = 0; // State of monitored Domoticz switch 0 = OFF 1 = ON
var TimeDifference = 0; // Minutes time value that can be used to match cube time with local time in case they are different
var boostDuration = 240; // Boost duration in minutes
var debuglevel = 2; // 1 or 2 possible 1 = Send operation messages via email 2 = additionally write to file "/Users/<USER>/AppData/Roaming/MAXBuddy/logs/ScriptLogs/DomoticzRadiatorOverride.log"
var URLReturn = ""; // holds response from the JSON call to Domoticz (long string)
var URLChop =""; // holds the useful data from URLReturn
var rooms = 0; // rooms value
// write out log information
function debug_(str){
var file = java.io.File("/Users/Kevin/AppData/Roaming/MAXBuddy/logs/ScriptLogs/DomoticzRadiatorOverride.log");
var datumlog = new Date;
logDate = datumlog.toLocaleString();
str = logDate +" | "+ str;
Packages.org.apache.commons.io.FileUtils.write(file, str+"\r\n",null,true);
debug(str); }
// Manipulate the file that holds the last updated value (held as epoch time - mS since 1970 unix time)
function timeFile(rw,timeValue){
var file = java.io.File("/Users/Kevin/AppData/Roaming/MAXBuddy/logs/ScriptLogs/DomoticzRadiatorOverride.time");
if (rw=="r") { //read the file
var fileTime = Packages.org.apache.commons.io.FileUtils.readFileToString(file, "UTF-8");
return fileTime;
}
if (rw=="w") { //write to the file
timeValueS = timeValue.toString();
Packages.org.apache.commons.io.FileUtils.write(file, timeValueS,null,false);
}
}
// perform the JSON get action to interigate the Domoticz web server and return the data string
function getJSON(RID, Type) {
if (Type == 1) {
URLString = 'http://'+IP+':'+Port+ '/json.htm?type=devices&rid='+RID;
} else {
URLString = 'http://'+IP+':'+Port+ '/json.htm?type=command¶m=getuservariable&idx='+RID;
}
var url = new URL( URLString),
outputStream,
out;
URLconnection = url.openConnection();
URLconnection.setRequestMethod('GET');
URLconnection.setReadTimeout(5000);
URLconnection.setDoOutput(true);
URLconnection.setRequestProperty('Content-type', 'application/json');
inputstream = URLconnection.getInputStream();
instream = new InputStreamReader(inputstream);
inbuffer = new BufferedReader(instream);
response = new StringBuffer();
while ((inputLine = inbuffer.readLine()) != null) {
response.append(inputLine);
}
inbuffer.close();
//print result
//debug(response.toString());
RespStr=response.toString();
RespStr=RespStr.replace(' ','');
return RespStr
}
// Seperate the switch state information from the returned URL string
function GetField (RawData, Field) {
Datalength=Field.length
DataIndex=RawData.indexOf('"'+Field+'"')
Param=RawData.substring(DataIndex+Datalength+3,RawData.indexOf(',',DataIndex+7));
return Param
}
var states = new Array();
// Send email
function notify(EmailTitle, text) {
buddy.sendEmail(
"mail.server.com", // SMTP Server
"[email protected]", // SMTP Account
"password", // SMTP Password
"[email protected]", // From address
"[email protected]", // To address
EmailTitle, //"Email Title",
text // "Email body text"
);
}
// Polls cube for all Radiators and turns them on until boostStop time
function TurnRadiatorsOn(boostStop) {
rooms = connection.getLastState().getRooms();
for (var i = 0; i < rooms.size(); i++ ) {
var room = rooms.get(i);
var devices = room.getDevices();
var RoomID = room.getId();
for ( var j = 0; j < devices.size(); j++ ) {
var device = devices.get(j);
var devicename = device.getName()
if( "HeatingThermostat" == device.getDeviceType() ) {
if (debuglevel >1) {
var devicename = device.getName();
var DeviceTemp= device.getState().getMeasuredTemperature();
debug_(" "+devicename+" Temp: "+DeviceTemp+" C (RoomID:"+RoomID+") Radiator overriddden to "+boostStop);
}
buddy.setRoomMode(RoomID, "TEMPORARY", new Array("EIN", boostStop.getTime()) ); // Opens the valve in Temporary mode until boostStop expiry time
}
}
}
if (debuglevel >0) {
var status= "The Domoticz Heating Override switch has been operated. Boosting all radiators On for "+boostDuration+" Minutes.";
notify("Woodburner heating overide started", status);
}
if (debuglevel >1) debug_(" Email sent");
}
function run() {
// set up http requirements
URL = java.net.URL,
InputStreamReader = java.io.InputStreamReader,
BufferedReader = java.io.BufferedReader,
StringBuffer = java.lang.StringBuffer;
var now = new Date(); // comes from PC so may not agree with cube time that seems to work in German time
boostDuration = boostDuration + TimeDifference; // add difference between PC and German time
var boostStop = new Date(now.getTime() + boostDuration * 60000);
// Call Domoticz and get the state of the monitored switch
URLReturn = getJSON(domoticzID, 1);
URLChop = GetField(URLReturn,"Status");
if (URLChop =='"On"') domoticzSwitch = 1;
/*
if (debuglevel >1) {
debug_(" Domoticz switch state is: "+URLChop);
debug_(" domoticzSwitch value is: "+domoticzSwitch);
}
*/
var oldTime = timeFile("r",""); // get the last Radiator on time
var nowTime = Date.now(); // get current time (epoch)
var checkDelay = boostDuration - 6; // only re run the radiator process 6 minutes (script run time plus one minute) before the end of the "On" period
checkDelay = checkDelay * 60 * 1000 // comvert to milliseconds
//debug_("checkDelay value in Ms is: "+checkDelay);
//debug_("nowTime value in Ms is: "+nowTime);
//debug_("oldTime value is: "+oldTime);
if (domoticzSwitch > 0 ) { // Let's go, the Domoticz switch is on
if (debuglevel >1) { // print the header to the log file
debug_( "");
debug_( "--------------------------------------------------");
debug_( " Information:");
debug_( " Boost stop time: "+boostStop);
debug_( " Boost Duration: "+(boostDuration - TimeDifference)+" Min.");
//debug_( " ");
}
radDifference = nowTime - parseInt(oldTime);
if (radDifference > checkDelay){ // Have we checked within the checkDelay time?
// nope, we need the send an On signal to the radiators
TurnRadiatorsOn(boostStop);
timeFile("w",nowTime); // update the last time the radiators were switched On
}else{ // too early to resend the Cube a command
if (debuglevel >1) {
debug_(" On Signal already sent to Radiators "+Math.ceil(radDifference / 60 / 1000)+ " minutes ago.");
}
}
} // end of domoticzSwitch
} //end of run
To further atone for my ommisions, here is a script (found on the net somewhere) I run once a day to check battery state and email issues.
Code: Select all
// Adjust this function as necessary:
function notify(body) {
buddy.sendEmail(
// !!!!!
// Adjust these values as necessary:
// !!!!!
"mail.server.com", // SMTP Server
"[email protected]", // SMTP Account
"password", // SMTP Password
"[email protected]", // From address
"[email protected]", // To address
//------------------------------------------------------------------------//
"Max!Cube Error", //"TITLE OF EMAIL",
//"room: " + room + "\u000a" + "Device: " + device.getName() + "\u000a" + "Status: " + status // "CONTENT OF EMAIL"
body
);
}
function getDateTime() {
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth()+1;
var day = now.getDate();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
if(month.toString().length == 1) {
var month = '0'+month;
}
if(day.toString().length == 1) {
var day = '0'+day;
}
if(hour.toString().length == 1) {
var hour = '0'+hour;
}
if(minute.toString().length == 1) {
var minute = '0'+minute;
}
if(second.toString().length == 1) {
var second = '0'+second;
}
// var dateTime = year+'/'+month+'/'+day+' '+hour+':'+minute+':'+second;
var dateTime = day+'/'+month+'/'+year+' '+hour+':'+minute+':'+second;
return dateTime;
}
function debug_(str)
{
var file = java.io.File("/Users/Kevin/AppData/Roaming/MAXBuddy/logs/ScriptLogs/BatteryAndRadio.log");
str = getDateTime() +" - "+ str;
Packages.org.apache.commons.io.FileUtils.write(file, str+"\r\n",null,true);
debug(str);
}
function getInfo(info) {
// Display Name in the MAX ! Buddy settings
info.name = "eMail if battery is low or radio contact is lost";
// Description of the script
info.description = "Sends an email when the battery of an appliance ( wall thermostat , window contact or heater thermostat ) is low or radio contact is broken. - V0.1.0 Runs every 8 hours";
// Execution interval of the script : Every 8 hours
info.interval = 28800; //28800
}
var states = new Array();
function run() {
var debuglevel = 1; // 1 or 2 possible 1 = Send error messages via email 2 = additoinally write to file "/Users/Kevin/AppData/Roaming/MAXBuddy/logs/BatteryAndRadio.log"
var body = "";
var fail = 0;
if (debuglevel > 1) debug_("--------------------------------------")
body = body + "--------------------------------------\u000a";
var rooms = connection.getLastState().getRooms();
for (var i = 0; i < rooms.size(); i++ ) {
var room = rooms.get(i);
var devices = room.getDevices();
var room = room.getName();
if (debuglevel > 1) debug_(" Room: " + room);
body = body + " Room: " + room + "\u000a";
for ( var j = 0; j < devices.size(); j++ ) {
var device = devices.get(j);
var devicename = device.getName()
if (debuglevel > 1) debug_(" " + devicename + ":");
body = body + " " + devicename + "\u000a";
//Verification of the wall thermostats
if( "WallMountedThermostat" == device.getDeviceType() ) {
var batteryState = device.getState().isBatteryLow();
if(batteryState == true ) {
if (debuglevel > 1) debug_(" Battery is low!");
fail = 1;
body = body + " Battery is low!\u000a";
} else if(batteryState == false ) {
if (debuglevel > 1) debug_(" Battery ok");
body = body + " Battery ok\u000a";
}
var transmitState = device.getRadioState();
if(transmitState == "Error") {
if (debuglevel > 1) debug_(" Lost Radio Contact!");
fail = 1;
body = body + " Lost Radio Contact!\u000a";
} else if(transmitState == "Ok") {
if (debuglevel > 1) debug_(" Radio Contact ok");
body = body + " Radio Contact ok\u000a";
}
//Checking the window contacts
} else if( "ShutterContact" == device.getDeviceType() ) {
var devicename = device.getName();
var batteryState = device.getState().isBatteryLow();
if(batteryState == true ) {
if (debuglevel > 1) debug_(" Battery is low!");
fail = 1;
body = body + " Battery is low!\u000a";
} else if(batteryState == false ) {
if (debuglevel > 1) debug_(" Battery ok");
body = body + " Battery ok\u000a";
}
var transmitState = device.getRadioState();
if(transmitState == "Error") {
if (debuglevel > 1) debug_(" Lost Radio Contact!");
fail = 1;
body = body + " Lost Radio Contact!\u000a";
} else if(transmitState == "Ok") {
if (debuglevel > 1) debug_(" Radio Contact ok");
body = body + " Radio Contact ok\u000a";
}
//Verification of heating thermostats
} else if( "HeatingThermostat" == device.getDeviceType() ) {
var devicename = device.getName();
var batteryState = device.getState().isBatteryLow();
if(batteryState == true ) {
if (debuglevel > 1) debug_(" Battery is low!");
fail = 1;
body = body + " Battery is low!\u000a";
} else if(batteryState == false ) {
if (debuglevel > 1) debug_(" Battery ok");
body = body + " Battery ok\u000a";
}
var transmitState = device.getRadioState();
if(transmitState == "Error") {
if (debuglevel > 1) debug_(" Lost Radio Contact!");
fail = 1;
body = body + " Lost Radio Contact!\u000a";
} else if(transmitState == "Ok") {
if (debuglevel > 1) debug_(" Radio Contact ok");
body = body + " Radio Contact ok\u000a";
}
var radState = device.getRadioState();
if(radState == "Error") {
if (debuglevel > 1) debug_(" Disturbed radio link!");
fail = 1;
body = body + " Disturbed radio link!\u000a";
} else if(radState == "Ok") {
if (debuglevel > 1) debug_(" Radio Link ok");
body = body + " Radio Link ok\u000a";
}
}
}
if (debuglevel > 1) debug_("--------------------------------------")
body = body + "--------------------------------------\u000a";
}
if(fail != 0) {
if (debuglevel > 0) debug_("At least one device failed. Sending error mail...");
notify(body);
}
}
All the best
Kevin