Hacking Electrolux Smart AC

@alex.venom, Legend! was just about to start down this path having imported everything else I own now into HA (about 3 days ago started with HA again), and finding the only thing that doesn’t have an integration is the aircon.

Did you have the chance to try that out?
I’ve seen this video on Youtube: https://youtu.be/Hl0IpoS503A
I might try that and see if I can get any luck…

I’m running a Kelvinator AC so it may be different.

The Kelvinator Home Comfort app from my iphone has a sqlite db that has the following info for my model profile:

{“ac_mark”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1,2,3,4,5],“act”:3}],“scrdisp”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:3}],“modelnumber”:[{“ifttt”:0,“idx”:1,“in”:[3],“act”:3}],“sn”:[{“ifttt”:0,“idx”:1,“in”:[3],“act”:3}],“ac_timingtime”:[{“ifttt”:0,“idx”:1,“in”:[3],“act”:3}],“ac_pwr”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:3}],“ac_timingenable”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:3}],“mldprfdisplay”:[{“ifttt”:0,“idx”:1,“in”:[1,1],“act”:1}],“slpdisplay”:[{“ifttt”:0,“idx”:1,“in”:[1,0],“act”:1}],“ac_mode”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1,2,3,4,6],“act”:3}],“ac_setsleepinfan”:[{“ifttt”:0,“idx”:1,“in”:[1,0],“act”:1}],“envtemp”:[{“ifttt”:0,“idx”:1,“in”:[2,-20,65,1,1],“act”:1}],“lightdisplay”:[{“ifttt”:0,“idx”:1,“in”:[1,1],“act”:1}],“ac_setautomarkinfan”:[{“ifttt”:0,“idx”:1,“in”:[1,1],“act”:1}],“ac_vdir”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:3}],“ac_errcode”:[{“ifttt”:0,“idx”:1,“in”:[2,0,255,1,1],“act”:1}],“ac_setquietinallmode”:[{“ifttt”:0,“idx”:1,“in”:[1,1],“act”:1}],“timer”:[{“ifttt”:0,“idx”:1,“in”:[3],“act”:3}],“ac_slp”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:3}],“mldprf”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:3}],“temp”:[{“ifttt”:0,“idx”:1,“in”:[2,16,30,1,1],“act”:3}],“ac_settempindehum”:[{“ifttt”:0,“idx”:1,“in”:[1,0,1],“act”:1}]}

1 Like

That was a great idea, @talondnb!
I made a backup of my iPhone and opened using iBackup Viewer. Then got a. file form the Electrolux app called “ConnectAppHub” which turned out to be a SQL database.
I then opened that in DB Browser for SQLite and was able to see a LOT of tables:

Most of those are empty, but I could find my Favorite settings saved in the ArConFavorite table, but what is really cool is the Configuration table, which has all the API endpoints:

I could find my ACs and fridge in the PNCDetails table, but not the token.
I also got a few JSON files but found nothing interesting in those.

2 Likes

I am also interested in integrating my portal Electro lux ac (WP71-265WT), its communicating with ibroadlink.com. I have some dumps of the traffic, captured it with mitmproxy, but Its not a plain-text protocol.

Ibroadlink have a appsdk demo for android and ios on github:


My Findings so Far on Reverse Engineering the Kelvinator Home Comfort API

First off, this is the first time I’m doing anything like this so just brain dumping what I’ve found so far and hoping it helps any smarter people than me, and I’ll keep researching.

I set up mitmproxy running on macOS to intercept traffic from my Android Pixel 4 XL, whilst performing a number of functions in the app including signing in to the app, I found 4 URLs (that appear to be api endpoints by the looks of them). I can’t seem to query then in Postman however and get the error {"error":-2002,"status":-2002,"msg":"数据错误"}

Funnily enough, when toggling the aircon (Kelvinator brand) on/off (or any control for that matter), no traffic is transmitted at all.


Identified the following URL’s

Endpoint /account/login

Traffic is captured when signing into the app, no traffic captured when signing out.

Request

