Binding Radio Thermostat?

Tags: #<Tag:0x00007faeda3be7b0>

I have a thermostat from Radio Thermostat and was hoping to add this to my openHAB setup. I found this discussion (https://groups.google.com/forum/#!searchin/openhab/radiothermostat/openhab/mUxUm34k5fA/m3kMwqrA-0YJ) that talks about adding bindings for this thermostat. I check the files but didn’t find any that mentioned Radio Thermostat.

Do people just bind this with the ZWave addon? I thought that in order to use what he used in his example ({ radiothermostat = “bindingType=targetTemperature” }) I needed to have an addon name “radiothermostat” but I can’t find that anywhere.

Any help would be greatly appreciated. Thanks!

As far as I can tell from searching through the wiki and the officially released bindings the Radio Thermostat binding either never made it in as an officially supported binding or has been abandoned. If you have a model that supports z-wave I’m sure that is the approach most people use. The Wifi model appears to have a REST API so people with that model probably use the HTTP binding to interact with it on openHAB.

Thanks Rich, Eric mentioned on his post that he made a binding for it so I was trying to find it in his repo but couldn’t find where it was.

I’ll try using the HTTP binding and see how that goes. Thank you!

I emailed the author but I’ve not heard back so I’m using the HTTP binding too. How to return current temp from my thermostat? had some interesting ideas. My setup is below, works with OpenHAB v1.7.1.

items/ct50.items

/*
** WiFi Radio Thermostat CT50 3M-50
** Should work with CT-80, CT-100, etc.
**
** Based in information from:
**    * https://github.com/openhab/openhab/wiki/Explanation-of-items
**    * https://github.com/openhab/openhab/wiki/Http-Binding
**    * https://community.openhab.org/t/how-to-return-current-temp-from-my-thermostat/3141
**        * https://community.openhab.org/t/how-to-return-current-temp-from-my-thermostat/3141/8
**
** TODO Add notes to https://github.com/openhab/openhab/wiki/Samples-Binding-Config?
** TODO see what happened to radiothermostat bindings described in
** https://groups.google.com/forum/#!searchin/openhab/radiothermostat/openhab/mUxUm34k5fA/m3kMwqrA-0YJ

CT-50 has limited control/sensors (for example, no humidity). Sample JSON payload for reading current HEATING mode:

    {
        "temp": 69.50,
        "tmode": 1,
        "fmode": 0,
        "override": 0,
        "hold": 0,
        "t_heat": 55.00,
        "tstate": 0,
        "fstate": 0,
        "time": {
            "day": 5,
            "hour": 11,
            "minute": 18
        },
        "t_type_post": 0
    }

TODO/not-implemented:
  * hold
  * t_type_post
  * cooling target; t_cool (tmode=2)
*/


Group All
Group gHVAC         (All)

Group gHVAC_CT50        "House Heating/Cooling"      <temperature>   (gHVAC)

/*
** TODO set http caching up in openhab.cfg file to match URLs below
**
**      # configuration of WiFi Radio Thermostat CT50 3M-50
**      http:ct50-cache.url=http://192.168.11.39/tstat
**      # once per minute
**      http:ct50-cache.updateInterval=60000
*/
Number  HVAC_CT50_CurrentTemp       "Current Temperature [%.1f F]"      <temperature>   (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.temp)]" }
Number  HVAC_CT50_TargetHeatTemp    "Target Heat Temperature [%.1f F]"  <temperature>   (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.t_heat)]" }
String  HVAC_CT50_Mode              "Thermostat Mode [MAP(ct50_en.map):%s_prog]"        (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.tmode)]" }
String  HVAC_CT50_Override          "Override [%d]"                                     (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.override)]" }
String  HVAC_CT50_State             "HVAC State [MAP(ct50_en.map):%d]"                  (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.tstate)]" }
String  HVAC_CT50_FanMode           "Fan mode [MAP(ct50_fan_en.map):%d]"                (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.fmode)]" }
Number  HVAC_CT50_FanState          "Fan state [%d]"                                    (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.fstate)]" }
String  HVAC_CT50_DayTime           "DayTime [%s]"                                      (gHVAC_CT50) { http="<[ct50-cache:60000:JS(ct50_get_daytime.js)]" }

