๐ป Making an Android App Jasa
Making my own square on my phone
Ever wondered what it takes to get one of those squares on your phone that you can tap and it does something? I did. Was curious one day several years ago, what's all involved in that. So I found a problem and set out to make a mobile app for it.
๐ฑ The Problemโ
Not going to lie, my problem I didn't focus to much on, just wanted to make an app and see what was possible. I always never liked plugging my phone in to charge before bed, for it to get fully charged within an hour or so and then sit at full charge for the rest of the night, and hurt the battery. But I wanted my phone to be charged in the morning also.
๐ Home Smart Plugsโ
I had these home smart plugs, that you can control with your phone. I figured I could plug a charger into one of those and have an app that would turn the plug off (stopping charge) once the phone battery got to a certain point.
๐ Python Scriptโ
Before I had this idea, I had already come across this article - Reverse Engineering the TP-Link HS110, which used a python script to control the plugs. So I knew it was possible to control the plugs with code.
๐ ๏ธ Starting Developmentโ
I have an Android phone and to start developing I just had to install Android Studio, the IDE for Android app development on a PC. To install my app on my phone I had to enable developer mode on my phone, which entails these steps:
- Go to Settings > System.
- Touch About phone.
- Touch the Build number field 7 times. You will begin seeing a message as you approach the 7 touches.
- Touch the back arrow once complete, and Developer options will now appear under Settings.
Then building the app was pretty straight forward with Android Studio. I won't go into to much detail about the whole process but I did want to share probably the hardest part.
๐ The hardest partโ
Firstly one of the things I had to figure out was converting the python script found in the article I mentioned into what Android apps are written in, Java. The hardest part of this conversion was that the commands sent to the smart plugs are a JSON object but encoded so if you capture the live packets sent across the network, you can't make out the commands. The python script had functions that did this encoding and decoding of the commands. But after the article came out, the plugs got a firmware update that changed how the plugs communicated with the app. The author did update the python script but did not explain what or why the changes were made and my translation of the functions wasn't working.
I worked on this problem for weeks, trying all sorts of things. I ended up quiting on the app for a couple weeks. But it ate at me and I eventually picked it back up. Two things lead me to the solution. One, I unpacked the original app to read its source code, which had minified code, but I was able to find the encryption code and see how it was done. But I was still missing something. And so two, through a series of packet captures, from the packets sent from my app and the original plug app, I noticed the original app had extra hexadecimal bytes on the end of the command packet. These bytes were just empty zeros, and after adding them to my command packets, my app started working. I tell you the audible click of the plug turning off from my app was so satisfying.
๐ฆ Codeโ
Encode command to be sent
String cmd = "{\"system\":{\"set_relay_state\":{\"state\":0}}}";
byte pkt[] = new byte[cmd.length() + (int) 4];
//create 4 byte header with cmd length in last byte
pkt[0] = (byte) 0;
pkt[1] = (byte) 0;
pkt[2] = (byte) 0;
pkt[3] = (byte) cmd.length();
//encode command then add its bytes to pkt after the header
byte encodedBytes[] = encode(cmd.getBytes());
int c = 0;
for (int i = 4; i < pkt.length; i++)
{
pkt[i] = encodedBytes[c];
c++;
}
Decode response from plug
//remove 4 byte header and decode into response json
c = 4;
byte nrsp[] = new byte[resultBuff.length - 4];
for (int i = 0; i < nrsp.length; i++) {
nrsp[i] = resultBuff[c];
c++;
}
nrsp = decode(nrsp);
Encode and decode functions
private static byte[] encode(byte[] bArr) {
byte b = -85;
for (int i = 0; i < bArr.length; i++) {
bArr[i] = (byte) (b ^ bArr[i]);
b = bArr[i];
}
return bArr;
}
private static byte[] decode(byte[] bArr) {
byte b = -85;
for (int i = 0; i < bArr.length; i++) {
byte a = (byte) (b ^ bArr[i]);
b = bArr[i];
bArr[i] = a;
}
return bArr;
}
๐คก Jasa Appโ
Here's a picture of the app, not much to look at, but it worked. You input the IP of the smart plug, specify your desired max charge percentage and click run. I also integrated the ability to load previous settings and run on launch so I could set my phone on a wireless charger that had a NFC tag that opened the app and it would seamlessly shut the charger off.
And now I just use the built in setting on my phone that stops charging at 85% ๐.