Content-type:     application/x-java-serialized-object
system:           android
appPlatform:      android
language:         en-au
timestamp:        1591960217
token:            [REDACTED]
User-Agent:       Dalvik/2.1.0 (Linux; U; Android 10; Pixel 4 XL Build/QQ3A.200605.002.A1)
Host:             bddb4af53f74edaa03b1aa439b75e7a6bizaccount.ibroadlink.com
Connection:       Keep-Alive
Accept-Encoding:  gzip
Content-Length:   144

Response

{
  "error":0,
  "status":0,
  "msg":"ok",
  "userid":"[REDACTED]",
  "companyid":"[REDACTED]",
  "nickname":"[REDACTED]",
  "iconpath":"",
  "sex":"male",
  "loginsession":"[REDACTED]",
  "logintime":"2020-06-12T19:10:19+08:00",
  "loginip":"[REDACTED]",
  "fname":"",
  "lname":"",
  "usertype":"0",
  "phone":"[REDACTED]",
  "email":"",
  "flag":1,
  "birthday":"0000-00-00 00:00:00",
  "pwdflag":0,
  "countrycode":""
}

Endpoint /user/getfamilyid

Traffic is captured when the app is listing the devices in app.

Request

Content-type:     application/x-java-serialized-object
system:           android
appPlatform:      android
language:         en-au
loginsession:     [REDACTED]
lid:              [REDACTED]
userid:           [REDACTED]
timestamp:        1591959932
token:            [REDACTED]
User-Agent:       Dalvik/2.1.0 (Linux; U; Android 10; Pixel 4 XL Build/QQ3A.200605.002.A1)
Host:             bddb4af53f74edaa03b1aa439b75e7a6bizihcv0.ibroadlink.com
Connection:       Keep-Alive
Accept-Encoding:  gzip
Content-Length:   64

Response

{
  "error":0,
  "status":0,
  "msg":"ok",
  "familyinfo":[{
    "id":"[REDACTED]",
    "familyname":"Electrolux Family",
    "version":"2020-03-11 18:25:07",
    "shareflag":0
  }]
}

Endpoint /family/getallinfo

Traffic is captured after the user/getfamilyid POST and is captured when the app is listing the devices in app. Again funnily enough the only device I have is called Master Bedroom aircon and is not set in a room so don’t know where all the rooms are coming from.

Request

Content-type:     application/x-java-serialized-object
system:           android
appPlatform:      android
language:         en-au
loginsession:     [REDACTED]
lid:              [REDACTED]
userid:           [REDACTED]
timestamp:        1591959932
token:            [REDACTED]
User-Agent:       Dalvik/2.1.0 (Linux; U; Android 10; Pixel 4 XL Build/QQ3A.200605.002.A1)
Host:             bddb4af53f74edaa03b1aa439b75e7a6bizihcv0.ibroadlink.com
Connection:       Keep-Alive
Accept-Encoding:  gzip
Content-Length:   64

Response

