Closed oroce closed 6 years ago
Hi Robert,
Thank you for your interest in my project. You are correct, I intend to create a library (and some front-ends for it [Windows, Mac, Android]) that mimic the functionality of the "official" Gree Smart app. Currently, as you can see, the project is in a very early state, but I'm working on it as my time allows.
I did not try to contact the manufacturer, but I did some research on the Internet to find details of the protocol without any luck, so I decided to find out how the Android app works. After analyzing the network traffic with Wireshark, I decided to disassemble the application (there are several, even online tools to do that) and reverse-engineered the protocol from that. It's a pretty basic, JSON-based protocol with some encryption. It uses AES-128 ECB to encode the data parts of the packet. The application has a master key which is used to initiate communication with a specific AC unit. In this process there is a binding phase where the application pairs with the unit and gets a device key from it. After binding, this unit key is used to encrypt and decrypt the packages.
The network part of the protocol uses UDP on port 7000, but my partial implementation currently works only if you set up the AC unit and it's connected to the local network. There is no option to initiate direct WiFi connection to the unit at the moment. The communication begins with a scanning phase where a scan packet is broadcasted on the local network. All the online units reply to that with a description packet which is encypted with the master key. In the response there is a device ID, which is used to address a specific unit. After scanning, you must bind the unit to get the device's unique AES key and from that point, you can send status request and update packets encrypted with that key.
Tamas
Hey Tamas,
wow thanks for detailed explanation. (I love these chinese manufacturers, i really doubt that this is the simplest solution to provide secure connection between an app and an AC unit.)
I was trying to understand your implementation, can it happen that you forgot to add src/deviceviewmodel.cpp
and src/deviceitem.cpp
to your repository?
Cheers
Hi,
Probably I forgot to add them, but the basic implementation can be found in GreeLib/src/devicefinder.cpp
and GreeLib/src/device.cpp
. DeviceFinder
does the initial scanning and the binding, Device
manages the AC unit. You can find some packet creator functions in protocolutils.cpp
.
I have just updated the library which now can give you the device parameters in a more digestible format with some nice methods. I have also mapped some numeric values to certain states of the fan, mode, swing etc, but there are a handful of values that my device doesn't seem to use. Maybe you should check the library with your device if it uses them.
It'd be more than welcome if you'd create a pull request with some new mappings. 😀
Wow thanks.
In the meantime I started playing with my AC and started reimplementing this library as a nodejs module but my goal is adding to home assistant, but node is the language which I'm most experienced with.
I'm happy to create a pull request once I'm familiar enough with the communication between the app and the AC.
Now I was able to get the status of the AC: https://github.com/oroce/node-gree-smart/pull/1
Basically this is what I received from the unit:
{
"id": "f4911e053a74",
"name": "1e053a74",
"address": "192.168.1.113",
"port": 7000,
"bound": true,
"props": {
"Pow": 0,
"Mod": 1,
"SetTem": 20,
"WdSpd": 3,
"Air": 0,
"Blo": 0,
"Health": 0,
"SwhSlp": 0,
"Lig": 1,
"SwingLfRig": 0,
"SwUpDn": 1,
"Quiet": 0,
"Tur": 0,
"StHt": 0,
"TemUn": 0,
"HeatCoolType": 0,
"TemRec": 0,
"SvSt": 0
},
"key": "<--key-->"
}
and in the meantime, I disassembled the app and started figuring out how can we send commands to the unit.
Can you play with the values using the remote control or the android application and see which variable is changed?
I already captured the device control packet and implementing it in the library right now. There is also a UI for device testing in the GreeRemoteQt
application.
I did, if I turn on the unit using the app, the Pow
changes to 1
.
update: just tried to change the temperature (SetTem
got updated), then the up and down (the SwUpDn
got updated).
so reading the device's status definitely works.
If you see device.h, you can find some values that I mapped already.
awesome, tomorrow I'm gonna continue playing with mine and report back here the results.
Setting the temperature is done via the following pack:
pack: {
"opt": ["TemUn", "SetTem"],
"p": [0, 27],
"t": "cmd"
}
TemUn
seems to be the temperature unit, 0 for Celsius, 1 for Fahrenheit and obviously SetTem
is the temperature value.
If the command is executed successfully, the response pack should look like this:
pack: {
"t": "res",
"mac": "<--- MAC --->",
"r": 200,
"opt": ["TemUn", "SetTem"],
"p": [0, 27],
"val": [0, 27]
}
Accordingly, you can use these packets for the other parameters you see in the status packet.
It works. I tried it this morning, and the temperature was set to 27
I made a dummy server to simulate the AC unit: https://github.com/oroce/node-gree-smart/pull/3/files
I'm playing with the mobile app to figure out how to change things, so far I have
{
opt: ['Pow'],
p: [1],
t: 'cmd'
}
{
opt: ['Pow'],
p: [0],
t: 'cmd'
}
low
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 1, 0, 0, 0 ],
t: 'cmd'
}
medium low
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 2, 0, 0, 0 ],
t: 'cmd'
}
medium
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 3, 0, 0, 0 ],
t: 'cmd'
}
medium high
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 4, 0, 0, 0 ],
t: 'cmd'
}
high
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 5, 0, 0, 0 ],
t: 'cmd'
}
Auto
windspeed:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 3, 0, 0, 0 ],
t: 'cmd'
}
turbo
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 5, 0, 1, 0 ],
t: 'cmd'
}
quiet
:{
opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ],
p: [ 1, 2, 0, 0 ],
t: 'cmd'
}
{
opt: [ 'SwUpDn' ],
p: [ 0 ],
t: 'cmd'
}
0 // blowing air to the ceiling, upside
10
11
1 // full range
{
opt: [ 'Air' ],
p: [ 1 ],
t: 'cmd'
}
To turn it off set p
to 0
{
opt: [ 'Blo' ],
p: [ 1 ],
t: 'cmd'
}
To turn it off set p
to 0
{
opt: [ 'Health' ],
p: [ 1 ],
t: 'cmd'
}
To turn it off set p
to 0
{
opt: [ 'Lig' ],
p: [ 1 ],
t: 'cmd'
}
To turn it off set p
to 0
{
opt: [ 'SwhSlp', 'SlpMod' ],
p: [ 1, 1 ],
t: 'cmd'
}
{
opt: [ 'SvSt', 'WdSpd', 'Quiet', 'Tur', 'SwhSlp', 'SlpMod' ],
p: [ 1, 0, 0, 0, 0, 0 ],
t: 'cmd'
}
Turning off at 20:40 on Tuesday and Friday
{
"cmd": [
{
"mac": [
"foo-mac"
],
"opt": [
"Pow"
],
"p": [
0
]
}
],
"enable": 0,
"hr": 20,
"id": 0,
"min": 40,
"name": "5363686564756c65",
"sec": 0,
"t": "setT",
"tz": 1,
"week": [
0,
0,
1,
0,
0,
1,
0
]
}
Todo:
Hi Robert and Tamas,
I'd been looking for some info on interfacing with the Gree airconditioner and stumbled upon this conversation. I'm amazed at the work that has been done :)
I hope you dont mind, but I took the liberty of creating a Java version of your library. So far I have Scanning, Binding, Power on & off and Set Temperature working.
My goal is to create a binding to use in OpenHab.
Please let me know if I can be of any help :)
Thanks, John
Hi,
Thank you for your interest. I'm looking forward to check your implementation and maybe I could get some inspiration for the Android app's network library. 😃
Hi, Quick question that was puzzling me... We connect and bind to the airconditioner... and we can query it's status... If the status on the airconditioner changes (e.g. using the IR remote control) does the airconditioner publish the status change to the bound client (our code)? Or do we need to periodically query the status of the airconditioner? Thanks, John
Hi,
In the original Gree Smart application and in my implementations the AC units are periodically polled because there is no signaling from the units.
Thanks for the info
Hi Robert, Many thanks for your description of the Wind settings above. But.. on my device remote control I only have 4 settings: Low, Medium, Hight and Auto. My values are the same as yours but 'Auto' has { opt: [ 'WdSpd', 'Quiet', 'Tur', 'NoiseSet' ], p: [ 0, 0, 0, 0 ], t: 'cmd' }
Hope this helps :)
@jllcunha thanks
fun fact: on the remote control i have the mentioned 4 options but in the app i have all of them.
Interesting :) For the Up Down Swing, I just ran some tests... Mine supports values ; 0 Seems to do nothing 10 Full Range 11 Full Range 1 Full range 2 Point up 3 Mid Up 4 Mid 5 Mid Down 6 Down
I'm guessing this depends on Model BTW: Mine is a Lomo (GWH12QC-K3DNB2G/I)
The Java application is pretty much done for now. I'll clean up the code and add more funtionality over time but for now I'm focussing on implementing an OpenHab binding based on this code. https://github.com/jllcunha/GreeTest
Just released the addon for OpenHab2 based on the work started here :) https://github.com/jllcunha/openhab-greeair-binding
Some info on the Presets:
List presets: We send: {"count":1,"index":0,"t":"queryT"} Unit Responds (there are no presets): {"t":"listT","total":0,"index":0,"list":[]}
Set a preset (preset1) to turn on the airconditioner Repeat Mon, Tue 19.00 We send: {"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[1]}],"enable":0,"hr":19,"id":0,"min":0,"name":"53636865643120","sec":0,"t":"setT","tz":1,"week":[0,1,1,0,0,0,0]} Unit Responds: {"t":"resT","r":200}
Now when we list presets: We send : {"count":1,"index":0,"t":"queryT"} Unit Responds: {"t":"listT","total":1,"index":0,"list":[{"id":0,"name":"53636865643120","enable":0,"hr":19,"min":0,"sec":0,"week":[0,1,1,0,0,0,0],"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[1]}]}]}
Now we set another preset (preset2) to turn on the airconditioner Repeat Wed, Thur 20.00 We send: {"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[0]}],"enable":0,"hr":20,"id":1,"min":0,"name":"53636865643220","sec":0,"t":"setT","tz":1,"week":[0,0,0,1,1,0,0]} Unit Responds: {"t":"resT","r":200}
Now we can query for the presets: Query for Preset1: We send : {"count":1,"index":0,"t":"queryT"} Unit Reponds: {"t":"listT","total":2,"index":0,"list":[{"id":0,"name":"53636865643120","enable":0,"hr":19,"min":0,"sec":0,"week":[0,1,1,0,0,0,0],"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[1]}]}]} Query for Preset2: We send : {"count":1,"index":1,"t":"queryT"} Unit Reponds: {"t":"listT","total":2,"index":1,"list":[{"id":1,"name":"53636865643220","enable":0,"hr":20,"min":0,"sec":0,"week":[0,0,0,1,1,0,0],"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[0]}]}]}
We can disable Preset1: We send : {"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[1]}],"enable":1,"hr":19,"id":0,"min":0,"name":"53636865643120","sec":0,"t":"updateT","tz":1,"week":[0,1,1,0,0,0,0]} Unit responds: {"t":"resT","r":200}
And we can enable Preset1 again We send ; {"cmd":[{"mac":["f4911e04c3b3"],"opt":["Pow"],"p":[1]}],"enable":0,"hr":19,"id":0,"min":0,"name":"53636865643120","sec":0,"t":"updateT","tz":1,"week":[0,1,1,0,0,0,0]} Unit Responds: {"t":"resT","r":200}
Finally we can delete Preset2 We send : {"id":1,"t":"deleteT"} Unit Responds : {"t":"resT","r":200}
Note that whenever we query for a preset, the response always contains "total":2 which tells us how many presets are stored in the unit. Important to note that "enable":0 enables the preset and "enable":1 disables the preset.
Great job on the Android app :) The code is much cleaner and organized than mine :)
Thank you but there is still room for improvements. The scheduling API is not implemented, you cannot rename the device and I want to add persistence to avoid binding on every start.
Hi, just wanted to say thank you for all the groundwork!
If anyone's interested, I've implemented an MQTT bridge in NodeJS based on your spec (it can also be used as a Hass.io addon).
Hi guys! Another Gree AC owner here (Viola model). I've found you by chance when discovering what openHAB could do with stuff in my home. You've done great job in opening this proprietary protocol and liberating us from Gree Smart Home Android app with its crazy permissions and privacy intrusions. I've intercepted the app's data with Fiddler and found out that you can also use web app for almost the same functions you are talking about here. According to your GitHub profiles, you are all from Europe, so this link should work for you, too. I don't know if we should keep a low profile just in case someone from Gree discovers us and changes the protocol?
Hi!
Thanks for the info about the web app, I'll check it out.
About the low profile thing I don't think they will re-write the firmware for all the devices they make and even if they do, I think firmware updates are done manually on these devices. In the latest version of the android app I saw they somewhat tried to hide the encryption layer in a native library, but after some fiddling with a disassembler one could find the encryption key and the algorithm, which makes this "security-by-obscurity" thing pretty useless.
In addition my question is why do they want to hide the protocol from the potential developers? Philips Hue has an open and documented API and as a result there are many hue-compatible apps in the app stores.
@sm4rk0 thanks for the information, first when I wanted to reverse engineer my AC I looked at their web app but you have to register an account to be able to access that, I did not do that on purpose. With the registration, you can access your device over the internet, you don't need to be on the same network. That last thing - to be honest - I want that my device is opening a tunnel to a server (which is probably located in China).
Maybe they are trying to hide the protocol so users are limited to using their privacy-intruding app. Just try running the Gree Smart Home with XPrivacy to see what I'm talking about.
@sm4rk0 IMHO privacy is not the only problem. The "official" app is bloated, buggy, inconvinient and drains the battery in the backgrund if I don't kill it. I'd also like a widget on my home screen which controls the AC units instead of always opening the app and waiting for it to connect to my units.
@oroce fun fact, the AC always communicates with a remote server even if you don't register them on the website. It sends heartbeat packets and waits for the server to reply to them. If you try to block them on the firewall, after a while the WiFi module freezes and you have to restart the unit.
Hello,
Thanks for your hard work in reverse engineering the gree controller protocol. Any chance to create a Homebridge plugin to integrate this AC with Apple HomeKit?
@duculete asked this question in my repo as well, here's my answer: https://github.com/oroce/node-gree-smart/issues/4
@duculete I'll look into it as my time allows.
Edit: I began to see how it works and it shouldn't be a hard thing to implement. Maybe on this weekend I can come up with a working version. If you have any other questions about the plugin, please open a new ticket as I'm gonna close this.
@duculete just FYI, the Homebridge plugin is in progress, I plan to release an initial version of it in a few days.
Thanks. I started also to create a homebridge version, I have something functional but not finished.
Great Work! @tomikaa87 Thanks! I just tried this on a new unit.
Have some updated info on setting temp using Fahrenheit for the ahem ... certain countries.
Set using Fahrenheit Two things I found were despite TemUn being set , the set temp is still in Celsius. Use the TemRec bit to distinguish between the two Fahrenheit temps
pack: {
"opt": ["TemUn", "SetTem","TemRec"],
"p": [1, 27,0],
"t": "cmd"
}
TempRec TemSet Mapping for setting Fahrenheit
Units | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Fahrenheit | 68. | 69. | 70. | 71. | 72. | 73. | 74. | 75. | 76. | 77. | 78. | 79. | 80. | 81. | 82. | 83. | 84. | 85. | 86. | |
Celsius | 20.0 | 20.5 | 21.1 | 21.6 | 22.2 | 22.7 | 23.3 | 23.8 | 24.4 | 25.0 | 25.5 | 26.1 | 26.6 | 27.2 | 27.7 | 28.3 | 28.8 | 29.4 | 30.0 | |
TemSet | 20 | 21 | 21 | 22 | 22 | 23 | 23 | 24 | 24 | 25 | 26 | 26 | 27 | 27 | 28 | 28 | 29 | 29 | 30 | 30 |
TemRec | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
Equations TemSet = round((desired_temp_f-32.)5.0/9.0) TemRec = (int) ((((desired_temp_f-32.)5.0/9.0) - TemSet) > 0)
@gurglespuge thanks for the info, i've added it to the protocol documentation. 👍
Tomi, thankyou for your great work!! In Hungary i purchased a AC named NORD which is produced by Gree and it is fully compatible with Gree app. So i hope i can write my own app for that too which would not possible without your great effort!
Thank you!
Hello! I have just installed Gree GWH09QB-K6DNB8 and am using the Openhab2 binding that was made by jllcunha. The unit I have has 8C heating function that is activated by remote (Temp+Clock simultaneously) or with Gree+ App. John's binding doesn't support that and seems that the function isn't listed here either.
Does anyone here have the 8C heating function so that it could be added to different bindings eliminating the need to use the Gree app?
Hello! I have just installed Gree GWH09QB-K6DNB8 and am using the Openhab2 binding that was made by jllcunha. The unit I have has 8C heating function that is activated by remote (Temp+Clock simultaneously) or with Gree+ App. John's binding doesn't support that and seems that the function isn't listed here either.
Does anyone here have the 8C heating function so that it could be added to different bindings eliminating the need to use the Gree app?
Hi,
I'll look into in today and add the necessary protocol instructions to the documentation.
Edit: probably it's the StHt
flag in the command and status pack.
Just checked with an android packet capturing application and can confirm that "opt":"StHt","p":"1.0"
is used to turn on and "opt":"StHt","p":"0.0"
is used to turn off the 8°C heating mode.
Great! Thank you guys!
Hey, I have a Gree Smart AC as well and if I can guess you are mimicking the Gree Smart app. Can you share some details how does it work? I was trying to reverse engineer it, but I had no luck.
I tried:
I emailed them for docs, no reply.
Do you have a documentation or did I miss something?
Thanks