Toshiba home AC control

I do have the same AC (with the wireless adapter) and I am having the same problem. Therefore I tried to reverse-engineer the app.

I started by downloading the APK from https://apkpure.com/toshiba-home-ac-control/com.toshibatctc.SmartAC/versions - I used the oldest version as it was the smallest and so I assumed was the easiest to start with.
The APK is basically a zip file that holds the android application - usually a .tex file where the java code needs to be extracted. In this case the app uses assemblies - meaning there are like 100 .dll files that are used as a library.
Those can be easily copied and looked into using tools like ILSpy (Releases · icsharpcode/ILSpy · GitHub) or dnSpy (Releases · dnSpy/dnSpy · GitHub).
I noted that there is a SmartAC.dll which seems to handle most of the logic and the communication of the app.
In this dll I also found out about the propertyStore on the phone which holds some mapping information about the connected ACs (see later).

Here are my findings so far:

The app uses two interfaces:

  1. a normal HTTP API to get the current state of the AC and stuff like pairing and programmSettings
  2. a MQTT (or better an AMQPS) interface to update the current state (like change temperature or modes)

I made a small PHP script that is able to connect to the HTTP API and get some basic informations - see here: Toshiba AC API Client - Get status and settings from Toshiba AC Services (used e.g. in RAS-18PKVSG-E + RAS-18PAVSG-E + WIFI Adapter RB-N103S-G) · GitHub

The the problem with the AMQPS interface is, that I can’t find a working client. I tried it with py-amqp without success.

The AMQPS connection seems to be opened to:
amqps://toshibasmaciothubprod.azure-devices.net:5671/devices/XXXXX/messages/events

whereas XXXXX is your deviceId.

I have extract that part directly from my phone propertyStore using adb.
basically you install android studio, connect your phone to your PC, start the app, start the debugger and run:

adb shell
su
cat /data/user/0/com.toshibatctc.SmartAC/files/.config/.isolated-storage/PropertyStore.forms

this did work for me on a non-rooted phone and gave me an output similar to this:

@ArrayOfKeyValueOfstringanyTyp9http://schemas.microsoft.com/2003/10/Serialization/Arrays       i)http://www.w3.org/2001/XMLSchema-instance@KeyValueOfstringanyType@
  Key�[email protected]:string    a http://www.w3.org/2001/XMLSchema�en@KeyValueOfstringanyType@
  [email protected]:string  a http://www.w3.org/2001/XMLSchemaXXXXXXX@KeyValueOfstringanyType@
  Key�[email protected]:string a http://www.w3.org/2001/XMLSchema�$5XXXXXXX3@KeyValueOfstringanyType@
  Key�[email protected]:string a http://www.w3.org/2001/XMLSchema�@4XXXXb@KeyValueOfstringanyType@
  Key�   [email protected]�a:int a http://www.w3.org/2001/XMLSchema�@KeyValueOfstringanyType@
  Key�[email protected]�
a:dateTime      a http://www.w3.org/2001/XMLSchema�>�
ݼ\I@KeyValueOfstringanyType@
  Key�[email protected]�a:base64Binary     a http://www.w3.org/2001/XMLSchema�xxx@KeyValueOfstringanyType@
  [email protected]:string    a http://www.w3.org/2001/XMLSchema�'toshibasmaciothubprod.azure-devices.net@KeyValueOfstringanyType@
  [email protected]:string        a http://www.w3.org/2001/XMLSchema�pxxxb@KeyValueOfstringanyType@
  Key�[email protected]:string     a http://www.w3.org/2001/XMLSchema�,oxx8=

From here I extracted:

  • the UserName
  • a ConsumerID (which is the same when using the HTTP API)
  • the HostName: toshibasmaciothubprod.azure-devices.net (which differs from the http api)
  • my DeviceID (which included my Username and is used for the amqps connection)
  • and a SharedAceeskey (yes it has this typo)

Using another APP (Packet Capture https://play.google.com/store/apps/details?id=app.greyshirts.sslcapture&hl=en_US&gl=US) I was able to read out the communication from the app to the server - unfortunatelly this amqps seems to be some kind of binary protocol and a single on/off request, results in multible queue entries like this:

[RANDOMBYTES]
IoThub-methodname: smmobile
{"sourceId":"4xx8","messageId":"0000000a68","targetId":["pxxxA"],"cmd":"CMD_FCU_FROM_AC","payload":{"data":"ffffffff31ffffffffffffffffffffffffffff"},"timeStamp":"0060dce13c"}
[MORERANDOMBYTES]

So far I found out that data is just a string of all attributes as 2-byte hex-values concationated - where ff means that it did not change. Position 9+10 - like above - is reserved for the air swing mode and 31 means its off. 41 would swing it vertically.
In the HTTP API this data/payload is named ACStateDataForProgram - in my example it has the value: 31421a3131640010197ffe0b00001002010000 - 31 … means currently off, 42 … is cooling mode, 1a … is hex for 26 degrees target temperature and so on…

So - I really hope someone with more experience using amqps will pick it up from here and we can somehow get a working integration out of this.

5 Likes