{
  "error":0,
  "status":0,
  "msg":"ok",
  "familyallinfo":[{
    "familyid":"",
    "shareflag":0,
    "familystate":0,
    "createuser":"[REDACTED]",
    "familyinfo":{
      "familyid":"[REDACTED]",
      "userid":"",
      "name":"Electrolux Family",
      "description":"20200311 20:21:34",
      "familylimit":0,
      "postcode":"",
      "mailaddress":"",
      "longitude":0,
      "latitude":0,
      "country":"",
      "province":"",
      "city":"",
      "area":"",
      "order":0,
      "icon":"https://bddb4af53f74edaa03b1aa439b75e7a6bizihcv0.ibroadlink.com",
      "version":"2020-03-11 18:25:07",
      "location":{
        "country":"",
        "province":"",
        "city":""
        },
      "orgname":"",
      "groupname":"",
      "attributes":[""],
      "additional":{
        "room":{
          "roomlist":null,
          "action":""
          }
        }
      },
      "roominfo":[{
        "familyid":"[REDACTED]","roomid":"2108073310317223722","name":"Senior housing","type":22,"order":15},{
        "familyid":"[REDACTED]","roomid":"2108119028718423284","name":"Dining room","type":19,"order":12},{
        "familyid":"[REDACTED]","roomid":"2108122847830735903","name":"Shower room","type":23,"order":16},{
        "familyid":"[REDACTED]","roomid":"2108247970584067929","name":"Bathroom","type":6,"order":6},{
        "familyid":"[REDACTED]","roomid":"2108323198848892842","name":"Second bedroom","type":18,"order":11},{
        "familyid":"[REDACTED]","roomid":"2108359874668912446","name":"Downstairs","type":28,"order":21},{
        "familyid":"[REDACTED]","roomid":"2108432329282346271","name":"Balcony","type":20,"order":13},{
        "familyid":"[REDACTED]","roomid":"2108614973837138423","name":"Guest room","type":2,"order":2},{
        "familyid":"[REDACTED]","roomid":"2108619978015459890","name":"Dining room","type":14,"order":8},{
        "familyid":"[REDACTED]","roomid":"2108729120378245569","name":"Living-room","type":10,"order":7},{
        "familyid":"[REDACTED]","roomid":"2108729232751990839","name":"Second floor","type":26,"order":19},{
        "familyid":"[REDACTED]","roomid":"2108747350697851510","name":"Study room","type":3,"order":3},{
        "familyid":"[REDACTED]","roomid":"2108765696525464922","name":"Master bedroom","type":17,"order":10},{
        "familyid":"[REDACTED]","roomid":"2108830474760370051","name":"Upstairs","type":27,"order":20},{
        "familyid":"[REDACTED]","roomid":"2108932253061927840","name":"Baby room","type":4,"order":4},{
        "familyid":"[REDACTED]","roomid":"2108966886782394463","name":"Kitchen","type":5,"order":5},{
        "familyid":"[REDACTED]","roomid":"2109041418065768636","name":"Children room","type":16,"order":9},{
        "familyid":"[REDACTED]","roomid":"2109059107734149287","name":"Bedroom","type":1,"order":1},{
        "familyid":"[REDACTED]","roomid":"2109127730762341864","name":"Pet room","type":21,"order":14},{
        "familyid":"[REDACTED]","roomid":"2109147301001058335","name":"The entrance","type":24,"order":17},{
        "familyid":"[REDACTED]","roomid":"2109189274487488426","name":"Ground floor","type":25,"order":18}],
      "devinfo":[{
        "userid":"",
        "familyid":"[REDACTED]",
        "version":"",
        "roomid":"",
        "did":"0000000000000000000024dfa74bbc6f",
        "mac":"24:df:a7:4b:bc:6f",
        "password":[REDACTED],
        "devtype":20379,
        "pid":"0000000000000000000000009b4f0000",
        "name":"Master Bedroom Aircon",
        "lock":false,
        "aeskey":"[REDACTED]",
        "terminalid":1,
        "subdevicenum":0,
        "longitude":0,
        "latitude":0,
        "extend":"",
        "wifimac":"",
        "devicetypeflag":0,
        "groupdevice":null}],
      "moduleinfo":[{
        "moduleid":"3108480959390461651",
        "userid":"",
        "familyid":"[REDACTED]",
        "version":"",
        "roomid":"",
        "name":"Master Bedroom Aircon",
        "icon":"",
        "flag":1,
        "moduledev":[{
          "did":"0000000000000000000024dfa74bbc6f",
          "sdid":"",
          "order":0,
          "content":"",
          "devmoduleid":""}],
        "order":1,
        "moduletype":1,
        "scenetype":"",
        "followdev":1,
        "extend":"",
        "extern":"",
        "linkagetype":"",
        "attributes":[""],
        "resourcetag":""}]}]}

Endpoint /common/api

Traffic captured randomly when opening the app after the 3rd time.

Request

system:           android
appPlatform:      android
language:         en-au
timestamp:        1591962013
User-Agent:       Dalvik/2.1.0 (Linux; U; Android 10; Pixel 4 XL Build/QQ3A.200605.002.A1)
Host:             bddb4af53f74edaa03b1aa439b75e7a6bizihcv0.ibroadlink.com
Connection:       Keep-Alive
Accept-Encoding:  gzip

Response

{
  "error":0,
  "status":0,
  "msg":"ok",
  "key":"[REDACTED]",
  "timestamp":"1591962015"
}
1 Like

