dvcrn / homebridge-sharp-cocoro

Homebridge plugin for SHARP Cocoro appliances
6 stars 1 forks source link

Unexpected end of JSON input error in homebridge terminal after calling boxInfo #1

Closed shahrilamrias closed 3 years ago

shahrilamrias commented 3 years ago

Describe Your Problem: After installing plugin, I initiated homebridge restart and this plugin specific errors are thrown at the end of the terminal

Logs:

...truncated...

[10/08/2021, 11:42:19] Loaded plugin: homebridge-sharp-cocoro@1.1.2
[10/08/2021, 11:42:19] Registering platform 'homebridge-sharp-cocoro.SharpCocoroPlatform'
[10/08/2021, 11:42:19] ---
[10/08/2021, 11:42:19] Loading 4 platforms...
[10/08/2021, 11:42:19] [Config] Initializing config platform...
[10/08/2021, 11:42:19] [Config] Running in Service Mode
[10/08/2021, 11:42:19] [miot] Initializing miot platform...
[10/08/2021, 11:42:19] [SamsungTizen] Initializing SamsungTizen platform...
[10/08/2021, 11:42:19] [SharpCocoroPlatform] Initializing SharpCocoroPlatform platform...
{
  appSecret: 'SECRET=',
  appKey: 'SECRET',
  platform: 'SharpCocoroPlatform'
}
[10/08/2021, 11:42:19] [miot] Initializing devices

...truncated...

[10/08/2021, 11:42:21] [miot] [Mi Air Purifier 3H] Filter life level: 83%.
[10/08/2021, 11:42:21] [miot] [Mi Air Purifier 3H] Filter used time: 574 hours.
(node:11580) UnhandledPromiseRejectionWarning: FetchError: invalid json response body at https://hms.cloudlabs.sharp.co.jp/hems/pfApi/ta/setting/boxInfo/?appSecret=SECRET=&mode=other reason: Unexpected end of JSON input
    at /usr/local/lib/node_modules/homebridge-sharp-cocoro/node_modules/node-fetch/lib/index.js:272:32
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:11580) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:11580) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

boxInfo response Here's what I got in response when I fired up the api for reference.

{"box":[{"boxId":"https://db.cloudlabs.sharp.co.jp/clpf/key/SECRET","maxFlag":false,"pairingFlag":true,"pairedTerminalNum":1,"timezone":"Asia/Kuala_Lumpur","terminalAppInfo":[{"terminalAppId":"https://db.cloudlabs.sharp.co.jp/clpf/key/SECRET","appName":"spremote_i_asean:1:1.4.2","userNumber":0}],"echonetData":[{"maker":"SHARP","series":null,"model":"AH-XP10WHD","serialNumber":null,"echonetNode":"SECRET","echonetObject":"SECRET","echonetAttr":"LONG_SECRET","echonetProperty":"VERY_LONG_SECRET","deviceId":0,"simulPerfModeFlag":false,"propertyUpdatedAt":"2021-08-10T12:35:43","labelData":{"id":0,"place":"GLOBAL_ROOM_E","name":"Bedroom Aircond","deviceType":"AIR_CON","zipCd":"48000","yomi":"","lSubInfo":null}}]}]}

Plugin Config:

    "platforms": [        
        {
            "appSecret": "SECRET=",
            "appKey": "SECRET",
            "platform": "SharpCocoroPlatform"
        }
    ]

Environment:

shahrilamrias commented 3 years ago

I understand the plugin is WIP but is it supposed to throw this error? I assumed device discovery would work fine but seems like it didn't

dvcrn commented 3 years ago

What kind of device is this?

And the boxInfo API returned to you just fine when you manually queried it?

Yeah for discovery it's pulling all devices off the API and then trying to create accessories with it. The JSON error you see usually means that authentication or something similar failed and the API just returned nothing.

Could you try to use the SDK directly and see if you can get that working? https://github.com/dvcrn/cocoro-sdk

Your input is very helpful in getting this to work with more aircon models and make the user experience better

dvcrn commented 3 years ago

How did you extract the secret? It's important to use the one from the login call, and not a secret from a different method

shahrilamrias commented 3 years ago

What kind of device is this?

This is the ahxp10whd 1HP air conditioner paired with the SHARP Air App. Unfortunately, I can only find the device on my country sharp page.

And the boxInfo API returned to you just fine when you manually queried it?

Could you try to use the SDK directly and see if you can get that working? https://github.com/dvcrn/cocoro-sdk

How did you extract the secret? It's important to use the one from the login call, and not a secret from a different method

Yes, I queried it in postman following the request in proxyman. From what I can see, my app is only logging in against this single endpoint https://asean-hms.cloudlabs.sharp.co.jp/hems/pfApi/ta/setting/login/?appSecret=SECRET&serviceName=auth-pf

I visited the SDK repo just now and noticed from your documentation that my Sharp app is actually authenticating using auth-pf rather than iClub as the serviceName parameter value.

As for the subdomain difference, it seems that I can authenticate against both asean-hms.cloudlabs.sharp.co.jp and hms.cloudlabs.sharp.co.jp respectively without issue using auth-pf but it returns 401 unauthorized with iClub

I see that your SDK is authenticating with the iClub as serviceName which would explain why I fail to authenticate in homebridge.

I reinstalled the app and double checked proxyman but the only login call I can see is the one I quoted above. When logging in normally through the app I can actually see it opens a webview for iclub.sharp.co.jp to show the login form. I have no idea why my account is using a different serviceName. Maybe it's a region thing?

dvcrn commented 3 years ago

If you replace iClub with auth-pf in the sdk, does the rest work for you as is? Try to query the devices manually with it after replacing and see if you get any errors (https://github.com/dvcrn/cocoro-sdk/blob/master/src/cocoro.ts#L57)

Change that line and do a quick test script like

    const cocoro = new Cocoro(appSecret, appKey);
    console.log(await cocoro.login());
    const devices = await cocoro.queryDevices();
    const device = devices[0];
    console.log(device);

(then ts-node foo.ts)

From the sounds of it, it could just be the session authentication is different but the rest of the API should hopefully be the same (taken from your BoxInfo response that's identical to mine).

(Best would be to implement full authentication into the sdk but I wasn't able to dump the login flow with proxyman because of the pinned certificate)

shahrilamrias commented 3 years ago

It works!

Here's a dump of the console log in gist. Hopefully they're the same as what your SDK expects.

dvcrn commented 3 years ago

Looks good! Then let's add a config variable for that field and see if that makes it work for you

dvcrn commented 3 years ago

I've pushed 1.2.0 with a new serviceName config field, can you give it a go?

shahrilamrias commented 3 years ago

Thank you so much. The aircond was discovered and automatically added to homebridge. I was able to turn it on/off and switch the modes.

Quick question - what’s the fan setting for though? Some other device?

dvcrn commented 3 years ago

Great to hear!

For the fan setting - On my aircon you can set different strength levels. The default Thermostat service that we use for aircons in HomeKit doesn't have this kind of characteristic because Thermostats just control temperature and not wind speed. A real 'aircon' doesn't exist in homekit yet so to get windspeed setting working I implemented it as an additional fan service that's synced with the thermostat.

If yours doesn't have a windspeed setting maybe we can either auto-detect that through the device properties and disable it, or add another config element to turn it off manually maybe?

shahrilamrias commented 3 years ago

Oh! I looked at the remote and turns out I actually do have the fan setting option. It’s just that I always set to auto so I forgot I had them 😅

Thanks a bunch for writing the plugin and sdk. Life without the dreaded sharp app is so much better now thanks to you.