Hints / Tips on reverse engineering dumb blind control

Hi All

I’ve recently had some work done to the house and had some “velux” windows installed in my kitchen’s vaulted ceiling. Despite being quoted for velux windows the builder actually installed another brand of window - Keylite.

I was planning on getting the velux automation kits so that I can automatically open the windows when the room gets too hot (this happens a lot as the room gets a lot of morning sun, this will save on aircon costs). Keylite do have a similar system but for some reason you can’t even hook the blinds up to Google Assistant or Alexa. The only control is from an app on your mobile phone - pretty much next to useless!

When you buy the kit you get the motor for the windows and a KeyliteConnect Hub (over £200 despite being mostly useless). It is connected over Wifi.

How likely is it that I would be able to figure out the api for communicating with this hub directly and controlling it from home assistant or node red rather than having to use the mobile app? I’ve never done anything like this before so no idea what hurdles I am likely to come up against.

There is also a chance I suppose that it has some common IOT chip in it that I would be able to re-flash. I’ve never actually flashed a chip like this let alone try and write a new config to it so I am quickly going to get out of my depth here!

Thanks

Some commonly used methods:

  • use tcpdump or Wireshark to see where data is being sent by the mobile app;
  • use a program like mitmproxy to eavesdrop on what your mobile phone is sending and receiving (and where to/from) when you’re using the app (assuming it uses HTTP(S));
  • try and find an APK (Android) or IPA (iOS) file for the mobile app so you can decompile it to see how it works;

I would not consider reflashing the device unless there’s absolutely no other way to work out what it does.

1 Like

Looks like it’s a cloud-based service:

