My Config Collection (OH 1.8 ONLY!) - Might help Someone

Hi, I’m learning your “HoneyWell Wifi Thermostat scripts for status” at post 4.
what is this location? http://10.1.100.23:10005/rest/items/IndTemp
Are you running the openhab at server http://10.1.100.23 ?
Why don’t you just leave it at script folder?
It seem you save the $powerstatus" also at http://10.1.100.23:10005/rest/items/HostBatteryPercentage
Thank you

Hello,

Yea, 10.1.100.23 was my openhab host. /rest is the rest api built into openhab. The rest api is the default location to have scripts like bash etc update your items in openhab.

Yes $powerstatus is from a bash script that talks to the openhab API.

“Why don’t you just leave it at script folder?” Not sure what you mean by this.

Hello,

For anyone looking for a cheap hosted IPv6 VM to play with check out http://ecare.cidcomm.com/cart.php

Hey Jay…
How do you controle wether to use geofencing or not. I doubt it´s optimal going for a walk and returning home, and then the garage door is opening? How to prevent that from happening?

Hi iam trying your scripts for the honeywell thermostat but i get the error below

11:25:08.790 [ERROR] [clipse.smarthome.io.net.exec.ExecUtil] - couldn't execute commandLine '/etc/tstat'
java.io.IOException: Cannot run program "/etc/tstat": error=2, No such file or directory
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048) [?:?]
	at java.lang.Runtime.exec(Runtime.java:620) [?:?]
	at java.lang.Runtime.exec(Runtime.java:450) [?:?]
	at java.lang.Runtime.exec(Runtime.java:347) [?:?]
	at org.eclipse.smarthome.io.net.exec.ExecUtil.executeCommandLine(ExecUtil.java:63) [118:org.eclipse.smarthome.io.net:0.10.0.oh230]
	at org.eclipse.smarthome.model.script.actions.Exec.executeCommandLine(Exec.java:43) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1085) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1060) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1046) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:991) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:143) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:223) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:446) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:227) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.runtime.internal.engine.ScriptImpl.execute(ScriptImpl.java:82) [141:org.eclipse.smarthome.model.script.runtime:0.10.0.oh230]
	at org.eclipse.smarthome.model.rule.runtime.internal.engine.ExecuteRuleJob.execute(ExecuteRuleJob.java:67) [138:org.eclipse.smarthome.model.rule.runtime:0.10.0.oh230]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [109:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [109:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
Caused by: java.io.IOException: error=2, No such file or directory
	at java.lang.UNIXProcess.forkAndExec(Native Method) ~[?:?]
	at java.lang.UNIXProcess.<init>(UNIXProcess.java:247) ~[?:?]
	at java.lang.ProcessImpl.start(ProcessImpl.java:134) ~[?:?]
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029) ~[?:?]
	... 28 more


Where do i have to place the tstat script? Actually the scripts!!
Thank you in advance.
ps. i am running openhab 2.3

Also when i am running the script tstat i get some errors.

Getting Data from MyTotalControl Website
Checking Indoor Temp
curl: (3) Illegal characters found in URL
28
Checking Heat Setpoint
curl: (3) Illegal characters found in URL
curl: (3) Illegal characters found in URL
21
Checking Heat On/Off Status
curl: (3) Illegal characters found in URL
1
Checking Fan Status
curl: (3) Illegal characters found in URL
None
Checking Hold Status
curl: (3) Illegal characters found in URL
1080
: numeric argument required

Any help appreciated.

Hi John,

These scripts are all for Debian Linux. are you running Debian Linux?

Also these scripts and code are for OH 1.8. 2.3 is completely redesigned so they most likely wont work.

I am on a raspberry with rasspbian jessie installed. The scripts seem to work individually but i get those errors.

Did you put all the custom scripts in the /etc folder? Its saying it cannot see them there.

Nothing. Wherever i try to put it i get the same error.

16:50:00.095 [ERROR] [clipse.smarthome.io.net.exec.ExecUtil] - couldn't execute commandLine '/etc/tstat'
java.io.IOException: Cannot run program "/etc/tstat": error=2, No such file or directory
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048) [?:?]
	at java.lang.Runtime.exec(Runtime.java:620) [?:?]
	at java.lang.Runtime.exec(Runtime.java:450) [?:?]
	at java.lang.Runtime.exec(Runtime.java:347) [?:?]
	at org.eclipse.smarthome.io.net.exec.ExecUtil.executeCommandLine(ExecUtil.java:63) [118:org.eclipse.smarthome.io.net:0.10.0.oh230]
	at org.eclipse.smarthome.model.script.actions.Exec.executeCommandLine(Exec.java:43) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1085) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1060) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1046) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:991) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:143) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:223) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:446) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:227) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) [139:org.eclipse.smarthome.model.script:0.10.0.oh230]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189) [158:org.eclipse.xtext.xbase:2.12.0.v20170519-0752]
	at org.eclipse.smarthome.model.script.runtime.internal.engine.ScriptImpl.execute(ScriptImpl.java:82) [141:org.eclipse.smarthome.model.script.runtime:0.10.0.oh230]
	at org.eclipse.smarthome.model.rule.runtime.internal.engine.ExecuteRuleJob.execute(ExecuteRuleJob.java:67) [138:org.eclipse.smarthome.model.rule.runtime:0.10.0.oh230]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [109:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [109:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
Caused by: java.io.IOException: error=2, No such file or directory
	at java.lang.UNIXProcess.forkAndExec(Native Method) ~[?:?]
	at java.lang.UNIXProcess.<init>(UNIXProcess.java:247) ~[?:?]
	at java.lang.ProcessImpl.start(ProcessImpl.java:134) ~[?:?]
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029) ~[?:?]
	... 28 more

When i try to run it from shell with

sudo bash tstat

the script runs but i get some errors in the script

Getting Data from MyTotalControl Website
Checking Indoor Temp
curl: (3) Illegal characters found in URL
28
Checking Heat Setpoint
curl: (3) Illegal characters found in URL
curl: (3) Illegal characters found in URL
21
Checking Heat On/Off Status
curl: (3) Illegal characters found in URL
1
Checking Fan Status
curl: (3) Illegal characters found in URL
None
Checking Hold Status
curl: (3) Illegal characters found in URL
1080
: numeric argument required

Looks like permissions partially. Run OH as root or change the folder permissions. chmod a=rwx /etc

I think i solved the problem with executeCommandLine(“sudo /etc/openhab2/scripts/tstat”) in the rule.

Now i am still having problem with refreshing the values in openhab as i get the error below when the script is executed.

Getting Data from MyTotalControl Website
Checking Indoor Temp
curl: (3) Illegal characters found in URL
28
Checking Heat Setpoint
curl: (3) Illegal characters found in URL
curl: (3) Illegal characters found in URL
21
Checking Heat On/Off Status
curl: (3) Illegal characters found in URL
1
Checking Fan Status
curl: (3) Illegal characters found in URL
None
Checking Hold Status
curl: (3) Illegal characters found in URL
1080
: numeric argument required

As you can see it retrieves the values from totalconnect but the values dont appear in openhab interface

Also when i try to send a curl post from terminal

curl --header "Content-Type: text/plain" --request POST --data "31" http://192.168.1.250:8080/rest/items/IndTemp

The item receives it normaly!!!
I am loosing my mind here!!!

Could be the incoming value from honeywell is messed up and feeding it to the script and breaking it.

Ok one step further. The script seems now to be working after some changes, i get the received commands to the items but the item state doesn’t change. i also get an error for ‘as DecimalType’ in the rule.
Here is how i changed the script

echo Checking Indoor Temp
TEMPSTATUS=$( grep "Indoor Temperature" $TEMPDATA | sed -n -e 's/^.*Indoor Temperature: //p')
curl --header "Content-Type: text/plain" --request POST http://192.168.1.250:8080/rest/items/IndTemp --data "$TEMPSTATUS"
echo $TEMPSTATUS

and here is the log from console

19:38:04.615 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'IndTemp' received command 28
19:38:04.756 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'IndHeat' received command 19
19:38:04.847 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Update Temp App': Could not cast NULL to org.eclipse.smarthome.core.library.types.DecimalType; line 180, column 27, length 28
19:38:04.968 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'IndHeatSet': Could not cast NULL to org.eclipse.smarthome.core.library.types.DecimalType; line 164, column 26, length 31
19:38:04.906 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'IndHeatSet' received command 19
19:38:05.472 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'IndHeaterStatus' received command 1
19:38:05.567 [INFO ] [smarthome.event.ItemStateChangedEvent] - LocalComputer_Memory_Used changed from 642 to 639
19:38:05.671 [INFO ] [smarthome.event.ItemStateChangedEvent] - LocalComputer_Cpu_Load changed from 35.4 to 51.9
19:38:05.778 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'IndHoldStatus' received command 1080

As you can see the items receive the command but nothing in the interface.

Finaly i think i got it working!!! The only thing that i couldnt figure out is the rule tha runs the tstat script every 5 min. It seems to be running but no changes to my items. i overcame the problem by creating a scheduled task with crontab.
Here are my config files for anyone interested using these scripts with openhab 2.3.

items file

// Honeywell Thermostat
Number 			IndHeat 			"Current Set Point [%.1f°C]" 								<temperature> 	(persist) 	
Number 			IndHoldStatus 		"Hold Status 	[MAP(thermostat2.map):%d]" 			<temperature> 	(persist)
Number 			IndHeaterStatus 	"Heat On/Off 	[MAP(thermostat.map):%d]" 					 		(persist)	
Number 			IndTemp 			"Indoor Temp [%.1f°C]" 							<temperature> 	(persist)	
Number 			SendTemp 			"[%.1f°C]" 														(persist) 	
Number 			IndHeatSet 			"Set Temp [%.1f°C]" 					<temperature> 	(persist)	
String 			IndHeatRes 			"Resume Schedule" 												 	(persist) { autoupdate="false",exec=">[ON:python /etc/openhab2/scripts/therm.py -x] >[OFF:python /etc/openhab2/scripts/therm.py -x]" }

sitemap file

Text label="Thermostat" icon="thermostat" {
			 Frame {			  
			 Text item=IndHoldStatus
			 Text item=IndHeaterStatus icon="heating"
			 //Text item=IndFanStatus
			 Text item=IndTemp
			 Text item=IndHeat
			 Setpoint item=IndHeatSet  minValue=16 maxValue=23 step=0.5
			 Switch item=IndHeatRes   label="Resume Schedule" mappings=[ON="Resume"] icon="Date"

Rules

//Honeywell Thermostat
// Send selected temperature to MyTotalConnectComfort Portal
rule "IndHeatSet"
when
    Item IndHeatSet received command
then
    SendTemp.sendCommand(IndHeatSet.state)
end


// Set Heat Setpoint 
rule "Send SetPoint to MyTotalConnectComfort Portal"
when
    Item SendTemp received command
then
    executeCommandLine(" /etc/openhab2/scripts/therm.py -h " + receivedCommand)
end


// Sync Setpoint with the set temp app
rule "Update Temp App"
when
    Item IndHeat received command
then
    IndHeatSet.postUpdate(IndHeat.state)
end

And the 2 scripts placed in etc\openhab2\scripts folder of my openhab2 installation

therm.py

#!/usr/bin/python

# By Brad Goodman
# http://www.bradgoodman.com/
# brad@bradgoodman.com

####################### Fill in settings below #######################

USERNAME="yourusername"
PASSWORD="yourpassword"
DEVICE_ID=deviceid

############################ End settings ############################

import urllib2
import urllib
import json
import datetime
import re
import time
import math
import base64
import time
import httplib
import sys
import getopt
import os
import stat
import subprocess
import string
    
AUTH="https://mytotalconnectcomfort.com/portal"

cookiere=re.compile('\s*([^=]+)\s*=\s*([^;]*)\s*')

def client_cookies(cookiestr,container):
  if not container: container={}
  toks=re.split(';|,',cookiestr)
  for t in toks:
    k=None
    v=None
    m=cookiere.search(t)
    if m:
      k=m.group(1)
      v=m.group(2)
      if (k in ['path','Path','HttpOnly']):
        k=None
        v=None
    if k: 
      #print k,v
      container[k]=v
  return container

def export_cookiejar(jar):
  s=""
  for x in jar:
    s+='%s=%s;' % (x,jar[x])
  return s



def get_login(action, value=None):
    
    cookiejar=None
    #print
    #print
    #print "Run at ",datetime.datetime.now()
    headers={"Content-Type":"application/x-www-form-urlencoded",
            "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Encoding":"sdch",
            "Host":"mytotalconnectcomfort.com",
            "DNT":"1",
            "Origin":"https://mytotalconnectcomfort.com/portal",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
        }
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com")
    conn.request("GET", "/portal/",None,headers)
    r0 = conn.getresponse()
    #print r0.status, r0.reason
    
    for x in r0.getheaders():
      (n,v) = x
      #print "R0 HEADER",n,v
      if (n.lower() == "set-cookie"): 
        cookiejar=client_cookies(v,cookiejar)
    #cookiejar = r0.getheader("Set-Cookie")
    location = r0.getheader("Location")

    retries=5
    params=urllib.urlencode({"timeOffset":"240",
        "UserName":USERNAME,
        "Password":PASSWORD,
        "RememberMe":"false"})
    #print params
    newcookie=export_cookiejar(cookiejar)
    #print "Cookiejar now",newcookie
    headers={"Content-Type":"application/x-www-form-urlencoded",
            "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Encoding":"sdch",
            "Host":"mytotalconnectcomfort.com",
            "DNT":"1",
            "Origin":"https://mytotalconnectcomfort.com/portal/",
            "Cookie":newcookie,
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
        }
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com")
    conn.request("POST", "/portal/",params,headers)
    r1 = conn.getresponse()
    #print r1.status, r1.reason
    
    for x in r1.getheaders():
      (n,v) = x
      #print "GOT2 HEADER",n,v
      if (n.lower() == "set-cookie"): 
        cookiejar=client_cookies(v,cookiejar)
    cookie=export_cookiejar(cookiejar)
    #print "Cookiejar now",cookie
    location = r1.getheader("Location")

    if ((location == None) or (r1.status != 302)):
        #raise BaseException("Login fail" )
        print("ErrorNever got redirect on initial login  status={0} {1}".format(r1.status,r1.reason))
        return


   # Skip second query - just go directly to our device_id, rather than letting it
    # redirect us to it. 

    code=str(DEVICE_ID)

    t = datetime.datetime.now()
    utc_seconds = (time.mktime(t.timetuple()))
    utc_seconds = int(utc_seconds*1000)
    #print "Code ",code

    location="/portal/Device/CheckDataSession/"+code+"?_="+str(utc_seconds)
    #print "THIRD"
    headers={
            "Accept":"*/*",
            "DNT":"1",
            #"Accept-Encoding":"gzip,deflate,sdch",
            "Accept-Encoding":"plain",
            "Cache-Control":"max-age=0",
            "Accept-Language":"en-US,en,q=0.8",
            "Connection":"keep-alive",
            "Host":"mytotalconnectcomfort.com",
            "Referer":"https://mytotalconnectcomfort.com/portal/",
            "X-Requested-With":"XMLHttpRequest",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
            "Cookie":cookie
        }
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com")
    conn.set_debuglevel(999);
    #print "LOCATION R3 is",location
    conn.request("GET", location,None,headers)
    r3 = conn.getresponse()
    if (r3.status != 200):
      print("Error Didn't get 200 status on R3 status={0} {1}".format(r3.status,r3.reason))
      return


    # Print thermostat information returned

    if (action == "status"):
    
        #print r3.status, r3.reason
        rawdata=r3.read()
        j = json.loads(rawdata)
        #print "R3 Dump"
        #print json.dumps(j,indent=2)
        #print json.dumps(j,sort_keys=True,indent=4, separators=(',', ': '))
        #print "Success:",j['success']
        #print "Live",j['deviceLive']
        print "Indoor Temperature:",j['latestData']['uiData']["DispTemperature"]
        #print "Indoor Humidity:",j['latestData']['uiData']["IndoorHumidity"]
        #print "Cool Setpoint:",j['latestData']['uiData']["CoolSetpoint"]
        print "Heat Setpoint:",j['latestData']['uiData']["HeatSetpoint"]
        print "Hold Until :",j['latestData']['uiData']["TemporaryHoldUntilTime"]
       # print "Status Cool:",j['latestData']['uiData']["StatusCool"]
        print "Status Heat:",j['latestData']['uiData']["StatusHeat"]
        #print "Status Fan:",j['latestData']['fanData']["fanMode"]
        return
    
    headers={
            "Accept":'application/json; q=0.01',
            "DNT":"1",
            "Accept-Encoding":"gzip,deflate,sdch",
            'Content-Type':'application/json; charset=UTF-8',
            "Cache-Control":"max-age=0",
            "Accept-Language":"en-US,en,q=0.8",
            "Connection":"keep-alive",
            "Host":"mytotalconnectcomfort.com",
            "Referer":"https://mytotalconnectcomfort.com/portal/",
            "X-Requested-With":"XMLHttpRequest",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
            'Referer':"/TotalConnectComfort/Device/CheckDataSession/"+code,
            "Cookie":cookie
        }


    # Data structure with data we will send back

    payload = {
        "CoolNextPeriod": None,
        "CoolSetpoint": None,
        "DeviceID": DEVICE_ID,
        "FanMode": None,
        "HeatNextPeriod": None,
        "HeatSetpoint": None,
        "StatusCool": 0,
        "StatusHeat": 0,
        "SystemSwitch": None
    }


    # Calculate the hold time for cooling/heating

#    t = datetime.datetime.now();

#    stop_time = ((t.hour+hold_time)%24) * 60 + t.minute
#    stop_time = stop_time/15


    # Modify payload based on user input

    if (action == "cool"):
      payload["CoolSetpoint"] = value
      payload["StatusCool"] = 1
      payload["StatusHeat"] = 1
      payload["CoolNextPeriod"] = 99
    
    if (action == "heat"):
      payload["HeatSetpoint"] = value
      payload["StatusCool"] = 1
      payload["StatusHeat"] = 1
      payload["HeatNextPeriod"] = 'null'

    if (action == "cancel"):
      payload["StatusCool"] = 0
      payload["StatusHeat"] = 0

    if (action == "fan"):
      payload["FanMode"] = value


    # Prep and send payload

    location="/portal/Device/SubmitControlScreenChanges"

    rawj=json.dumps(payload)
        
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com");
    conn.set_debuglevel(999);
    #print "R4 will send"
    #print rawj
    conn.request("POST", location,rawj,headers)
    r4 = conn.getresponse()
    if (r4.status != 200): 
      print("Error Didn't get 200 status on R4 status={0} {1}".format(r4.status,r4.reason))
      return
    else:
        print "Success in configuring thermostat!"
    #  print "R4 got 200"


def printUsage():
    print
    print "Cooling: -c temperature -t hold_time"
    print "Heating: -h temperature -t hold_time"
    print "Status: -s"
    print "Cancel: -x"
    print "Fan: -f [0=auto|1=on]"
    print
    print "Example: Set temperature to cool to 80f for 1 hour: \n\t therm.py -c 80 -t 1"
    print
    print "If no -t hold_time is provided, it will default to one hour from command time."
    print
    
    
def main():

    if sys.argv[1] == "-s":
        get_login("status")
        sys.exit()

    if sys.argv[1] == "-x":
        get_login("cancel")
        sys.exit()        
        
    if (len(sys.argv) < 3) or (sys.argv[1] == "-help"):
        printUsage()
        sys.exit()
        
    if sys.argv[1] == "-c":
        get_login("cool", sys.argv[2])
        sys.exit()

    if sys.argv[1] == "-h":
        get_login("heat", sys.argv[2])
        sys.exit()

    if sys.argv[1] == "-f":
        get_login("fan", sys.argv[2])
        sys.exit()        
        
if __name__ == "__main__":
    

############################ End settings ############################

 import urllib2
 import urllib
 import json
 import datetime
 import re
 import time
 import math
 import base64
 import time
 import httplib
 import sys
 import getopt
 import os
 import stat
 import subprocess
 import string
    
AUTH="https://mytotalconnectcomfort.com/portal"

cookiere=re.compile('\s*([^=]+)\s*=\s*([^;]*)\s*')

def client_cookies(cookiestr,container):
  if not container: container={}
  toks=re.split(';|,',cookiestr)
  for t in toks:
    k=None
    v=None
    m=cookiere.search(t)
    if m:
      k=m.group(1)
      v=m.group(2)
      if (k in ['path','Path','HttpOnly']):
        k=None
        v=None
    if k: 
      #print k,v
      container[k]=v
  return container

def export_cookiejar(jar):
  s=""
  for x in jar:
    s+='%s=%s;' % (x,jar[x])
  return s



def get_login(action, value=None, hold_time=0):
    
    cookiejar=None
    #print
    #print
    #print "Run at ",datetime.datetime.now()
    headers={"Content-Type":"application/x-www-form-urlencoded",
            "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Encoding":"sdch",
            "Host":"mytotalconnectcomfort.com",
            "DNT":"1",
            "Origin":"https://mytotalconnectcomfort.com/portal",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
        }
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com")
    conn.request("GET", "/portal/",None,headers)
    r0 = conn.getresponse()
    #print r0.status, r0.reason
    
    for x in r0.getheaders():
      (n,v) = x
      #print "R0 HEADER",n,v
      if (n.lower() == "set-cookie"): 
        cookiejar=client_cookies(v,cookiejar)
    #cookiejar = r0.getheader("Set-Cookie")
    location = r0.getheader("Location")

    retries=5
    params=urllib.urlencode({"timeOffset":"240",
        "UserName":USERNAME,
        "Password":PASSWORD,
        "RememberMe":"false"})
    #print params
    newcookie=export_cookiejar(cookiejar)
    #print "Cookiejar now",newcookie
    headers={"Content-Type":"application/x-www-form-urlencoded",
            "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Encoding":"sdch",
            "Host":"mytotalconnectcomfort.com",
            "DNT":"1",
            "Origin":"https://mytotalconnectcomfort.com/portal/",
            "Cookie":newcookie,
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
        }
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com")
    conn.request("POST", "/portal/",params,headers)
    r1 = conn.getresponse()
    #print r1.status, r1.reason
    
    for x in r1.getheaders():
      (n,v) = x
      #print "GOT2 HEADER",n,v
      if (n.lower() == "set-cookie"): 
        cookiejar=client_cookies(v,cookiejar)
    cookie=export_cookiejar(cookiejar)
    #print "Cookiejar now",cookie
    location = r1.getheader("Location")

    if ((location == None) or (r1.status != 302)):
        #raise BaseException("Login fail" )
        print("ErrorNever got redirect on initial login  status={0} {1}".format(r1.status,r1.reason))
        return


   # Skip second query - just go directly to our device_id, rather than letting it
    # redirect us to it. 

    code=str(DEVICE_ID)

    t = datetime.datetime.now()
    utc_seconds = (time.mktime(t.timetuple()))
    utc_seconds = int(utc_seconds*1000)
    #print "Code ",code

    location="/portal/Device/CheckDataSession/"+code+"?_="+str(utc_seconds)
    #print "THIRD"
    headers={
            "Accept":"*/*",
            "DNT":"1",
            #"Accept-Encoding":"gzip,deflate,sdch",
            "Accept-Encoding":"plain",
            "Cache-Control":"max-age=0",
            "Accept-Language":"en-US,en,q=0.8",
            "Connection":"keep-alive",
            "Host":"mytotalconnectcomfort.com",
            "Referer":"https://mytotalconnectcomfort.com/portal/",
            "X-Requested-With":"XMLHttpRequest",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
            "Cookie":cookie
        }
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com")
    #conn.set_debuglevel(999);
    #print "LOCATION R3 is",location
    conn.request("GET", location,None,headers)
    r3 = conn.getresponse()
    if (r3.status != 200):
      print("Error Didn't get 200 status on R3 status={0} {1}".format(r3.status,r3.reason))
      return


    # Print thermostat information returned

    if (action == "status"):
    
        #print r3.status, r3.reason
        rawdata=r3.read()
        j = json.loads(rawdata)
        #print "R3 Dump"
        #print json.dumps(j,indent=2)
        #print json.dumps(j,sort_keys=True,indent=4, separators=(',', ': '))
        #print "Success:",j['success']
        #print "Live",j['deviceLive']
        print "Indoor Temperature:",j['latestData']['uiData']["DispTemperature"]
        #print "Indoor Humidity:",j['latestData']['uiData']["IndoorHumidity"]
        #print "Cool Setpoint:",j['latestData']['uiData']["CoolSetpoint"]
        print "Heat Setpoint:",j['latestData']['uiData']["HeatSetpoint"]
        print "Hold Until :",j['latestData']['uiData']["TemporaryHoldUntilTime"]
        #print "Status Cool:",j['latestData']['uiData']["StatusCool"]
        print "Status Heat:",j['latestData']['uiData']["StatusHeat"]
        #print "Status Fan:",j['latestData']['fanData']["fanMode"]
        return
    
    headers={
            "Accept":'application/json; q=0.01',
            "DNT":"1",
            "Accept-Encoding":"gzip,deflate,sdch",
            'Content-Type':'application/json; charset=UTF-8',
            "Cache-Control":"max-age=0",
            "Accept-Language":"en-US,en,q=0.8",
            "Connection":"keep-alive",
            "Host":"mytotalconnectcomfort.com",
            "Referer":"https://mytotalconnectcomfort.com/portal/",
            "X-Requested-With":"XMLHttpRequest",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
            'Referer':"/TotalConnectComfort/Device/CheckDataSession/"+code,
            "Cookie":cookie
        }


    # Data structure with data we will send back

    payload = {
        "CoolNextPeriod": None,
        "CoolSetpoint": None,
        "DeviceID": DEVICE_ID,
        "FanMode": None,
        "HeatNextPeriod": None,
        "HeatSetpoint": None,
        "StatusCool": 0,
        "StatusHeat": 0,
        "SystemSwitch": None
    }


    # Calculate the hold time for cooling/heating

    #t = datetime.datetime.now();

    #stop_time = ((t.hour+hold_time)%24) * 60 + t.minute
    #stop_time = stop_time/15


    # Modify payload based on user input

    if (action == "cool"):
      payload["CoolSetpoint"] = value
      payload["StatusCool"] = 1
      payload["StatusHeat"] = 1
      payload["CoolNextPeriod"] = 'null'
    
    if (action == "heat"):
      payload["HeatSetpoint"] = value
      payload["StatusCool"] = 1
      payload["StatusHeat"] = 1
      payload["HeatNextPeriod"] = 'null'

    if (action == "cancel"):
      payload["StatusCool"] = 0
      payload["StatusHeat"] = 0

    if (action == "fan"):
      payload["FanMode"] = value


    # Prep and send payload

    location="/portal/Device/SubmitControlScreenChanges"

    rawj=json.dumps(payload)
        
    conn = httplib.HTTPSConnection("mytotalconnectcomfort.com");
    #conn.set_debuglevel(999);
    #print "R4 will send"
    #print rawj
    conn.request("POST", location,rawj,headers)
    r4 = conn.getresponse()
    if (r4.status != 200): 
      print("Error Didn't get 200 status on R4 status={0} {1}".format(r4.status,r4.reason))
      return
    else:
        print "Success in configuring thermostat!"
    #  print "R4 got 200"


def printUsage():
    print
    print "Cooling: -c temperature -t hold_time"
    print "Heating: -h temperature -t hold_time"
    print "Status: -s"
    print "Cancel: -x"
    print "Fan: -f [0=auto|1=on]"
    print
    print "Example: Set temperature to cool to 80f for 1 hour: \n\t therm.py -c 80 -t 1"
    print
    print "If no -t hold_time is provided, it will default to one hour from command time."
    print
    
    
def main():

    if sys.argv[1] == "-s":
        get_login("status")
        sys.exit()

    if sys.argv[1] == "-x":
        get_login("cancel")
        sys.exit()        
        
    if (len(sys.argv) < 3) or (sys.argv[1] == "-help"):
        printUsage()
        sys.exit()
        
    if sys.argv[1] == "-c":
        get_login("cool", sys.argv[2])
        sys.exit()

    if sys.argv[1] == "-h":
        get_login("heat", sys.argv[2])
        sys.exit()

    if sys.argv[1] == "-f":
        get_login("fan", sys.argv[2])
        sys.exit()        
        
if __name__ == "__main__":
    main()

tstat

#!/bin/bash
#
# Script by Jamie R. Cid
# jay@cidcomm.com
#
#Get data from MyTotalControl and send to OH. This grabs one copy of the data and stores it instead of doing it for every request below. That's how you get blocked ;)
echo Getting Data from MyTotalControl Website
/etc/openhab2/scripts/therm.py -s > /var/log/honeywell.log
TEMPDATA="/var/log/honeywell.log"
#
#
echo Checking Indoor Temp
TEMPSTATUS=$( grep "Indoor Temperature" $TEMPDATA | sed -n -e 's/^.*Indoor Temperature: //p')
curl --header "Content-Type: text/plain" -X POST  "http://192.168.1.250:8080/rest/items/IndTemp"  -d "$TEMPSTATUS"
echo $TEMPSTATUS
#
echo Checking Heat Setpoint
HEATSTATUS=$( grep "Heat Setpoint" $TEMPDATA | sed -n -e 's/^.*Heat Setpoint: //p')
curl --header "Content-Type: text/plain" -X POST "http://192.168.1.250:8080/rest/items/IndHeat" -d "$HEATSTATUS"
curl --header "Content-Type: text/plain" -X POST "http://192.168.1.250:8080/rest/items/IndHeatSet" -d "$HEATSTATUS"
echo $HEATSTATUS
#
echo Checking Hold Status
HOLDSTATUS=$( grep "Hold Until" $TEMPDATA | sed -n -e 's/^.*Hold Until : //p')
curl --header "Content-Type: text/plain" -X POST "http://192.168.1.250:8080/rest/items/IndHoldStatus" -d "$HOLDSTATUS"
echo $HOLDSTATUS
#
echo Checking Heat On/Off Status
HEATERSTATUS=$( grep "Status Heat" $TEMPDATA | sed -n -e 's/^.*Status Heat: //p')
curl --header "Content-Type: text/plain" -X POST "http://192.168.1.250:8080/rest/items/IndHeaterStatus" -d "$HEATERSTATUS"
echo $HEATERSTATUS
#
#
exit 0

honeywell

Sorry for the long post but i hope it will help anyone want to implement it to openhab 2.3
Many thanks to jcid1 for the original config.

Is there a command to set the thermostat to permanent hold?

Will this work with mulitple thermostats? I have system that has 3 zones.

Can anyone post what you have set up in your transformation maps? I have everything displaying and behaving properly but I can’t get my mapping straight. I keep getting errors saying it can’t map.