I’ve also unpacked the Android apk for the Kelvinator Home Comfort app, however I’m going to bed so thought I’d upload to GitHub if anyone cared to filter through it.

1 Like

Was anyone able to get an further on this?

@TJohnson93 did you make any progress on this? I’ve just put in a Kelvinator and looking to integrate it to HASS. If I can do it directly that would be awesome, but I also have Tado heating so could use their AC IR control…but then would have to try to hid those units somewhere.

Will be willing to PayPal anyone who can sort this out $20.
There’s some really helpful tips in this thread. When I have some spare time I will see if I can contribute at all.
If anyone seeing this can provide any general advice about what the next steps would be, I’d appreciate it.
Took me about 3 weeks and 30+ support calls to get them to fix the integration with google home, I think the likelihood of any Dev support from Kelvinator/Electrolux whatsoever is absolutely impossible. (For anyone curious they never told me what they did, or responded to my questions asking how they fixed it, it just appeared in my device list in the home app today)

Unfortunately I haven’t had much opportunity to play anymore @pixsoul, I’ve even begun contemplating just putting up with the Google home app haha

following.

This needs to be done. Please :raised_hands:t3:

Checkout this article (in Russian): Управляем конвектором и термостатом Electrolux из Home Assistant. Часть 1 / Хабр
This article has part 2 where author (Ailme) implemented custom component
Custom component repository is here: GitHub - Ailme/home_assistant_electrolux_remote: Integration Electrolux remote device in Home Assistant

1 Like

Good find!
Here’s the translated version of the Github repo: Google Translate

Did anyone try this component? My impression that it might not work for my Electrulux AC, a Well P7.

Hello! It’s work on Electrolux EACS/i-09HAT/N3 with ESPHome USB Stick. This is a completely working option with getting the state of the device, i.e. mode changes from the remote control are transmitted to the Home assistant.

There is also a solution for devices that work through the Home Comfort App. The author in the telegram channel writes that the specified model of the air conditioner will work, but I did not check this option due to the lack of the original ECH / WF-01 module

Good luck!

1 Like

Checked out the post but didn’t get any clever on it, anyone could clear it out for me?

Try to ask the questions you are interested in in the Telegram group. Preferably with translation into Russian. Telegram: Contact @midea_smart_russia

For those Aussies using Kelvinators I havn’t been able to add the Electrolux Remote Device Custom Integration yet into HA (emulating the Home Comfort app) and have added to an existing issue with the dev on GitHub.

So, this thread is becoming a dumping ground, in case smarter people then me see something I don’t or I get some ideas from peeps… Decompiled APK and found the file BLApiUrls.java under Sources > com > electrolux > aircondition > http > data > containing:

package com.electrolux.aircondition.http.data;

