Closed ryancdotorg closed 4 years ago
Thanks for the info! It's really sad that users can no longer control their own devices but need to rely on cloud services. I won't recommend anyone buying such device.
How is the initial pairing between the mobile app and the device is done?
I won't recommend anyone buying such device.
Indeed, I am looking into getting a refund for it.
How is the initial pairing between the mobile app and the device is done?
I was unfortunately not able to sniff that.
I have two possible solutions to sniff the paring process, will give it a try this weekend. Have you looked at all at the firmware update code in the app? I'm wondering if a downgrade is possible, but my reversing skills are pretty weak.
Yeah, there is an update functionality in the app but currently I don't have the time and motivation to reverse it. I believe a more plausible approach in this direction would be hacking the physical device (see issue #3) in case you want to void your warranty.
In any case keep us posted about your findings for the pairing process!
I've got a friend who does Android reversing who is willing to take at least a brief look at the app. I can go looking for a uart if I can't return the AC2889. Will probably open up the AC3259/60 regardless to add a switch for the speaker.
This is for the /40 - do you know what the different / numbers mean? Don't see an obvious system UART, but the photos are super blurry.
https://fccid.io/2AICSAC2889/Internal-Photos/Internal-photos-3222110
@DerPaco, @michalboronski or @apfelsheriff - can you share the first six characters (excluding the colons) of the mac address for your AC2889 with us? I believe the --wifi command will show it.
I can share mine if useful?
Yes, please, if you've got it working with this project I would really appreciate that.
e8:c1:d7:
Hmm, that's what I was afraid of.... That MAC prefix is registered to Phillips. My unit has one starting with b0:f8:93 which is registered to Shanghai MXCHIP Information Technology Co., Ltd. I'm wondering if the hardware is different.
I have an AC2889/10 also encountering the {"status":"failed"}
issue. My MAC prefix is also B0:F8:93
. Happy to help with any information I can provide.
@DerPaco, @michalboronski or @apfelsheriff - can you share the first six characters (excluding the colons) of the mac address for your AC2889 with us? I believe the --wifi command will show it.
Sure, no problem : E8:C1:D7
Have an ac4550, "status:failed" here. From inet the Mac address start with b0:f8:93, Shanghai MXCHIP Information Technology Co., Ltd.
I can read values but I cannot write values. When I try to change pwr for example I also get {"status":"failed"}
But reading works. But I wrote my own tool because the python script also did not work for me. For /dev/info:
{"product_id":"<longNumber>","device_id":"<longNumber>","name":"Wohnzimmer","type":"AC3033","modelid":"AC3033/10","swversion":"Ms3105","option":"1"}
And for /dev/status:
{"state":{"reported":{"name":"Wohnzimmer","type":"AC3033","modelid":"AC3033/10","swversion":"Ms3105","language":"EN","DeviceVersion":"1.0.5","om":"1","pwr":"1","cl":false,"aqil":0,"uil":"0","uaset":"A","mode":"AG","pm25":6,"iaql":2,"aqit":4,"tvoc":1,"ddp":"0","rddp":"0","err":0,"fltt1":"A3","fltt2":"none","fltsts0":352,"fltsts1":4800,"fltsts2":65535,"filna":"0","filid":"0","ota":"ck","Runtime":27871569,"WifiVersion":"AWS_Philips_AIR@54.2","ProductId":"<longNumber>","DeviceId":"<longNumber>","StatusType":"localcontrol","ConnectType":"Localcontrol"}}}
For writing it looks like the message "must" be of this structure (not sure though):
{"state":{"desired":{"CommandType":"app","DeviceId":"<longNumber>","EnduserId":"???","pwr":"0"}}}
I do not know what EnduserId should be...
edit:
it works!!!
{"status":"success"}
EnduserId seems to be irrelevant. But you need to sync an id when sending a message. The id is received via /dev/sync. The message send then needs to contain id + 1
@holomekc Hi I came yesterday to a similar conclusion (for me it was /sys/dev/sync not /dev/sync), but I'm unclear if there aren' different firmware versions around. My conclusion is here: https://github.com/rgerganov/py-air-control/issues/21#issuecomment-619284974 I managed to get data back, but it's no json, it's also no json what the app gets back.
Could you point me in the right direction? What device to you have? What do you mean with "The message send then needs to contain id + 1". What does the message to the device look like? Do you have a sample of your code? Would be interesting if you get back a json string directly ... Thanks!
From your example:
encodedCounter: substring(0, 8) '23D56232'
decodedCounter: remove zeros in front if they exist. hex -> decimal = 601186866
const keyAndIv = CleanHomeCoapHelper.bufferToHexString(CleanHomeCoapHelper.toMD5('JiangPan' + encodedCounter));
const secretKey = keyAndIv.substring(0, keyAndIv.length / 2);
const iv = keyAndIv.substring(keyAndIv.length / 2, keyAndIv.length);
const encodedMessage = response.substring(8, response.length - 64);
return CleanHomeCoapHelper.fromAES(encodedMessage, secretKey, iv);
result: {
encodedCounter: '23D56232',
keyAndIv: '10917AAD9D5AD7FB36F62901C8072233',
secretKey: '10917AAD9D5AD7FB',
iv: '36F62901C8072233',
encodedMessage: '3CC15DD4C1E80B11EF5D2E70493CF5C470671A5B2AD54578006A3B9C965D8F39D99D0152F37AA5286C1AEEF6C5D5A608FA5AB38206532E88C27C4FDA3437561F687D59CDA0BCA2F09E78B2BA5EEC6AFD99354646A66231031375CBACA80D6BCE66244EB08269A121F326D089971C6F9BE1D6649D453C98D961FA3D4767D3A8512B5E92FF7F1D285FD420FD527057C419A3B2063EB87831B7C6E843830E6DEAC187DD63CE2B8F0B756F8224C2C40799812923A4398298A493C7DD38A240BCA5AB182BC9582687F2EF1DDB0D2FD945CD4F616BA8CE66D4731148BB93B001D47B1B28C4A8C621298A8EBB41C4AFA3696F593E6C60397B8361DE2FF4A98BE99FD84874B10A70111139154E30E61E0A10E85CD6E8942A9943F076FEDC8E31008BAA5C068A96C117042EF80AE6E2D897C97660F24775DE571F09C32064C2FEB85A4EDA80AD1C5EA2CA385DA83C1883601B4D5A5EDFD5DA5FB02DBA44FFA4980142D1A157B6EBC48D3D71CA91A4433E7E5542732CCE6EAB9C27171AAEDFE360A9A07919A2BC75466EF6AE7ED8FBD1577477AE75D857B54FEB43476E6A5E41D331F1A6CBE0B700D87FF74882C0D0EBAE09D33ED17DC55DC00CE28420000BD414F513682B40B6EFF436331A708522C02F80D2408CBAE4DF4259A5E23285BD385AEDCC64B2653C71A4FBE38094EF2B1C00036DA2B0E4C39F916454C64A48707B66A587A894',
message: '{"state":{"reported":{"name":"Luftreiniger","type":"AC2889","modelid":"AC2889/10","swversion":"1.0.7","om":"1","pwr":"1","cl":false,"aqil":0,"uil":"0","dt":0,"dtrs":0,"mode":"A","pm25":1,"iaql":1,"aqit":4,"ddp":"0","err":0,"fltt1":"A3","fltt2":"C7","fltsts0":358,"fltsts1":4798,"fltsts2":2398,"ota":"no","Runtime":8842135,"WifiVersion":"AWS_Philips_AIR@54.2","ProductId":"<longNumber>","DeviceId":"<longNumber>","StatusType":"localcontrol","ConnectType":"Localcontrol"}}}'
}
@holomekc Ah I see, you seem to have decompiled the app, the 'JiangPan' and the substrings with 8 and 64 look quite familar to me. And the CleanHomeCoapHelper seems to be something you wrote. Seems like we are having similar firmware versions. I'll have a try lateron, I think that won't be too hard with your code snippet. Thanks!
This is great progress, PRs are welcome!
Great work with the decryption! I'm not a python guy myself, but if it helps - I've put together a java sample here, which works with my AC3829/10.
@timbuktu-t I have just tried your java implementation with my AC2729, it works! I think a python coap library might help to make it work for >2019 models.
[main] INFO philipsair.PhilipsAir - initializing
[main] INFO philipsair.PhilipsAir - synchronizing with coap://172.27.0.163:5683/sys/dev/sync
[main] INFO org.eclipse.californium.core.network.config.NetworkConfig - loading properties from file /tmp/java/Californium.properties
[main] INFO org.eclipse.californium.core.network.RandomTokenGenerator - using tokens of 8 bytes in length
[main] INFO org.eclipse.californium.core.network.CoapEndpoint - coap CoapEndpoint uses udp plain
[main] INFO org.eclipse.californium.core.network.stack.BlockwiseLayer - BlockwiseLayer uses MAX_MESSAGE_SIZE=1024, PREFERRED_BLOCK_SIZE=512, BLOCKWISE_STATUS_LIFETIME=300000, MAX_RESOURCE_BODY_SIZE=8192, BLOCKWISE_STRICT_BLOCK2_OPTION=false
[main] INFO org.eclipse.californium.core.network.stack.ReliabilityLayer - ReliabilityLayer uses ACK_TIMEOUT=2000, ACK_RANDOM_FACTOR=1.5, and ACK_TIMEOUT_SCALE=2.0 as default
[main] INFO org.eclipse.californium.core.network.CoapEndpoint - coap Endpoint [coap://0.0.0.0:0] requires an executor to start, using default single-threaded daemon executor
[main] INFO org.eclipse.californium.elements.UDPConnector - UDPConnector starts up 1 sender threads and 1 receiver threads
[main] INFO org.eclipse.californium.elements.UDPConnector - UDPConnector listening on 0.0.0.0/0.0.0.0:50776, recv buf = 106496, send buf = 106496, recv packet size = 2048
[main] INFO org.eclipse.californium.core.network.CoapEndpoint - coap Started endpoint at coap://0.0.0.0:50776
[main] INFO org.eclipse.californium.core.network.EndpointManager - created implicit endpoint coap://0.0.0.0:50776 for coap
[main] INFO philipsair.PhilipsAir - synchronized with client id 1079002D and server id 1DDB5E50
[main] INFO philipsair.PhilipsAir - observing coap://172.27.0.163:5683/sys/dev/status
{"state":{"reported":{"name":"Room","type":"AC2729","modelid":"AC2729/10","swversion":"0.2.1","om":"0","pwr":"0","cl":false,"aqil":100,"uil":"1","dt":0,"dtrs":0,"mode":"A","func":"P","rhset":50,"rh":69,"temp":22,"pm25":13,"iaql":7,"aqit":4,"ddp":"0","rddp":"0","err":0,"wl":100,"fltt1":"A3","fltt2":"C7","fltsts0":59,"fltsts1":4126,"fltsts2":4126,"wicksts":4126,"ota":"ck","Runtime":17131730,"WifiVersion":"AWS_Philips_AIR@56.4","ProductId":"---xxx---","DeviceId":"---xxx---","StatusType":"localcontrol","ConnectType":"Localcontrol"}}}
[main] INFO philipsair.PhilipsAir - disposing
@timbuktu-t Hi thanks for your sample, seems that AC3829 and AC2889 and obviously also the AC2729 share the same program, at least the newer versions. I've seen the original android-code uses "AES/CBC/PKCS7PADDING" instead of AES/CBC/PKCS5PADDING, but in this case it doesn't seem to matter.
@o0v7r0o The coap library is already in the master of this repo, I get encrypted messages after some code changes, the tricky part seems to be the decoding, at least in python ( or at least for me ๐ )
I had some time today, the AES-step is still a problem for me, I'm assuming python has some differences here, I'm just getting garbage for now (for easy testing I've used a returned string from my AC2889) It looks similar to the java-code, but I can't convert the result to utf-8, there must be something missing. Don't know how much time I'll have during the week, hope next weekend I have a solution.
Any ideas? I've tested with this small program including an encrypted message - result should be the "message" part of this comment: https://github.com/rgerganov/py-air-control/issues/35#issuecomment-619494963
import hashlib
from Cryptodome.Cipher import AES
payload='23D562323CC15DD4C1E80B11EF5D2E70493CF5C470671A5B2AD54578006A3B9C965D8F39D99D0152F37AA5286C1AEEF6C5D5A608FA5AB38206532E88C27C4FDA3437561F687D59CDA0BCA2F09E78B2BA5EEC6AFD99354646A66231031375CBACA80D6BCE66244EB08269A121F326D089971C6F9BE1D6649D453C98D961FA3D4767D3A8512B5E92FF7F1D285FD420FD527057C419A3B2063EB87831B7C6E843830E6DEAC187DD63CE2B8F0B756F8224C2C40799812923A4398298A493C7DD38A240BCA5AB182BC9582687F2EF1DDB0D2FD945CD4F616BA8CE66D4731148BB93B001D47B1B28C4A8C621298A8EBB41C4AFA3696F593E6C60397B8361DE2FF4A98BE99FD84874B10A70111139154E30E61E0A10E85CD6E8942A9943F076FEDC8E31008BAA5C068A96C117042EF80AE6E2D897C97660F24775DE571F09C32064C2FEB85A4EDA80AD1C5EA2CA385DA83C1883601B4D5A5EDFD5DA5FB02DBA44FFA4980142D1A157B6EBC48D3D71CA91A4433E7E5542732CCE6EAB9C27171AAEDFE360A9A07919A2BC75466EF6AE7ED8FBD1577477AE75D857B54FEB43476E6A5E41D331F1A6CBE0B700D87FF74882C0D0EBAE09D33ED17DC55DC00CE28420000BD414F513682B40B6EFF436331A708522C02F80D2408CBAE4DF4259A5E23285BD385AEDCC64B2653C71A4FBE38094EF2B1C00036DA2B0E4C39F916454C64A48707B66A587A8944FF20E8EE3460A2C65482FA56EC5B6EA0A16E17AC2B4331F2B3FF8831F83F9B1'
encodedCounter=payload[0:8]
keyAndIv = hashlib.md5(('JiangPan' + encodedCounter).encode()).hexdigest();
keylen=len(keyAndIv)
print(int(len(keyAndIv) / 2))
secretKey = keyAndIv[0:int(len(keyAndIv) / 2)];
iv = keyAndIv[int(len(keyAndIv) / 2):len(keyAndIv)];
encodedMessage = payload[8:-64];
prepmessage=bytes.fromhex(encodedMessage.upper())
decodedMessage=AES.new(bytes(secretKey.encode('utf8')), AES.MODE_CBC, bytes(iv.encode('utf8'))).decrypt(prepmessage)
@o0v7r0o Glad to hear it works! I'm curious though, did you get just one reading in those ten seconds? Once I start observing, my device sends one packet every 2-3 seconds, so I usually have 4-5 readings in that time. However, sometimes I get pauses for a few seconds as well, where I can see in Wireshark that udp packets are retransmitted. Could you maybe increase the sleep time in line 214 to e.g. a minute (using "Thread.sleep(60000)") to see if more readings arrive? And did you per chance try sending a poweroff command (as decribed in line 218) to your device as well?
@Cyber1000 Thanks for the tip! I did not reverse the app, just built upon the discoveries you and @holomekc posted in the forum (and a bit of Wireshark), so PKCS5 and UTF8 are just wild guesses. I did not test using device names with special characters, so UTF8 might still be wrong and yield character encoding problems.
Regarding your snippet: The method hexdigest() returns lowercase hexdigits, You have to upper() the keyAndIv, then it works and print(decodedMessage) yields:
b'{"state":{"reported":{"name":"Luftreiniger","type":"AC2889","modelid":"AC2889/10",...}}}\x01'
I have no clue about the prefix "b'" and suffix "\x01'" though. I assume, this is how python indicates a byte array?
I have no clue about the prefix "b'" and suffix "\x01'" though. I assume, this is how python indicates a byte array?
Yes, b
means it's a byte array. The \x01
at the end is padding, you should unpad with Crypto.Util.Padding.unpad(data, 16, style='pkcs7')
@Cyber1000 Could you please submit a PR when you get this working with your device?
@o0v7r0o Glad to hear it works! I'm curious though, did you get just one reading in those ten seconds? Once I start observing, my device sends one packet every 2-3 seconds, so I usually have 4-5 readings in that time. However, sometimes I get pauses for a few seconds as well, where I can see in Wireshark that udp packets are retransmitted. Could you maybe increase the sleep time in line 214 to e.g. a minute (using "Thread.sleep(60000)") to see if more readings arrive? And did you per chance try sending a poweroff command (as decribed in line 218) to your device as well?
I have indeed successfully tested power on/off. However, as I remember I've got only one status update during these 10 seconds.
Awesome work, @timbuktu-t !
Working on my newly purchased AC1214/10:
{
"state": {
"reported": {
"name": "XXX",
"type": "AC1214",
"modelid": "AC1214/10",
"swversion": "2.0.0",
"om": "1",
"pwr": "1",
"cl": false,
"aqil": 25,
"uil": "1",
"dt": 0,
"dtrs": 0,
"mode": "P",
"pm25": 2,
"iaql": 1,
"aqit": 4,
"ddp": "0",
"err": 0,
"fltt1": "A3",
"fltt2": "C7",
"fltsts0": 23,
"fltsts1": 4463,
"fltsts2": 2063,
"ota": "ck",
"Runtime": 19976679,
"WifiVersion": "AWS_Philips_AIR@54.2",
"ProductId": "XXX",
"DeviceId": "XXX",
"StatusType": "localcontrol",
"ConnectType": "Localcontrol"
}
}
}
Cool! So now we know of four models this works for. Out of curiosity, how many readings did you get during the 10 seconds window?
Credit should got to @Cyber1000 and @holomekc though, as they figured out the decryption :-)
I'm starting work on Coap support for the Openhab binding. However as I have an older version without Coap I cannot phisycally test it, so I'm working on some mock simualator to make at least dry implementation. @timbuktu-t or @sal0max could you provide me DEBUG logs from the poc code of yours so that it includes whole communication log? You can add it here : https://github.com/michalboronski/openhab2-addons/issues/2
me too, but then in node and for homey instead. Already got it working for last year devices. So the security part is still the same?
Much is going on in this thread ๐
@timbuktu-t Yes the code looks similar to yours:
A little bit different in the flow, but this may also due to decompiling processes. UTF8 should be just fine.
And sometimes things can get so simple, many thanks ๐ for the hint with upper, that's all I was missing, I looked so often at @holomekc result, that I didn't notice the difference between my lower case and his upper-case keys. upper was missing and in the end also this one:
response = unpad(decodedMessage, 16)
print(response.decode('utf8'))
padding/unpadding is done directly in java but not in python. Now I get a "normal" string without the \x01 at the end.
As said I'm still in my small sample, I'll need to get this back in your code and clean this up @rgerganov
So it seems that we have these versions around:
@Cyber1000 I poked around a bit regarding PKCS#7. Apparently you have to specify PKCS5Padding in Oracle JDK even when you actually want to use PKCS#7, which is a superset for longer block sizes. For details see Stack Overflow or the Oracle Bug Database.
@michalboronski I'll send you debug logs next chance I get.
@Cyber1000 Iam running this
[modelid] ModelId: AC2729/10
[swversion] Version: 0.2.1
@timbuktu-t Ok nice to know, sorry for misleading, java is not my main language, thanks for the information.
@michalboronski what exactly do you need?
btw: Had time to check out controlling my AC1214/10. Works great: powering on/off, changing modes & manual speeds all works flawlessly.
Hi all, I tried to run java tool from @timbuktu-t and it work well now. I can turn on/off and other, but can't reset a scheduler...
I got this:
{"state":{"reported":{"name":"xxx","type":"AC1214","modelid":"AC1214/10","swversion":"2.0.0","om":"2","pwr":"0","cl":false,"aqil":25,"uil":"1","dt":0,"dtrs":0,"mode":"M","pm25":7,"iaql":2,"aqit":7,"ddp":"0","err":0,"fltt1":"A3","fltt2":"C7","fltsts0":169,"fltsts1":4247,"fltsts2":1847,"ota":"no","Runtime":406669706,"WifiVersion":"AWS_Philips_AIR@54.2","ProductId":"xxx","DeviceId":"xxx","StatusType":"localcontrol","ConnectType":"Localcontrol"}}}
Air purifier is configured to power on every night at 22:35 and I dont know where its configured. Also checked from mobile applications (cleanHome, air matters) Even when I set via app some schedule, it still return "dt":0,"dtrs":0
Thanks
Good news: I've forked the project using a new git branch: https://github.com/Cyber1000/py-air-control/tree/coap_1_0_7
Installation (maybe you need sudo):
git clone -b coap_1_0_7 https://github.com/Cyber1000/py-air-control.git && cd py-air-control
python3 setup.py install
What works for now:
airctrl --ipaddr 192.168.11.190 --version 1.0.7 -d
airctrl --ipaddr 192.168.11.190 --version 1.0.7
So you are getting information in json and list-format, writing to your device won't work for now.
parser.add_argument('--version', help='set the version of your device ', choices=['0.1.0','0.2.1', '1.0.7'], default='0.1.0')
Can confirm that this gets data on my AC2889/10 on version 1.0.7. Thanks for all the work guys.
Nice work! I tried with AC2729/50; Device version: 0.2.1; Firmware: AWS_Philips_AIR@54.2, airctrl from @Cyber1000 's repo:
2020-05-06 01:36:40,980 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('172.16.0.140', 5683), None-None, EMPTY-None, [] No payload 2020-05-06 01:36:40,980 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('172.16.0.140', 5683), CON-3889, EMPTY-None, [] No payload 2020-05-06 01:36:40,981 - Thread-1 - coapthon.client.coap - DEBUG - Start receiver Thread 2020-05-06 01:36:40,982 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('172.16.0.140', 5683), ACK-None, GET-kdsk, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload 2020-05-06 01:36:40,982 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('172.16.0.140', 5683), ACK-3890, GET-kdsk, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload 2020-05-06 01:36:40,983 - MainThread-Retry-3889 - coapthon.client.coap - DEBUG - retransmit loop ... enter 2020-05-06 01:36:40,983 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_empty - From ('172.16.0.140', 5683), To None, RST-3889, EMPTY-None, [] No payload 2020-05-06 01:36:40,984 - MainThread-Retry-3889 - coapthon.client.coap - DEBUG - retransmit loop ... exit 2020-05-06 01:36:40,998 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('172.16.0.140', 5683), To None, ACK-1110, CONTENT-kdsk, [Observe: 87, Content-Type: 50, Max-Age: 60, ] 391309FB4544FA01BD4D...1137 bytes 2020-05-06 01:36:40,998 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('172.16.0.140', 5683), To None, ACK-1110, CONTENT-kdsk, [Observe: 87, Content-Type: 50, Max-Age: 60, ] 391309FB4544FA01BD4D...1137 bytes 2020-05-06 01:36:41,099 - Thread-1 - coapthon.client.coap - DEBUG - Exiting receiver Thread due to request Traceback (most recent call last): File "./airctrl.py", line 771, in
main() File "./airctrl.py", line 767, in main c.get_status(debug=args.debug) File "./airctrl.py", line 599, in get_status status = self._get() File "./airctrl.py", line 337, in _get return json.loads(response.payload)["state"]["reported"] File "/usr/lib/python3.7/json/init.py", line 348, in loads return _default_decoder.decode(s) File "/usr/lib/python3.7/json/decoder.py", line 340, in decode raise JSONDecodeError("Extra data", s, end) json.decoder.JSONDecodeError: Extra data: line 1 column 7 (char 6)
I rebooted the device, It was auto-upgraded to Firmware: AWS_Philips_AIR@56.4:
airctrl.py --ipaddr 172.16.0.140 --version 0.2.1 -d 2020-05-06 01:52:23,865 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('172.16.0.140', 5683), None-None, EMPTY-None, [] No payload 2020-05-06 01:52:23,865 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('172.16.0.140', 5683), CON-38532, EMPTY-None, [] No payload 2020-05-06 01:52:23,866 - Thread-1 - coapthon.client.coap - DEBUG - Start receiver Thread 2020-05-06 01:52:23,867 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('172.16.0.140', 5683), ACK-None, GET-AdDP, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload 2020-05-06 01:52:23,867 - MainThread-Retry-38532 - coapthon.client.coap - DEBUG - retransmit loop ... enter 2020-05-06 01:52:23,867 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('172.16.0.140', 5683), ACK-38533, GET-AdDP, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload 2020-05-06 01:52:24,688 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_empty - From ('172.16.0.140', 5683), To None, RST-38532, EMPTY-None, [] No payload 2020-05-06 01:52:24,689 - MainThread-Retry-38532 - coapthon.client.coap - DEBUG - retransmit loop ... exit 2020-05-06 01:52:25,891 - Thread-1 - coapthon.client.coap - DEBUG - Exiting receiver Thread due to request
Raw status: {}
airctrl.py --ipaddr 172.16.0.140 --version 1.0.7 --debug 2020-05-06 02:02:55,149 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('172.16.0.140', 5683), None-None, POST-dC, [Uri-Path: sys, Uri-Path: dev, Uri-Path: sync, ] 410C4BEF...8 bytes 2020-05-06 02:02:55,150 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('172.16.0.140', 5683), CON-23894, POST-dC, [Uri-Path: sys, Uri-Path: dev, Uri-Path: sync, ] 410C4BEF...8 bytes 2020-05-06 02:02:55,151 - Thread-1 - coapthon.client.coap - DEBUG - Start receiver Thread 2020-05-06 02:02:55,152 - MainThread-Retry-23894 - coapthon.client.coap - DEBUG - retransmit loop ... enter 2020-05-06 02:02:55,155 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('172.16.0.140', 5683), To None, NON-23894, CONTENT-dC, [Content-Type: 0, ] 5668C3D4...8 bytes 2020-05-06 02:02:55,155 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('172.16.0.140', 5683), To None, NON-23894, CONTENT-dC, [Content-Type: 0, ] 5668C3D4...8 bytes 2020-05-06 02:02:55,156 - Thread-1 - coapthon.client.coap - DEBUG - Waiting for retransmit thread to finish ... 2020-05-06 02:02:55,156 - MainThread-Retry-23894 - coapthon.client.coap - DEBUG - retransmit loop ... exit 2020-05-06 02:02:55,167 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('172.16.0.140', 5683), ACK-None, GET-rhCN, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload 2020-05-06 02:02:55,167 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('172.16.0.140', 5683), ACK-23895, GET-rhCN, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload 2020-05-06 02:02:55,184 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('172.16.0.140', 5683), To None, ACK-112, CONTENT-rhCN, [Observe: 65, Content-Type: 50, Max-Age: 60, ] 410C4BF0DC53FFB0BC9F...1137 bytes 2020-05-06 02:02:55,185 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('172.16.0.140', 5683), To None, ACK-112, CONTENT-rhCN, [Observe: 65, Content-Type: 50, Max-Age: 60, ] 410C4BF0DC53FFB0BC9F...1137 bytes 2020-05-06 02:02:55,286 - Thread-1 - coapthon.client.coap - DEBUG - Exiting receiver Thread due to request Traceback (most recent call last): File "./airctrl.py", line 771, in
main() File "./airctrl.py", line 767, in main c.get_status(debug=args.debug) File "./airctrl.py", line 636, in get_status status = self._get() File "./airctrl.py", line 677, in _get decrypted_payload = self._decrypt_payload(encrypted_payload) File "./airctrl.py", line 663, in _decrypt_payload decoded_message = AES.new(bytes(secret_key.encode('utf8')), AES.MODE_CBC, bytes(iv.encode('utf8'))).decrypt(bytes.fromhex(encoded_message)) ValueError: non-hexadecimal number found in fromhex() arg at position 1065
I tried @timbuktu-t 's java version, seems to work:
[main] INFO philipsair.PhilipsAir - initializing [main] INFO philipsair.PhilipsAir - synchronizing with coap://172.16.0.140:5683/sys/dev/sync [main] INFO org.eclipse.californium.core.network.config.NetworkConfig - writing properties to file C:\Users\szogi\Downloads\poc-philipsair-master\Californium.properties [main] INFO org.eclipse.californium.core.network.RandomTokenGenerator - using tokens of 8 bytes in length [main] INFO org.eclipse.californium.core.network.CoapEndpoint - coap CoapEndpoint uses udp plain [main] INFO org.eclipse.californium.core.network.stack.BlockwiseLayer - BlockwiseLayer uses MAX_MESSAGE_SIZE=1024, PREFERRED_BLOCK_SIZE=512, BLOCKWISE_STATUS_LIFETIME=300000, MAX_RESOURCE_BODY_SIZE=8192, BLOCKWISE_STRICT_BLOCK2_OPTION=false [main] INFO org.eclipse.californium.core.network.stack.ReliabilityLayer - ReliabilityLayer uses ACK_TIMEOUT=2000, ACK_RANDOM_FACTOR=1.5, and ACK_TIMEOUT_SCALE=2.0 as default [main] INFO org.eclipse.californium.core.network.CoapEndpoint - coap Endpoint [coap://0.0.0.0:0] requires an executor to start, using default single-threaded daemon executor [main] INFO org.eclipse.californium.elements.UDPConnector - UDPConnector starts up 4 sender threads and 4 receiver threads [main] INFO org.eclipse.californium.elements.UDPConnector - UDPConnector listening on 0.0.0.0/0.0.0.0:63851, recv buf = 65536, send buf = 65536, recv packet size = 2048 [main] INFO org.eclipse.californium.core.network.CoapEndpoint - coap Started endpoint at coap://0.0.0.0:63851 [main] INFO org.eclipse.californium.core.network.EndpointManager - created implicit endpoint coap://0.0.0.0:63851 for coap [main] INFO philipsair.PhilipsAir - synchronized with client id B3E24779 and server id 5BB802AF [main] INFO philipsair.PhilipsAir - observing coap://172.16.0.140:5683/sys/dev/status {"state":{"reported":{"name":"Bedroom","type":"AC2729","modelid":"AC2729/50","swversion":"0.2.1","om":"1","pwr":"1","cl":false,"aqil":100,"uil":"1","dt":0,"dtrs":0,"mode":"A","func":"P","rhset":50,"rh":29,"temp":23,"pm25":1,"iaql":1,"aqit":4,"ddp":"1","rddp":"1","err":49408,"wl":0,"fltt1":"A3","fltt2":"C7","fltsts0":307,"fltsts1":1327,"fltsts2":1327,"wicksts":1327,"ota":"no","Runtime":1896792,"WifiVersion":"AWS_Philips_AIR@56.4","ProductId":"XXXXXXXX","DeviceId":"XXXXXXXXXXX","StatusType":"localcontrol","ConnectType":"Localcontrol"}}} {"state":{"reported":{"name":"Bedroom","type":"AC2729","modelid":"AC2729/50","swversion":"0.2.1","om":"1","pwr":"1","cl":false,"aqil":100,"uil":"1","dt":0,"dtrs":0,"mode":"A","func":"P","rhset":50,"rh":29,"temp":23,"pm25":2,"iaql":1,"aqit":4,"ddp":"1","rddp":"1","err":49408,"wl":0,"fltt1":"A3","fltt2":"C7","fltsts0":307,"fltsts1":1327,"fltsts2":1327,"wicksts":1327,"ota":"no","Runtime":1903897,"WifiVersion":"AWS_Philips_AIR@56.4","ProductId":"XXXXXXXXXXXXX","DeviceId":"XXXXXXXX","StatusType":"localcontrol","ConnectType":"Localcontrol"}}} [main] INFO philipsair.PhilipsAir - disposing
Can I help testing? :)
Confirm its working on my ac4550/10 and version 1.0.7
Unfortunately does not work with my AC3039/10.
$ airctrl --ipaddr 192.168.1.24 --version 1.0.7 -d
2020-05-06 12:05:36,810 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('192.168.1.24', 5683), None-None, POST-To, [Uri-Path: sys, Uri-Path: dev, Uri-Path: sync, ] AE0B4A85...8 bytes
2020-05-06 12:05:36,811 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('192.168.1.24', 5683), CON-49605, POST-To, [Uri-Path: sys, Uri-Path: dev, Uri-Path: sync, ] AE0B4A85...8 bytes
2020-05-06 12:05:36,812 - Thread-1 - coapthon.client.coap - DEBUG - Start receiver Thread
2020-05-06 12:05:36,812 - MainThread-Retry-49605 - coapthon.client.coap - DEBUG - retransmit loop ... enter
2020-05-06 12:05:36,915 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('192.168.1.24', 5683), To None, NON-49605, CONTENT-To, [Content-Type: 0, ] 57B77750...8 bytes
2020-05-06 12:05:36,915 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('192.168.1.24', 5683), To None, NON-49605, CONTENT-To, [Content-Type: 0, ] 57B77750...8 bytes
2020-05-06 12:05:36,916 - Thread-1 - coapthon.client.coap - DEBUG - Waiting for retransmit thread to finish ...
2020-05-06 12:05:36,916 - MainThread-Retry-49605 - coapthon.client.coap - DEBUG - retransmit loop ... exit
2020-05-06 12:05:36,928 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('192.168.1.24', 5683), ACK-None, GET-HtFD, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload
2020-05-06 12:05:36,928 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('192.168.1.24', 5683), ACK-49606, GET-HtFD, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload
2020-05-06 12:05:37,136 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('192.168.1.24', 5683), To None, ACK-1316, CONTENT-HtFD, [Observe: 35, Content-Type: 50, Max-Age: 60, ] AE0B4A860B22951ED81E...1137 bytes
2020-05-06 12:05:37,136 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('192.168.1.24', 5683), To None, ACK-1316, CONTENT-HtFD, [Observe: 35, Content-Type: 50, Max-Age: 60, ] AE0B4A860B22951ED81E...1137 bytes
2020-05-06 12:05:37,237 - Thread-1 - coapthon.client.coap - DEBUG - Exiting receiver Thread due to request
Traceback (most recent call last):
File "/home/Lorianne/philips/bin/airctrl", line 8, in <module>
sys.exit(main())
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 767, in main
c.get_status(debug=args.debug)
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 636, in get_status
status = self._get()
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 677, in _get
decrypted_payload = self._decrypt_payload(encrypted_payload)
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 663, in _decrypt_payload
decoded_message = AES.new(bytes(secret_key.encode('utf8')), AES.MODE_CBC, bytes(iv.encode('utf8'))).decrypt(bytes.fromhex(encoded_message))
ValueError: non-hexadecimal number found in fromhex() arg at position 1065
/sys/dev/info
returns {"product_id":"660c6902649b11e9a1e3061302926720","device_id":"0b529c58af8111e9a1e3061302926720","name":"Maison","type":"AC3039","modelid":"AC3039/10","swversion":"Ms3104","option":"1"}
Confirm its working on my ac4550/10 and version 1.0.7
[modelid]: AC1214/10 works too
ok so it seems to work sometimes, with some bad experiences for @szogi and @bobzomer
@szogi - Interesting ... You tested with both 0.2.1 and 1.0.7
airctrl --ipaddr [ip] --version 0.2.1
hasn't really changed from @shexbeer's version, it's more or less the same as airctrl --ipaddr [ip] --protocol coap
from this repopython3 setup.py install
) and post it here or send per pm -
print(encrypted_payload)
@bobzomer You seem to have the same problem, question ii would apply to you too, btw your sw-version looks interesting
I think there may be some "filling" characters or some other type of clutter around.
I don't expect having much time till tommorow evening or friday. Thanks for everyone's input so far ๐
{"state":{"reported":{"name":"Bedroom","type":"AC2729","modelid":"AC2729/50","swversion":"0.2.1","om":"1","pwr":"1","cl":false,"aqil":100,"uil":"1","dt":0,"dtrs":0,"mode":"A","func":"P","rhset":50,"rh":29,"temp":23,"pm25":1,"iaql":1,"aqit":4,"ddp":"1","rddp":"1","err":49408,"wl":0,"fltt1":"A3","fltt2":"C7","fltsts0":307,"fltsts1":1327,"fltsts2":1327,"wicksts":1327,"ota":"no","Runtime":1896792,"WifiVersion":"AWS_Philips_AIR@56.4","ProductId":"XXXXXXXX","DeviceId":"XXXXXXXXXXX","StatusType":"localcontrol","ConnectType":"Localcontrol"}}}
{"state":{"reported":{"name":"Bedroom","type":"AC2729","modelid":"AC2729/50","swversion":"0.2.1","om":"1","pwr":"1","cl":false,"aqil":100,"uil":"1","dt":0,"dtrs":0,"mode":"A","func":"P","rhset":50,"rh":29,"temp":23,"pm25":2,"iaql":1,"aqit":4,"ddp":"1","rddp":"1","err":49408,"wl":0,"fltt1":"A3","fltt2":"C7","fltsts0":307,"fltsts1":1327,"fltsts2":1327,"wicksts":1327,"ota":"no","Runtime":1903897,"WifiVersion":"AWS_Philips_AIR@56.4","ProductId":"XXXXXXXXXXXXX","DeviceId":"XXXXXXXX","StatusType":"localcontrol","ConnectType":"Localcontrol"}}}
@Cyber1000 If you mean these two lines printed by my sample, I do not thing this is a mistake. The java program sets the observe option, which instructs the device to continue sending status notifications as long as the client is alive. I tried a simple GET to receive just one reading, but that was rejected by my AC3829/10. @szogi probably got two separate readings during the 10 second window the program is running, my device sends a notification approx. every 1-3 seconds. The device sets the confirmable option on the notifications, so Eclipse Californium automatically acknowledges them (you can see that in Wireshark, but not in my sample code). This way the device knows the client is still listening. You can find more information in RFC 7641.
@Cyber1000 Here is the encrypted payload:
$ airctrl --ipaddr 192.168.1.24 --version 1.0.7 -d
073CBCB1DCABB8CE96A60C81CBF8A6A9E57F4C9D0F0AD86C4B1A1F005874061AD6063DC72432138ABDD0A5AFEDD1D3333D430758DE3BD294BE026B2D1630A71C089EE74036C02F5D8954FEBA93A2886D3F8252263F770F3320ACEFB643FC65C97F0AC762B312AB18203D98F303DC3E1C7C8A8E3E35C86ED5C126121632088D569B50CFED6B72C4E44727E31E0AEE800B022B8B8F71D45CE19A50A0E94471661D9D4CA6694A75C81E5347FAE48E9F4706F6B169B8232BD23CCC9DD6353E2776199A5281EF351AA19AA8E1E003F7DAC6C93A05958EA71E1E55F0A78F63EC4F7D6258FD7F85D994AFF1815DFBC9714F85465FF0955884A3B39F55DDB62F19C7AD3A24AB1E66BEC78FA6FC727AF8C5BD28DB74655F836B71DD8872002F61FFCDF4799D40214F692953B4690A6B00FFBA5C260E5CDD998C2D8FB813EBC8E658B3B5E10907695268DA5DE213D5F134704AAA6E47B3DE42208BB9694F7E0F0414F42292E865A983EAFF0044D01E93F2E0ACF2F8FA4263064749ACE8A5A05FDD36EF1CF301A3311BE5FCE5E2B71085F752E1D4020A25BCECA9DDA4D577046395C82698B413666D7C3DAA0E7A4CEA7C1FD9DCB4FD791D82C12FA385E827F6B22D5C8F4FC6E0DE967BEEC5F365C39317CED6C2F6D86F3C03440724D9AC026A692C38D71BE227C4E59E828F02BB4CCB156919B1D989D76E4585DB6874FABFAD2495FC0365A53F542FACB244EBD35C80F4BEFA2CCB7A44A12A8B6D77D23388137600419878F3D946F9303C8003A7FB920105C2167DA0C9F0C6A238126DE0
Traceback (most recent call last):
File "/home/Lorianne/philips/bin/airctrl", line 8, in <module>
sys.exit(main())
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 768, in main
c.get_status(debug=args.debug)
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 636, in get_status
status = self._get()
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 678, in _get
decrypted_payload = self._decrypt_payload(encrypted_payload)
File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 664, in _decrypt_payload
decoded_message = AES.new(bytes(secret_key.encode('utf8')), AES.MODE_CBC, bytes(iv.encode('utf8'))).decrypt(bytes.fromhex(encoded_message))
File "/home/Lorianne/philips/lib/python3.8/site-packages/Cryptodome/Cipher/_mode_cbc.py", line 246, in decrypt
raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
ValueError: Data must be padded to 16 byte boundary in CBC mode
Model:AC2729/50 Device Version: 0.2.1 Wifi Version: AWS_Philips_AIR@56.4
Output:
2020-05-07 16:25:56,830 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('192.168.0.134', 5683), None-None, POST-WU, [Uri-Path: sys, Uri-Path: dev, Uri-Path: sync, ] 6CB55613...8 bytes
2020-05-07 16:25:56,830 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('192.168.0.134', 5683), CON-17786, POST-WU, [Uri-Path: sys, Uri-Path: dev, Uri-Path: sync, ] 6CB55613...8 bytes
2020-05-07 16:25:56,831 - Thread-1 - coapthon.client.coap - DEBUG - Start receiver Thread
2020-05-07 16:25:56,831 - MainThread-Retry-17786 - coapthon.client.coap - DEBUG - retransmit loop ... enter
2020-05-07 16:25:56,837 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('192.168.0.134', 5683), To None, NON-17786, CONTENT-WU, [Content-Type: 0, ] 76035E0A...8 bytes
2020-05-07 16:25:56,838 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('192.168.0.134', 5683), To None, NON-17786, CONTENT-WU, [Content-Type: 0, ] 76035E0A...8 bytes
2020-05-07 16:25:56,838 - Thread-1 - coapthon.client.coap - DEBUG - Waiting for retransmit thread to finish ...
2020-05-07 16:25:56,838 - MainThread-Retry-17786 - coapthon.client.coap - DEBUG - retransmit loop ... exit
2020-05-07 16:25:56,848 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('192.168.0.134', 5683), ACK-None, GET-VJyr, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload
2020-05-07 16:25:56,849 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('192.168.0.134', 5683), ACK-17787, GET-VJyr, [Uri-Path: sys, Uri-Path: dev, Uri-Path: status, Observe: 0, ] No payload
2020-05-07 16:25:56,878 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('192.168.0.134', 5683), To None, ACK-272, CONTENT-VJyr, [Observe: 14, Content-Type: 50, Max-Age: 60, ] 6CB55614FBE503D9FC3F...1137 bytes
2020-05-07 16:25:56,878 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('192.168.0.134', 5683), To None, ACK-272, CONTENT-VJyr, [Observe: 14, Content-Type: 50, Max-Age: 60, ] 6CB55614FBE503D9FC3F...1137 bytes
2020-05-07 16:25:56,979 - Thread-1 - coapthon.client.coap - DEBUG - Exiting receiver Thread due to request
Traceback (most recent call last):
File "./airctrl.py", line 771, in
@Cyber1000 Here is the encrypted payload:
$ airctrl --ipaddr 192.168.1.24 --version 1.0.7 -d 073CBCB1DCABB8CE96A60C81CBF8A6A9E57F4C9D0F0AD86C4B1A1F005874061AD6063DC72432138ABDD0A5AFEDD1D3333D430758DE3BD294BE026B2D1630A71C089EE74036C02F5D8954FEBA93A2886D3F8252263F770F3320ACEFB643FC65C97F0AC762B312AB18203D98F303DC3E1C7C8A8E3E35C86ED5C126121632088D569B50CFED6B72C4E44727E31E0AEE800B022B8B8F71D45CE19A50A0E94471661D9D4CA6694A75C81E5347FAE48E9F4706F6B169B8232BD23CCC9DD6353E2776199A5281EF351AA19AA8E1E003F7DAC6C93A05958EA71E1E55F0A78F63EC4F7D6258FD7F85D994AFF1815DFBC9714F85465FF0955884A3B39F55DDB62F19C7AD3A24AB1E66BEC78FA6FC727AF8C5BD28DB74655F836B71DD8872002F61FFCDF4799D40214F692953B4690A6B00FFBA5C260E5CDD998C2D8FB813EBC8E658B3B5E10907695268DA5DE213D5F134704AAA6E47B3DE42208BB9694F7E0F0414F42292E865A983EAFF0044D01E93F2E0ACF2F8FA4263064749ACE8A5A05FDD36EF1CF301A3311BE5FCE5E2B71085F752E1D4020A25BCECA9DDA4D577046395C82698B413666D7C3DAA0E7A4CEA7C1FD9DCB4FD791D82C12FA385E827F6B22D5C8F4FC6E0DE967BEEC5F365C39317CED6C2F6D86F3C03440724D9AC026A692C38D71BE227C4E59E828F02BB4CCB156919B1D989D76E4585DB6874FABFAD2495FC0365A53F542FACB244EBD35C80F4BEFA2CCB7A44A12A8B6D77D23388137600419878F3D946F9303C8003A7FB920105C2167DA0C9F0C6A238126DE0 Traceback (most recent call last): File "/home/Lorianne/philips/bin/airctrl", line 8, in <module> sys.exit(main()) File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 768, in main c.get_status(debug=args.debug) File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 636, in get_status status = self._get() File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 678, in _get decrypted_payload = self._decrypt_payload(encrypted_payload) File "/home/Lorianne/philips/lib/python3.8/site-packages/pyairctrl/airctrl.py", line 664, in _decrypt_payload decoded_message = AES.new(bytes(secret_key.encode('utf8')), AES.MODE_CBC, bytes(iv.encode('utf8'))).decrypt(bytes.fromhex(encoded_message)) File "/home/Lorianne/philips/lib/python3.8/site-packages/Cryptodome/Cipher/_mode_cbc.py", line 246, in decrypt raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) ValueError: Data must be padded to 16 byte boundary in CBC mode
This can be decrypted if we get a bigger chunk from the payload:
msg = encrypted_payload[8:-8].upper()
cipher = AES.new(secret_key.encode('ascii'), AES.MODE_CBC, iv.encode('ascii'))
print(cipher.decrypt(msg))
this is the result:
b'{"state":{"reported":{"name":"Maison","type":"AC3039","modelid":"AC3039/10","swversion":"Ms3104","language":"EN","DeviceVersion":"1.0.4","om":"s","pwr":"1","cl":false,"aqil":0,"uil":"0","uaset":"A","mode":"S","pm25":11,"iaql":3,"aqit":4,"tvoc":1,"ddp":"1","rddp":"1","err":0,"fltt1":"A3","fltt2":"none","fltsts0":129,"fltsts1":4752,"fltsts2":65535,"filna":"0","filid":"0","ota":"ck","Runtime":1037325155,"WifiVersion":"AWS_Philips_AIR@54.2","ProductId":"660c6902649b11e9a1e3061302926720","DeviceId":"0b529c58af8111e9a1e3061302926720","StatusType":"localcontrol'
As you can see it is truncated. I guess this means we should either increase the COAP response buffer or make another request.
I have written an ioBroker adapter for myself. I did not publish it because I have absolutely no time to maintain it. But if you are interested, I can upload the current version to GitHub.
@rgerganov @Cyber1000
As you can see it is truncated. I guess this means we should either increase the COAP response buffer or make another request.
2020-05-09 01:10:50,491 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('172.16.0.139', 5683), To None, ACK-1, CONTENT-nUQg, [Observe: 0, Content-Type: 50, Max-Age: 60, ] 53D70E9486BFD0E51915... 1138 bytes
Here is my encrypted payload:
53D70E9486BFD0E51915E2FAA605B32F2FDCCBB20995C527D841FCC6B88C408D25A0631FAEAC44F2F69806936C67A473BEA4712F20E2B2847B59D48B200E5297E2BE8ED8B0CE0BCE52841CDDC29DDC245C0FECF0F784BEAC4197BD3041A533427B8974918D8D7249C3F033EA35BCC3D574FC610168DC963B01B4B3DDBA8EA442F3AA106F1F7ED7D2292824CD42EBC8ADE2F2352986D03ADB56698959F0BC3A551AD9406378EB39E72352154EBB220685090119086E68E09549D62895E079939463B383DDFBA33655D8971356B17EE13D086777CC33E4F7644AE699610E5CE6530A5DA80657432ACE6ED2BB31E783DDC7E2CF17835D6530340BD75934D5A9F7469F7D2FC3CDA9DB28321541918D0F78B29CA110052B7D86D192C8CEE4C5F6D8447CCFEC67234A29897369EECCB08CFD554EF6B088FB2DE4E2D417C9BBBD6765ED6102EE7FB43D87A58D40596063830F2F329FAF23D6EA0D0364033578BAA74EF710F40615128C7EBF93D4C8DB2D36A1C2E183CD7D6AE89239327EE032B0F0B0917793252F03AFD602990E9BCF578A923472DB5D9669EED4F89E5215521D079A25A28DC1BDA583E00AC1FFB85D9337F40FAA4FC1BA113714D76226601B451DBDF2C5E2161B0028B630CE5D72FCACEE654357067BD55804A6FCB9DFB2617AE8C690A95466CAE7FD5BB80B84660D4CF9CFC24AAE7A183C9C244D0270662E939229943D821C8396192F9885A7DED122FF25A432B496BD134A1255E003CEC34166DEF34D91BB922ED0F801983C4577F916F916130E3A7A674904FC81
Firmware (from the app) reports as
Firmware Version: AWS_Philips_AIR@54.2 Device Version: 1.0.7 Model: AC2889/10
Any attempt to send a command just gets back
{"status":"failed"}
(looking at it via tcpdump). Also from tcpdump, the app appears to be exclusively using the cloud based system to talk to it. If I put both on a wifi network not connected to the internet, even the app doesn't work.