/*
String  HVAC_CT50_Day               "Day [%s]"                                          (gHVAC_CT50) { http="<[ct50-cache:60000:JSONPATH($.time.day)]" }
String  HVAC_CT50_Time              "Time [%s]"                                         (gHVAC_CT50) { http="<[ct50-cache:60000:JS(ct50_get_time.js)]" }

ct50_get_time.js:

    // Wrap everything in a function
    (function(json_str) {
        var
            data = JSON.parse(json_str);
        return data.time.hour.toString() + ':' + data.time.minute.toString();
    })(input)
    // input variable contains data passed by openhab
*/

Switch  HVAC_CT50_SetHeatTemp_55F   "Set Target Heat Temperature to 55F"    <temperature>   (gHVAC_CT50)
Switch  HVAC_CT50_SetHeatTemp_70F   "Set Target Heat Temperature to 70F"    <temperature>   (gHVAC_CT50)

rules/ct50.rules

rule "Set Heating Target Temperature"
when
    Item HVAC_CT50_TargetHeatTemp received command
then
    logInfo("HVAC", "HVAC_CT50_TargetHeatTemp received: " + receivedCommand)
    output = sendHttpPostRequest("http://192.168.11.39/tstat", "application/json", '{"tmode":1,"t_heat":' + receivedCommand + '}')
    logInfo("HVAC", "HVAC Command sent - output: " + output)
end



rule "Set Heating Target Temperature 55F"
when
    Item HVAC_CT50_SetHeatTemp_55F received command
then
    logInfo("HVAC", "HVAC_CT50_SetHeatTemp_55F received: " + receivedCommand)
    output = sendHttpPostRequest("http://192.168.11.39/tstat", "application/json", '{"tmode":1,"t_heat":55}')
    logInfo("HVAC", "HVAC Command sent - output: " + output)
end

rule "Set Heating Target Temperature 70F"
when
    Item HVAC_CT50_SetHeatTemp_70F received command
then
    logInfo("HVAC", "HVAC_CT50_SetHeatTemp_70F received: " + receivedCommand)
    output = sendHttpPostRequest("http://192.168.11.39/tstat", "application/json", '{"tmode":1,"t_heat":70}')
    logInfo("HVAC", "HVAC Command sent - output: " + output)
end

rule "Set Fan"
when
    Item HVAC_CT50_FanMode received command
then
    logInfo("HVAC", "HVAC_CT50_FanMode received: " + receivedCommand)
    output = sendHttpPostRequest("http://192.168.11.39/tstat/fmode", "application/json", '{"fmode":' + receivedCommand + '}')
    logInfo("HVAC", "HVAC Command sent - output: " + output)
end

rule "Set Thermostat Mode"
when
    Item HVAC_CT50_Mode received command
then
    logInfo("HVAC", "HVAC_CT50_Mode received: " + receivedCommand)
    output = sendHttpPostRequest("http://192.168.11.39/tstat", "application/json", '{"tmode":' + receivedCommand + '}')
    logInfo("HVAC", "HVAC Command sent - output: " + output)
end

sitemaps/ct50.sitemap

/*
** Sitemap for WiFi Radio Thermostat CT50 3M-50
**  See https://github.com/openhab/openhab/wiki/Explanation-of-Sitemaps
*/