public class BLApiUrls {
    public static final String BAIDU_AUTH_INFO = "https://openapi.baidu.com/oauth/2.0/authorize";
    public static final String BAIDU_AUTH_INFO2 = "https://openapi.baidu.com/oauth/2.0/token";
    private static final String BASE_AC_URL = "https://cloudac.ibroadlink.com";
    public static String BASE_APP_MANAGE = "https://%sbizappmanage.ibroadlink.com";
    public static String BASE_FAMILY_URL = "https://%sbizihcv0.ibroadlink.com";
    private static final String BASE_TV_URL = "https://publictvir.ibroadlink.com";
    public static String BASE_VIRTUAL_DEV = "https://%sbizvdreg.ibroadlink.com";
    public static final String CLOUD_AC_BRAND_LIST = "https://cloudac.ibroadlink.com/cloudac/reqcloudname";
    public static String CLOUD_NEW_BASE = "https://%srccode.ibroadlink.com";
    public static final String CLOUD_TV_BRAND_LIST = "https://publictvir.ibroadlink.com/publictv/gettvbrand";
    public static String ELECTROLUX_URL = "https://%sthirdpartyservice.ibroadlink.com";
    public static String FAQ_URL = "https://kelvinatordownload.ibroadlink.com/soft/Kelvinator/help/";
    public static final String FEEDBACK = "https://feedback.ibroadlink.com/feedback/report";
    public static final String FW_VERSION = "https://fwversions.ibroadlink.com/getfwversion?devicetype=%1$s";
    public static final String GET_CITY_LIST = "https://publictvir.ibroadlink.com/publictv/getcity";
    public static final String GET_PROVIDER_LIST = "https://publictvir.ibroadlink.com/publictv/getprovider";
    public static final String GET_PROVINCES_LIST = "https://publictvir.ibroadlink.com/publictv/getprovince";
    public static String GOOGLEPLAY_URL = "https://play.google.com/store/apps/details?id=com.kelvinator.airconditioner";
    public static String GUIDE_URL = "https://kelvinatordownload.ibroadlink.com/soft/Kelvinator/help/#/answer/33";
    public static final String MS1_VERSION_URL = "https://upgrade.ibroadlink.com/sw/musicbox/stable/version.html";
    public static String PRIVACY_URL = "https://electrolux.ibroadlink.com/soft/privacy/#/";
    public static String PRIVACY_URL_AU = "https://www.kelvinator.com.au/other/privacy/";
    public static String PRIVACY_URL_NZ = "https://www.kelvinator.co.nz/other/privacy/";
    public static final String QT_FM_CATEGORIES = "http://api.qingting.fm/api/tongli/qtradiov4/categories?id=507&deviceid=%1$s";
    public static final String QT_FM_CHANNEL_LIST = "http://api.qingting.fm/api/tongli/qtradiov4/items";
    public static final String QT_FM_PROGRAM_LIST = "http://api.qingting.fm/api/tongli/qtradiov4/programs";
    public static final String QT_FM_RADIO_CATEGORY = "http://api.qingting.fm/api/tongli/qtradiov2/categories?id=100002&deviceid=%1$s";
    public static final String QT_FM_RADIO_STATION_LIST = "http://api.qingting.fm/api/tongli/qtradiov2/items";
    public static final String QUERY_BRAND_AC_LIST = "https://cloudac.ibroadlink.com/cloudac/oldversion/requrlbyname";
    public static final String QUERY_BRAND_TV_LIST = "https://publictvir.ibroadlink.com/publictv/geturldbybrand";
    public static final String QUERY_CHANNEL_HAS_NUM_LIST = "https://publictvir.ibroadlink.com/publictv/tvchannel/getlistchannel";
    public static final String QUERY_CITY_INFO = "https://publictvir.ibroadlink.com/publictv/query/areainfobyid";
    public static final String QUERY_COLUD_AC_RECOGNIZE_LIST = "https://cloudac.ibroadlink.com/cloudac/oldversion/recognize";
    public static final String QUERY_DEV_ELEC = "https://%srtasquery.ibroadlink.com/dataservice/v1/device/stats";
    public static final String QUERY_DEV_HISTORY = "https://%srtasquery.ibroadlink.com/dataservice/v1/device/status";
    public static final String QUERY_PROVIDER_CODE_LIST = "https://publictvir.ibroadlink.com/publictv/geturlbyarea";
    public static final String QUERY_PROVIDER_INFO = "https://publictvir.ibroadlink.com/publictv/query/providerinfobyid";
    public static final String QUERY_TV_CHANNEL_LIST = "https://publictvir.ibroadlink.com/publictv/tvchannel/getchannel";
    public static final String SPK_GET_ALL_RADIO_LIST = "https://ms1.ibroadlink.com/spkchannel?method=getall";
    public static final String SPK_GET_NET_RADIO_UPDATE_TIME = "https://ms1.ibroadlink.com/spkchannel?method=getupdatetime";
    public static final String SP_HOSTROY = "https://cn-clouddb.ibroadlink.com/spmini/history/status";
    public static String TERM_CONDITION_URL = "https://electrolux.ibroadlink.com/soft/terms/#/";
    public static String TERM_CONDITION_URL_AU = "https://www.kelvinator.com.au/other/terms-and-conditions/";
    public static String TERM_CONDITION_URL_NZ = "https://www.kelvinator.co.nz/other/terms-and-conditions/";
    public static String TEST_FAMILY_URL = "https://%sbizihcv0.ibroadlink.com";
    public static String TEST_MODELNUMBER_URL = "https://%sbizappmanage.ibroadlink.com";
    public static final String THRID_DEV_VALIDITY_CHECK_RUL = "https://3rddevrecognize.ibroadlink.com/ec/v1/thirdparty/productinfo/check";
    public static final String UPDATE_CHANNEL = "https://publictvir.ibroadlink.com/publictv/user/revisechannel";
    public static final String UPLOAD_REVISE_IRDA = "https://publictvir.ibroadlink.com/publictv/user/revisedata";
    public static final String WEIXIN_REQUEST_AUTHORIZE = "https://api.weixin.qq.com/device/authorize_device?access_token=";
    public static final String WEIXIN_REQUEST_QR = "https://api.weixin.qq.com/device/create_qrcode?access_token=";
    public static final String WEIXIN_REQUEST_TOKEN = "http://wechat.ibroadlink.com/control/key";
    public static final String XIMA_GET_CATEGORIES = "http://3rd.ximalaya.com/categories";
    public static final String XIMA_GET_CATEGORIES_ALBUMS = "http://3rd.ximalaya.com/categories/%1$s/hot_albums";
    public static final String XIMA_GET_CATEGORIES_TAGS = "http://3rd.ximalaya.com/categories/%1$s/tags";
    public static final String XIMA_SEARCH_ALBUMS = "http://3rd.ximalaya.com/search/albums";
    public static final String XIMA_SEARCH_VOICE = "http://3rd.ximalaya.com/search/tracks";

