ConEd customers in NYC can order SmartAC kits for use with window AC units. Essentially, these are wifi-connected smart switches with an accompanying temperature-sensing remote. You set your window AC to its lowest setting (thereby ensuring it will always be “on”) and let the smart switch do the rest. When the smart switch turns the power back on, the window AC responds like a power failure and returns to its last setting (i.e. on). The remote senses the temperature in the room and allows you to turn the unit on/off and adjust the desired target temperature.
Unfortunately, ThinkEco is quite guarded with their API and have only opened it up to ConEd. As such, there is a single terrible app to control these devices remotely and no third party integrations (Alexa, Siri, Google Home). I set out to find a way to overcome this, so I’ll outline it here.
First, there is a wonderful plugin written by Dave Marquard which exposes your ThinkEco SmartAC units to Homebridge. While this does a fine job of generating Homekit / Siri integrations, I have no iOS devices so I needed to bring this into Home Assistant.
After some digging, I found that homebridge could be queried using HTTP calls which would return JSON answers. So let’s dive in!
I’m going to assume you have homebridge and home assistant installed. You don’t need the homebridge plugin for home assistant for the purposes of this tutorial.
Next, get the list of devices on your homebridge. Specifically, you need the aid
and iid
numbers for your SmartAC units. This post over on the homebridge github page helped a lot.
curl -X PUT http://IP:PORT/accessories --header "Content-Type:Application/json" --header "authorization: "XXX-XX-XXX"" -s > loghomekitaccessories.js
Note: throughout the rest of this tutorial, IP:PORT refers to the IP and port of your homebridge server.
Parsing through that output, I found that the aid
's for my three SmartAC units were 16, 17 and 18. All of the aid
's share a common list of iid
's which each represent the different change-able states:
iid:10
- indicates the current on/off state
iid:11
- change this to actually turn it on/off
iid:12
- the current thermostat temperature (i.e. the temperature in the room as sensed by the remote)
iid:13
- the target temperature to cool the room to
Warning: I have no idea if these will be the same for you. I sent GET and PUT requests to the different iid
's and matched the returns with the known values of my AC to figure this one out. Also, the output above provides some hints (min/max allowed values, whether the valuable to writeable or not, etc.).
Now we can set up some sensors, switches, sliders and automations to get the whole thing working.
sensors:
# Read the current temperature
- platform: rest
resource: http://IP:PORT/characteristics?id=18.12 # note the syntax here: 18 is the aid, 12 is the iid
name: Bedroom temperature
value_template: '{{ (value_json.characteristics[0].value * 1.8 + 32)|round(0)}}' # Converts the temperature to F
unit_of_measurement: "°F"
headers:
authorization: "XXX-XX-XXX" # This is your homebridge API password
Content-Type: "application/json"
# Check if the ACs are on or off
- platform: rest
resource: http://IP:PORT/characteristics?id=18.10
name: Bedroom state
value_template: '{% if value_json.characteristics[0].value == 2 %} On {% else %} Off {% endif %}' # The API returns "2" if it's on
headers:
authorization: "XXX-XX-XXX"
Content-Type: "application/json"
# Read what temperature the ACs are set to
- platform: rest
hide_entity: True
resource: http://IP:PORT/characteristics?id=18.13
name: Bedroom set temp
value_template: '{{ (value_json.characteristics[0].value * 1.8 + 32)|round(0)}}'
unit_of_measurement: "°F"
headers:
authorization: "XXX-XX-XXX"
Content-Type: "application/json"
Now the switches:
switch:
platform: command_line
switches:
bedroom_ac:
command_on: /usr/bin/curl -X PUT http://IP:PORT/characteristics --header "Content-Type:Application/json" --header "authorization:XXX-XX-XXX" --data "{\"characteristics\":[{\"aid\":18,\"iid\":11,\"value\":2}]}"
command_off: /usr/bin/curl -X PUT http://IP:PORT/characteristics --header "Content-Type:Application/json" --header "authorization:XXX-XX-XXX" --data "{\"characteristics\":[{\"aid\":18,\"iid\":11,\"value\":0}]}"
command_state: /usr/bin/curl -X GET http://IP:PORT/characteristics?id=18.11 --header "Content-Type:Application/json" --header "authorization:XXX-XX-XXX"
value_template: '{% if value_json.characteristics[0].value == 2 %} true {% else %} false {% endif %}'
friendly_name: Bedroom AC
Then I made a slider:
input_slider:
dining_room_temp_slider:
name: Bedoom Temperature
initial: 72
min: 50
max: 86
step: 1
I used the shell_command
component to send a PUT command actually change the target temperature of the AC:
shell_command:
set_bedroom_temp: /usr/bin/curl -X PUT http://IP:PORT/characteristics --header "Content-Type:Application/json" --header "authorization:XXX-XX-XXX" --data "{\"characteristics\":[{\"aid\":18,\"iid\":13,\"value\":{{ ((states.input_slider.bedroom_temp_slider.state | float -32 ) * 5/9) | round(1) }} }]}"
And finally, I set up some automations to make the slider actually do its job:
automation:
# This first automation responds to the slider and calls the shell command
- alias: "Set Bedroom Temp"
hide_entity: True
trigger:
- platform: state
entity_id: input_slider.bedroom_temp_slider
action:
service: shell_command.set_bedroom_temp
# This second automation responds to the the slider (and also runs once on startup) to override the "initial value" on the slider and set it to the actual value that the AC is set to now.
- alias: "bedroom input slider"
hide_entity: True
trigger:
- platform: homeassistant
event: start
- platform: state
entity_id: sensor.bedroom_set_temp
action:
service: input_slider.select_value
data_template:
entity_id: input_slider.bedroom_temp_slider
value: "{{ states.sensor.bedroom_set_temp.state | int }}"
I made a grouping in my groups.yaml
file so that these each display on the frontend neatly:
bedroom_ac:
name: Bedroom AC
entities:
- sensor.bedroom_temperature
- sensor.bedroom_set_temp
- input_slider.bedroom_temp_slider
- switch.bedroom_ac
And in the end I get a card like this:
I hope this helps someone else! I’m also sure there are more elegant ways to achieve all of this so please add your suggestions in the comments section. I’m fairly new to Home Assistant so I bet I could benefit from your wisdom.