sitemap house label="CT50 Thermostat"
{

    Frame label="Thermostat" {
        Text item=HVAC_CT50_DayTime
        /*
        Text item=HVAC_CT50_Day
        Text item=HVAC_CT50_Time
        */
        Text item=HVAC_CT50_CurrentTemp
        Text item=HVAC_CT50_TargetHeatTemp
        Text item=HVAC_CT50_Mode
        Text item=HVAC_CT50_Override
        Text item=HVAC_CT50_State
        Text item=HVAC_CT50_FanMode
        Text item=HVAC_CT50_FanState

        Setpoint item=HVAC_CT50_TargetHeatTemp label="Set target Heating temperature [%d F]" icon="temperature" step=1

        Switch item=HVAC_CT50_SetHeatTemp_70F mappings=[ON="70"]
        Switch item=HVAC_CT50_SetHeatTemp_55F mappings=[ON="55"]

        Switch item=HVAC_CT50_FanMode label="Fan" icon="settings" mappings=[0="Auto(Off)", 2="On"]
        Switch item=HVAC_CT50_Mode mappings=[0="Off", 1="Heat", 2="Cool", 3="Auto"]
    }

}

transform/ct50_en.map

0=OFF
0_prog=OFF
1_prog=Heating program
2_prog=Cool program
3_prog=Auto program
1=Heating
2=Cooling

transform/ct50_fan_en.map

0=OFF
2=On

transform/ct50_get_daytime.js

/*
** Parse JSON from WiFi Radio Thermostat CT50 3M-50
**  https://github.com/openhab/openhab/wiki/Transformations#java-script-transformation-service
*/


// Wrap everything in a function
(function(json_str) {
    var data = JSON.parse(json_str);
    // Hard coded English days of the week
    var day_description =   {
                        0: 'Monday',
                        1: 'Tuesday',
                        2: 'Wednesday',
                        3: 'Thursday',
                        4: 'Friday',
                        5: 'Saturday',
                        6: 'Sunday',
                    };

    //return data.time.day.toString() + ' ' + data.time.hour.toString() + ':' + data.time.minute.toString();
    data = data.time
    //return day_description[data.time.day] + ' ' + data.time.hour.toString() + ':' + data.time.minute.toString();

    // Prefix with leading zero
    return day_description[data.day] + ' ' + (data.hour <= 9 ? '0' : '') + data.hour.toString() + ':' + (data.minute <= 9 ? '0' : '') + data.minute.toString();
})(input)
// input variable contains data passed by openhab
3 Likes

Haven’t seen your email, probably caught up in spam filter…

Here’s what my setup looks like. And I too am using the http binding. As far as I know it’s the only way to talk to the model 50 as it’s wifi only. They do/did have other models that were zwave.

Items:

/* Thermostat */
Number Tstat_mode “System Status” { http="<[tstat:600000:JSONPATH($.tmode)]" }
Number Tstat_temp “Indoor Temp [%.1f °F]” { http="<[tstat:600000:JSONPATH($.temp)]" }
Number Tstat_SetpointH “Set Heat Temperature [%.1f °F]” { http="<[tstat:600000:JSONPATH($.t_heat)]" }
Number Tstat_SetpointC “Set A/C Temperature [%.1f °F]” { http="<[tstat:600000:JSONPATH($.t_cool)]" }
Number Tstat_Setpoint “Set Temperature [%.1f °F]”
Number Tstat_hold “Hold Status” { http="<[tstat:600000:JSONPATH($.hold)]" }
Number Tstat_fan “Fan Mode” { http="<[tstat:600000:JSONPATH($.fmode)]" }
DateTime Tstat_LastUpdate “Last contact [%1$tm-%1$td @ %1$tH:%1$tM]”

String Tstat2_rToday “Today [%s]” { http="<[tstat2:600000:JS(todayRuntime.js)]" }
String Tstat2_rYesterday “Yesterday [%s]” { http="<[tstat2:600000:JS(yesterdayRuntime.js)]" }

Rules:

// 3M50 Filtrete Thermostat Rules
rule “Records last thermostat update time”
when
Item Tstat_temp received update
then
postUpdate(Tstat_LastUpdate, new DateTimeType())
end

// Set HVAC Mode
rule “System Off”
when
Item Tstat_mode received command 0
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“tmode”:0}’)
end
rule “System Heat”
when
Item Tstat_mode received command 1
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“tmode”:1}’)
end
rule “System Cool”
when
Item Tstat_mode received command 2
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“tmode”:2}’)
end