p = o.default.create({ baseURL: 'https://app.keyliteroofwindows.com/v1' });
e.apiClient = p;
var f = o.default.create({ baseURL: 'https://app.keyliteroofwindows.com/oauth/' });
…
return o.apiClient.get('/user').then(function (n) {
return o.apiClient.post('/user/', { user: t }).then(function (t) {
return o.apiClient.put('/user/', { user: t }).then(function (t) {
return o.apiClient.post('/user/validate', { user: t }).then(function (t) {
return o.apiClient.post('/user/update_password', t).then(function (t) {
return o.apiClient.post('/user/send_reset_password_link', { email: t });
return o.apiClient.post('/user/reset_password_by_token', t).then(function (t) {
return o.apiClient.get('/user/validate_token?token=' + t).then(function (t) {
return o.apiClient.post('/user/confirm_email', { token: t }).then(function (t) {
return c.apiClient.get('/gateways').then(function (n) {
return o.apiClient.get('/gateways/' + t + '/groups').then(function (t) {
return o.apiClient.get('/gateways/' + t + '/windows').then(function (t) {

I found an APK for the app, it looks like it’s based on React Native so most of the code is JavaScript (quite heavily obfuscated though).

1 Like

wow, many thanks (I didn’t get an email about your reply so only just stumbled across it). I should be able to replicate what the app does then if it’s OAuth right? I’ll still need to use the cloud service but should be able to call it from Home assistant.

Probably, although you’d need OAuth (I assume it’s using OAuth2) credentials (which are probably stored in the app code too, though).

You’ve been very helpful already but I could do with some more help! :slightly_smiling_face:

So using the tool that you’ve mentioned I can monitor the communications from the app to the cloud but as it’s https I’m not going to be able to see the payload and won’t be able to extract the secret - is that correct? There’s no way I can look inside the https traffic?
Secondly have you got any guides or tips for downloading the apk and decompiling it. What tools do you use for that? (I’ve not googled this yet at all so I am sure the answers are out there but if you could give me a shortcut that would be much appreciated).

Thanks

With mitmproxy you can look inside HTTPS traffic, although it depends on how exactly the app communicates with the real server (if it uses client certificates, I don’t think you can make it work). The website should provide information on how to set it up on your phone.

General decompilation instructions are:

  • Find an APK (Android app) for your app. To do this, it works best to find the app identifier, which can be found in the URL of its Google Play page (in this case, the identifier is com.attopartners.keylite). Google for the identifier plus “apk” and you’ll find plenty of sites that will offer the APK for download (like this one).
  • Since an APK is basically a ZIP file, unzip it first. Sometimes there are additional APK files that get extracted, unzip those too.
  • To decompile the Java app itself, I use jadx. However, since the Keylite Connect app is mostly written in Javascript, this isn’t really necessary since most of the code is readable(-ish) JS code anyway and contained in the file assets/index.android.bundle.
  • To make the JS code more readable, I use prettier.

From there, experience starts playing a role, because even though the JS code is formatted, it’s still quite unreadable because it was obfuscated. So you start looking for tell-tale strings that point to the app making web requests, like auth, oauth, http:, https:, etc.

In this case, it looks there are two different login API’s, one “simple” (called “v1”) and one based on OAuth.

The simple one seems to perform a login like this:

POST https://app.keyliteroofwindows.com/v1/login

With data:

{ "username" : "XXX", "password" : "YYY", "grant_type" : "password", "scope" : "" }

(not sure if it’s JSON or URL-encoded)

This should return an access token, which should be sent with each additional API request, in the form of a header:

Authorization: Bearer TOKEN

The endpoints that I can find in the code:

GET('/user')
POST('/user/', { user: t })
PUT('/user/', { user: t })
POST('/user/validate', { user: t })
POST('/user/update_password', t)
POST('/user/send_reset_password_link', { email: t });
POST('/user/reset_password_by_token', t)
GET('/user/validate_token?token=' + t)
POST('/user/email_link', { email: t })
POST('/user/confirm_email', { token: t })
GET('/gateways')
POST('/gateways/' + u + '/claim', { name: l, mac_address: f, timezone: s })
PUT('/gateways/' + t.id, { gateway: t })
POST('/gateways/' + t.id + '/windows_close')
GET('/gateways/' + t + '/groups')
POST('/gateways/' + u.id + '/groups', { group: c })
PUT('/gateways/' + u.id + '/groups/' + c.id, { group: c })
POST('/gateways/' + n + '/groups/' + u + '/windows_open', { override: l })
POST('/gateways/' + n + '/groups/' + u + '/windows_close')
POST('/gateways/' + n + '/groups/' + u + '/windows_vent')
POST('/gateways/' + n + '/groups/' + u + '/windows_move_to_percentage', {
POST('/gateways/' + n + '/groups/' + u + '/blinds_move_to_percentage', {
POST('/gateways/' + n + '/groups/' + u + '/blinds_open')
POST('/gateways/' + n + '/groups/' + u + '/blinds_close')
DELETE('/gateways/' + u + '/groups/' + c.id)
GET('/gateways/' + t + '/windows')
POST('/gateways/' + c + '/windows/' + w + '/window_move_to_percentage', {
POST('/gateways/' + c + '/windows/' + w + '/window_vent')
POST('/gateways/' + c + '/windows/' + w + '/window_notice')
POST('/gateways/' + c + '/windows/' + w + '/window_close')
POST('/gateways/' + c + '/windows/' + w + '/blind_move_to_percentage', {
PUT('/gateways/' + c + '/windows/' + w.id, { window: w })
POST('/gateways/' + c + '/windows/' + w.id + '/machine_learn_mode', { window: w })
DELETE('/gateways/' + c + '/windows/' + w.id)

I don’t know what the variables are, but I assume in most cases an index or identifier that should become apparent when you retrieve the /gateways endpoint.

1 Like

Brilliant! You’ve save me a load of pain there. Hopefully what you’ve posted is all I need so I don’t need to get into the weeds of the other steps you’ve listed.
I like to think that I am an experienced js developer so hopefully I can get it working based on what you’ve posted using the simple login.

Did you end up getting this working @Roaders ?

No. I’ve not got round to ordering and getting it installed yet. It’s not a very simple process!

Hi @Roaders Did you manage to look into this at all? I’ve been lurking on this post for a while. To my absolute disbelief, Keylite have actually discontinued and completely turned off Keylite Connect without any notice, rendering the app and the smartness of the 2 x brand new keylite windows as useless.
I’m attempting to get a full refund as I feel like I’ve been mis-sold here. I am seething, how they can do this. I bought these windows due to the fact they were smart, I would have gone elsewhere if they had told me it was being discontinued i.e. velux. Not happy at all.

Saying that, I could ask for the source code - see if they can release it now its defunct? If you have managed to reverse engineer it as well please let me know.

All the best!

More often than not manufacturers like Keylite don’t develop their own digital products. This seems to be the case here as well, judging from the App Identifier (com.attopartners.keylite). In that case manufacturers often don’t own the source code and one of the reasons for discontinuing service is that license fees to their digital product provider are too high, especially if the product isn’t as successful as anticipated.
But Keylite has done a quite good job to scrub any mention of Keylite Connect from any of their official communication. Looking at their website you’d never know it existed.

No, I am afraid I never got round to it (although maybe I made a lucky escape).
This sort of thing is exactly why allowing local control of smart devices is so important.

Hi @FelixKa @Roaders thanks for getting back to me. Knew it would be a slim chance if any, and appreciate your feedback and insight. Funnily, Keylite were still advertising the top spec model of window as Keylite Connect compatible on the 7th Feb 2023, on the 8th it was moved to a Wi-Fi symbol, even though the app / service was completely taken offline around a month ago with no warning, no press release etc.
I’m going to be attempting to pursue some compensation… and hopefully move to velux. Could all be avoided if they could allow local control somehow.
All the best!

even if they refund you the cost of the windows it’s still going to be very expensive to remove them and install velux though right? Re-decoration, re-tiling the roof, scaffolding perhaps?

See I’ve gone with a different approach as you say, the £200 for a dumb WiFi <-> RF thing, I’m pretty sure the remote is just RF, (Going after a few other RF things around the house/garage as well).

So I’ve got a Broadlink RM4 Pro on the way from Amazon (£39.99) which should just let me randomly pair things around the house and filter through to Home assistant as the integration already exists. You could probably have gotten away with one of the other Broadlink models however.

Looking forward to your findings as I also have these windows and looking into ways to automate them.

Have you received your rm4 pro yet? I have one and hoping I can use it to control the Keylite blinds. I have one with the dual band Rf so hoping it will work but would be great to get an update.

So i bit the bullet and bought these blinds thinking i would be able to use the Broadlink to control them. This is not the case. The remote uses rolling codes and this means the Broad link cannot learn the code. I have been doing some testing this morning as the broad link can detect a code, but it keeps changing. I thought if there was a pattern to the codes then i could create something to try all those codes. Unfortunately there was a small section of frequencies used for the up button but then when testing the down button the same frequencies were used so the system is difficult to replicate. I was wondering if there were any such projects that could duplicate the remote function as it is a fifteen channel transmitter Model number : DD2702H. Just as a hail Mary i tried to pair it with my lightwave rf hub but no joy, but am slowly coming round to the idea of pushing a button on a remote being the only way. If any of you clever chaps out there have any better ideas i am all ears and fairly tech savvy so can help where i can.

Hey Matthew, did you get anywhere with any alternatives? I’ve got 3 windows with blinds and sadly my kids have managed to break all 3 remotes (stupid lcd screens that if you look at them wrongly they break). Would rather get something better than these rubbish remotes.