    public static void init(String str) {
        BASE_FAMILY_URL = String.format(BASE_FAMILY_URL, new Object[]{str});
        BASE_APP_MANAGE = String.format(BASE_APP_MANAGE, new Object[]{str});
        BASE_VIRTUAL_DEV = String.format(BASE_VIRTUAL_DEV, new Object[]{str});
        CLOUD_NEW_BASE = String.format(CLOUD_NEW_BASE, new Object[]{str});
        ELECTROLUX_URL = String.format(ELECTROLUX_URL, new Object[]{str});
        TEST_FAMILY_URL = String.format(BASE_FAMILY_URL, new Object[]{str});
        TEST_MODELNUMBER_URL = String.format(TEST_MODELNUMBER_URL, new Object[]{str});
    }

    public static class Electrolux {
        public static final String ADD_DEV_HW_INFO() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/dev/adddevhwinfo";
        }

        public static final String UPDATE_DEV_HW_INFO() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/dev/editdevhwinfo";
        }

        public static final String DELETE_DEV_HW_INFO() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/dev/deldevhwinfo";
        }

        public static final String GET_DEV_HW_INFO() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/dev/getdevhwinfo";
        }

        public static final String GET_MODELNUMBER_LIST() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/dev/getmodelnumberlist";
        }

        public static final String GET_DEV_PID() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/dev/getdevtype";
        }

        public static final String GET_DEV_PID_QRCODE() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/resource/product/qrcode";
        }

        public static final String GET_DEV_PID_QRCODE_NEW() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/language/product/qrcode";
        }

        public static final String ADD_TIMETASK() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/timetask/manage/add";
        }

        public static final String UPDATE_TIMETASK() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/timetask/manage/update";
        }

        public static final String DELETE_TIMETASK() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/timetask/manage/del";
        }

        public static final String QUERY_TIMETASK() {
            return BLApiUrls.ELECTROLUX_URL + "/thirdparty/v1/timetask/query";
        }

        public static final String QRCODE_GENERATE() {
            return BLApiUrls.TEST_FAMILY_URL + "/ec4/v1/dev/qrcode/generate";
        }

        public static final String QRCODE_SCAN() {
            return BLApiUrls.TEST_FAMILY_URL + "/ec4/v1/dev/qrcode/scan";
        }

        public static final String DEVICE_DELETE() {
            return BLApiUrls.TEST_FAMILY_URL + "/ec4/v1/dev/share/delete";
        }

        public static final String QUERY_SHAREFAMILY_MEMBER() {
            return BLApiUrls.TEST_FAMILY_URL + "/ec4/v1/dev/sharefamily/query";
        }

        public static final String DELETE_SHAREFAMILY_MEMBER() {
            return BLApiUrls.TEST_FAMILY_URL + "/ec4/v1/dev/sharefamily/delete";
        }

        public static final String GET_PRICATEGORY_LIST() {
            return BLApiUrls.TEST_MODELNUMBER_URL + "/ec4/v1/system/language/category/list";
        }

        public static final String GET_CATEGORY_LIST() {
            return BLApiUrls.TEST_MODELNUMBER_URL + "/ec4/v1/system/language/product/list";
        }

        public static final String GET_QRCODE_LIST() {
            return BLApiUrls.TEST_MODELNUMBER_URL + "/ec4/v1/system/getproductlist";
        }
    }

    public static class AppManager {
        public static final String PRODUCT_ICON() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/configfile";
        }

        public static final String ADD_PRODUCT_DIRECTORY() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/language/category/list";
        }

        public static final String ADD_PRODUCT_LIST() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/language/product/list";
        }

        public static final String ADD_PRODUCT_DETAIL() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/language/product/info";
        }

        public static final String ADD_QR_PRODUCT_DETAIL() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/language/product/qrcode";
        }

        public static final String GET_SP_APPLIANCE_LIST() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/getsmartplugapp";
        }

        public static final String QUERY_DEFAULT_ROOM() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/defineroom";
        }

        public static final String APPLY_VIRTUAL_DEV() {
            return BLApiUrls.BASE_VIRTUAL_DEV + "/ec/v2/thirdparty/dev/didapply";
        }

        public static final String DEVICE_AUTH() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/auth/add";
        }

        public static final String DEVICE_AUTH_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/auth/query";
        }

        public static final String LOCATION_CONFIG_URL() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/config/getconfig?mtag=locationconfig";
        }

        public static final String GET_SCENE_DETAIL() {
            return BLApiUrls.BASE_APP_MANAGE + "/ec4/v1/system/scenedetail";
        }
    }

    public static class Family {
        public static final String RM_TC() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/model/other/tc_home_big_off.png";
        }

        public static final String RM_AC() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/icon_module_rm_ac.png";
        }

        public static final String RM_TV() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/icon_module_rm_tv.png";
        }

        public static final String RM_STB() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/icon_module_rm_stb.png";
        }

        public static final String RM_CHANNEL() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/icon_module_rm_stb_channel.png";
        }

        public static final String RM_CTRL_CENTRE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/icon_module_total_control.png";
        }

        public static final String RM_STATISTICS() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/icon_module_statistics.png";
        }

        public static final String RM_LAMP() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/lamp_home_big_off.png";
        }

        public static final String RM_CURTAIN() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/curtain_on.png";
        }

        public static final String RM_COMMON() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/moduleicon/commonpanel.png";
        }

        public static final String APP_VERSION_URL() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/app/update";
        }

        public static final String APP_HELP_URL() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4appsysinfo/helppage/help.html";
        }

        public static final String FAMILY_REQUEST_TIMESTAMP() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/common/api";
        }

        public static final String GET_DEVICE_FAMILY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/dev/getfamily";
        }

        public static final String GET_RM_BTN_ICON_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/system/defineircodeicon";
        }

        public static final String CREATE_FAMILY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/add";
        }

        public static final String EDIT_FAMILY_INFO() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/modifyinfo";
        }

        public static final String EDIT_FAMILY_ICON() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/modifyicon";
        }

        public static final String EDIT_ROOM_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/room/manage";
        }

        public static final String REQUEST_FAMILY_QRCODE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/invited/reqqrcode";
        }

        public static final String REQUEST_QRCODE_FAMILY_INFO() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/invited/scanqrcode";
        }

        public static final String FAMILY_JOIN_BY_QR() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/invited/joinfamily";
        }

        public static final String JOIN_PUBLIC_FAMILY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/joinpublicfamily";
        }

        public static final String FAMILY_NUM_QUERY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/getfamilymember";
        }

        public static final String FAMILY_NUM_DELETE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/delfamilymember";
        }

        public static final String GET_CONFIG_DEVICE_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/dev/getconfigdev";
        }

        public static final String GET_FAMILY_VERSION_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/user/getfamilyid";
        }

        public static final String GET_FAMILY_VERSION() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/getversion";
        }

        public static final String GET_FAMILY_LIST_DETAL_INFO() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/getallinfo";
        }

        public static final String GET_CATEGORY_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/system/getchilddir";
        }

        public static final String ADD_MODULE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/add";
        }

        public static final String MODIFY_MODULE_ORDER() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modifyorder";
        }

        public static final String ADD_MODULE_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/addlist";
        }

        public static final String EDIT_MODULE_FLAG() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modifyflag";
        }

        public static final String EDIT_MODULE_INFO_AND_ROOM() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modifyandmovemodule";
        }

        public static final String EDIT_MODULE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modify";
        }

        public static final String EDIT_MODULE_NEW() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modifybasicinfo";
        }

        public static final String DELETE_MODULE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/del";
        }

        public static final String DELETE_DEV() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/dev/deldev";
        }

        public static final String MODFIY_MODULE_ROOM() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/movemodule";
        }

        public static final String SET_PEAK_INFO() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/electricinfo/config";
        }

        public static final String QUERY_PEAK_INFO() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/electricinfo/query";
        }

        public static final String DELETE_FAMILY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/del";
        }

        public static final String QUIT_FAMILY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/member/quitfamily";
        }

        public static final String DEV_ROOM_EDIT() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/dev/movedev";
        }

        public static final String ADD_PIC() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/system/addpic";
        }

        public static final String MODULE_NAME_EDIT() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modifyname";
        }

        public static final String MODULE_RELATION_EDIT() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/module/modifyrelation";
        }

        public static final String SET_USER_PRIVATE_DAT() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/upsertprivatedata";
        }

        public static final String GET_USER_PRIVATE_DAT() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/family/getprivatedata";
        }

        public static final String LINKAGE_ADD() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/linkage/add";
        }

        public static final String LINKAGE_DELETE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/linkage/delete";
        }

        public static final String LINKAGE_QUERY() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/linkage/query";
        }

        public static final String LINKAGE_UPDATE() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/linkage/update";
        }

        public static final String DELETE_FAMILY_DEVICE_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/dev/dellist";
        }

        public static final String AUTH_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/authmanager/auth/list";
        }

        public static final String GET_DEV_LIST_BY_AUTH() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/authmanager/auth/devlist/query";
        }

        public static final String UPDATE_DEV_LIST_BY_AUTH() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/authmanager/auth/devlist/update";
        }

        public static final String GET_AUTHORIZED_DEV_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/authmanager/dev/list";
        }

        public static final String GET_DEV_AUTH_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/authmanager/dev/authlist/query";
        }

        public static final String UPDATE_DEV_AUTH_LIST() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/authmanager/dev/authlist/update";
        }

        public static final String GET_SCENE_TYPE_ADD() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/moduleclassify/add";
        }

        public static final String GET_SCENE_TYPE_DEL() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/moduleclassify/del";
        }

        public static final String GET_SCENE_TYPE_MOD() {
            return BLApiUrls.BASE_FAMILY_URL + "/ec4/v1/moduleclassify/modify";
        }
    }

    public static class IrdaAPI {
        public static String CLOUD_BRAND_LIST() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/app/getbrand";
        }

        public static String CLOUD_BRAND_CLASS_LIST() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/app/geturlbybrandversion?mtag=app";
        }

        public static String CLOUD_AC_RECOGNIZE_LIST() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/cloudac/recognizeirdata?mtag=app";
        }

        public static String CLOUD_PROVINCES_LIST() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/app/getsubarea";
        }

        public static String CLOUD_PROVIDERS_LIST() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/stb/getprovider";
        }

        public static String CLOUD_PROVINCES_CODE_LIST() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/stb/geturlbyarea";
        }

        public static String CLOUD_AREA_BY_ID() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/app/getareainfobyid";
        }

        public static String CLOUD_PROVIDER_BY_ID() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/stb/getproviderinfobyid";
        }

        public static String CLOUD_CHANNEL_LIST_BY_ID() {
            return BLApiUrls.CLOUD_NEW_BASE + "/publicircode/v2/stb/getchannel";
        }
    }
}

The % in the URL is the Licence ID captured by Mitmproxy… API call with token results to:

{"error":-2002,"status":-2002,"msg":"数据错误"}

In other words:

Screen Shot 2021-11-29 at 3.58.57 pm