// Get Current Heat/AC Target Temperature - load Setpoint
rule “New Target Temperature”
when
Item Tstat_mode received update
then
if (Tstat_mode.state == 1) {
Tstat_Setpoint.state = Tstat_SetpointH.state
}
if (Tstat_mode.state == 2) {
Tstat_Setpoint.state = Tstat_SetpointC.state
}
end

// Set Temperature
rule “Set Temperature Target”
when
Item Tstat_Setpoint received command
then
if (Tstat_mode.state == 1) {
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“a_heat”:’ + Tstat_Setpoint.state + ‘}’)
}
if (Tstat_mode.state == 2) {
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“a_cool”:’ + Tstat_Setpoint.state + ‘}’)
}
end

// Set Temperature Hold State
rule “Hold Disabled”
when
Item Tstat_hold received command 0
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“hold”:0}’)
end
rule “Hold Enabled”
when
Item Tstat_hold received command 1
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“hold”:1}’)
end

// Set Fan State
rule “Fan Auto”
when
Item Tstat_fan received command 0
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“fmode”:0}’)
end
rule “Fan On”
when
Item Tstat_fan received command 2
then
sendHttpPostRequest(“http://192.168.224.50:80/tstat”, “application/json”, ‘{“fmode”:2}’)
end

Sitemap:

  Text item=Tstat_temp icon="thermostat" {
  	Frame {
  		Switch item=Tstat_mode       mappings=[0="Off", 1="Heat", 2="Cool"]   icon="thermometer"  
  		Setpoint item=Tstat_Setpoint minValue=60 maxValue=80 step=1.0
  		Switch item=Tstat_hold       mappings=[0="No", 1="Yes"]  
  		Switch item=Tstat_fan        mappings=[0="Auto", 2="On"]   icon="fan"  
            Text item=Tstat2_rToday
            Text item=Tstat2_rYesterday
  		Text item=Tstat_LastUpdate //valuecolor=[Tstat_LastUpdate>120="orange", Tstat_LastUpdate>300="red"]
  		//Text item=Tstat2_Ystrdy
  	}
  }

Transform:

hvac1.map:
0=Off
1=Heat
2=Cool

hvac2.map:
0=Auto
2=On

hvac4.map:
0=Disabled
1=Enabled

todayRuntime.js:
(function(json) {
var datalog = JSON.parse(json);
return “” + datalog.today.heat_runtime.hour + "hrs, " +
datalog.today.heat_runtime.minute + “min”;
})(input)

yesterdayRunTime.js:
(function(json) {
var datalog = JSON.parse(json);
return “” + datalog.yesterday.heat_runtime.hour + "hrs, " +
datalog.yesterday.heat_runtime.minute + “min”;
})(input)

2 Likes

And here’s what the interface looks like:

1 Like

@p912s thanks for those.

Where did you get the fan icon from? That isn’t present in my OpenHAB installation.

I like the last contact date/time and the today/yesterday info! Great idea, I’m totally going to steal, I mean borrow that :smile:

I think last contact need “import org.openhab.core.library.types.*” at the head of the rules file to work?

The today/yesterday needs another cache entry in openhab.cfg (extract from mine below):

http:ct50-cache2.url=http://192.168.11.39/tstat/datalog
# once per 10 minutes
http:ct50-cache2.updateInterval=600000

For the setPoint heat/cool rule you can do both heat and cool in the same http request, at least on the the different firmware versions I’ve tried - which would simplify the rule slightly.

Where did you get the fan icon from? That isn’t present in my OpenHAB installation.
I’ve added quite a few icons to use in the sitemap. Google for png files to use and then save them to the webapps\images folder.

I think last contact need "import org.openhab.core.library.types." at the head of the rules file to work?*
That is correct.

The today/yesterday needs another cache entry in openhab.cfg (extract from mine below):
Yes it does, should have mentioned that. This is what I have in my binding.

# 3M/Filtrete 50 Thermostat - heating/cooling info 
http:tstat.url=http://192.168.224.50/tstat
# refresh every 10 minutes
http:tstat.updateInterval=600000

# 3M/Filtrete 50 Thermostat - run information
http:tstat2.url=http://192.168.224.50/tstat/datalog
# refresh every 1 hour
http:tstat2.updateInterval=600000

For the setPoint heat/cool rule you can do both heat and cool in the same http request, at least on the the different firmware versions I’ve tried - which would simplify the rule slightly.
And I probably will at some point. Because I couldn’t find functioning rules/uitems for this I played around a lot until I had a functioning system. And now that we’re in the heating season I’ve left it alone to see how well it works. And it works great!

At this point I haven’t made any changes to my system and it’s been flawlessly running the heat/lights in the house for a couple of months. Currently adding my zwave FirstAlert Smoke Detector. After that will be motion sensors for some lights. And in the spring taking control of the lawn sprinkling system.

It’s great to be able to control of these things from my phone/tablet/pc.

New to Openhab, coming from Vera. Having problems use the 2 set of files above with Openhab 2. Can’t seem to get any status from my ct50. Does anyone have a link to a repo or something with all the files needed?

I have two Ct50’s. Would love to see a binding, I’m no developer so I’d be willing to offer to be a tester. It would be two more things to migrate off my Vera.

Well, it appears this has come full circle. I wrote that original Radio Thermostat Binding a long time ago that was referenced in the first post of this thread. Never did much with it. I apologize if anyone tried to email me about it; it probably got lost in a bunch of other emails. Anyways, I took a stab at re-writing it last night for personal use as I’m starting to use OpenHAB again and still have my CT30.

Here’s the binding (you’ll need to build from source):
https://github.com/ejthill/openhab/tree/master/bundles/binding/org.openhab.binding.radiothermostat

I used this spec (which is for a CT50, but should also work with CT30 and CT80):

Here is my openhab.cfg:
radiothermostat:refresh=60000

Here are my items (take a look at that spec starting on page 4 to understand what these values mean):
Number TStat_ACool {radiothermostat="192.168.1.14/a_cool"} Number TStat_AHeat {radiothermostat="192.168.1.14/a_heat"} Number TStat_AMode {radiothermostat="192.168.1.14/a_mode"} Number TStat_FMode {radiothermostat="192.168.1.14/fmode"} Number TStat_FState {radiothermostat="192.168.1.14/fstate"} Number TStat_Hold {radiothermostat="192.168.1.14/hold"} Number TStat_ITCool {radiothermostat="192.168.1.14/it_cool"} Number TStat_ITHeat {radiothermostat="192.168.1.14/it_heat"} Number TStat_Override {radiothermostat="192.168.1.14/override"} Number TStat_TCool {radiothermostat="192.168.1.14/t_cool"} Number TStat_THeat {radiothermostat="192.168.1.14/t_heat"} Number TStat_Temp {radiothermostat="192.168.1.14/temp"} Number TStat_Time {radiothermostat="192.168.1.14/time"} Number TStat_TMode {radiothermostat="192.168.1.14/tmode"} Switch TStat_Refresh {radiothermostat="192.168.1.14/_refresh"} String TStat_LastConnTime {radiothermostat="192.168.1.14/_last_connection_time"}

And here’s a very quick stab at a simple sitemap (I’m sure someone can come up with something prettier than this):
Text item=TStat_Temp label="Temperature [%s]" Text item=TStat_FState label="Fan [MAP(fan.map):%s]" Selection item=TStat_TMode label="Thermostat Mode" mappings=[0=OFF, 1=HEAT, 2=COOL, 3=AUTO] Selection item=TStat_FMode label="Fan Mode" mappings=[0=AUTO, 1=CIRCULATE, 2=ON] Selection item=TStat_Hold label="Hold" mappings=[0=DISABLED, 1=ENABLED] Setpoint item=TStat_TCool label="Cool Temp [%s]" visibility=[TStat_TMode==2] minValue="66" maxValue="82" step="0.5" Setpoint item=TStat_THeat label="Heat Temp [%s]" visibility=[TStat_TMode==1] minValue="66" maxValue="82" step="0.5" Switch item=TStat_Refresh label="Refresh" mappings=[ON=REFRESH] Text item=TStat_LastConnTime label="Last Connection [%1$ta %1$tR]"

According to that spec, there may be some discrepancies between how all of those values are utilized between CT30/CT50/CT80, etc. As such, I made the binding provide everything as-is from the Radio Thermostat API. It will be up to some sitemap magic to polish it up. From reading the spec, it seems a_cool, t_cool, it_cool values may be utilized a little differently between versions.

Here’s the caveat: While I’m happy to provide this and polish up the initial implementation, I simply don’t have the time to be the de facto contact for everything. If this is ever going to make it into the main openhab repo, I’ll need someone to volunteer to be a co-author/tester/primary-contact/documentation-writer.

I’ll be out of town this weekend. If anyone is interested in this, I’ll be able touch base on Monday or Tuesday. In the meantime, feel free to dive into the new binding if you want.

-E

1 Like

Hi Eric T,

I have two CT80s that I would love to get into openhab. I’m willing to help with co-author/tester/primary-contact/documentation-writer!

I’m googling how to compile the binding now, and will start testing in next day or so.

Thanks for your work on this.

Eric J.

Cool! The CT80 may have some features my CT30 doesn’t, so let me know if you think there’s anything else that is important and should be included. Since I don’t have the hardware, I can try to develop to the API and have you test it out. Since the API is fairly simple, this would probably be workable for us to test a couple new features.

Here’s a link to get started if you have trouble building from source: http://ejthill.github.io/org.openhab.binding.radiothermostat-1.9.0-20160907-SNAPSHOT.jar

I’m not sure what the openHAB documentation says about how to build from source, but here’s any easy way to do it: Once you have downloaded the source, and you have Maven and Java JDK installed and properly setup, you should just need to do this from a command prompt:

cd path/to/source/of/openhab/ mvn clean install

That will take a while the first time you run it. Once it has run successfully, you should be able to find the radiothermostat jar at “path/to/source/of/openhab/bundles/binding/org.openhab.binding.radiothermostat/target/org.openhab.binding.radiothermostat-1.9.0-SNAPSHOT.jar”

Thanks for the pre-made jar binding - it seems to be working. I’ll have more details soon.

Can you please post your fan.map file? Thanks!

I am expecting delivery of a CT80 in the next few days, so I intend to add humidity control, etc. to the binding. I haven’t used maven, but it appears to be straightforward (I mainly work in .NET.)

Thanks for all you have done so far!

Eric-

I just submitted a pull request to add support for humidity, humidity setpoint, and humidity mode. Because I don’t have my thermostat yet, I can’t test this, but could you please check that the changes don’t break your CT30’s connection?

Also, @jorgy, could you test with your CT80s? I will test next week (hopefully,) once I have my thermostat installed.

Here is the pull request: https://github.com/ejthill/openhab/pull/1

Thanks!

Hey Mark,

Where did you find the documentation for t_humidity? This certainly won’t break anything on my CT30, but from the documentation I have, I don’t think that value will be populated with anything on a CT80, either.

  • I see thumidity without an underscore in the docs I have. Is that what you’re after?
  • All of the humidity values live in different resources outside of /tstat

I’ll try to look at this in more detail tonight.

I suppose I should also add support for save_enery, dehumidifier, and ext_dehumidifier as well. Is there anyone who would be able to help test those functions?

I don’t want to turn this into a java hand-holding thread, but I’m more of a UNIX guy and less of a developer. I did the git clone and then the mvn command but got an error:

Once I have my environment set up I can test my CT80 with the latest code.

http://pastebin.com/aJtx75ps

Not a problem. That’s a pretty cryptic Java error, so I don’t blame you. It’s pretty much just saying it couldn’t load a class. The root of the problem is “Unsupported major.minor version 51.0”. 51.0 means a class is compiled with Java 7 and you’re using an earlier JDK. If you have JDK 8 or JDK 7 installed, it’s likely that mvn is using another installation. “mvn -version” will tell you which local java installation it’s picking up. Fix that, and you should be able to compile.