myq-api
myq-api copied to clipboard
V6 Support
Noticed errors being thrown from my implementation of this package. After a bit of looking, it appears that Chamberlain has deprecated V5 of their API, and has moved to V6. (Discussion here.)
It looks like someone on that side has been able to reverse engineer it, but I'm not sure how to grab the logs myself to get an implementation going. Might be possible to get into the Discord server and ask them for the info.
Not sure how big a change this is. Ideally, the public facing API for this package remains as-is.
Happy to help if I have time.
Acknowledged, thanks for reporting! This does align with the cron tests that started failing as of yesterday.
I might try to see if I can MITM to see what the new requests look like. I will join the Discord as well to keep up with progress on the Homebridge end.
Thanks a lot. Stupid that they just can change the api without compatibility to the last one...
I'll add my thanks - yes, would love to see this work again! Missing the functionality here. Shout if I can help in any way.
A short-term fix with the V5 API has landed (see #35). I did some MITM/research with the V6 API that I didn't get a chance to publish yet, but hopefully I can get around to it relatively soon.
Does the app work for you using mitmproxy? I was trying to capture some traces (and yes, noticed the app is now using V6 per the hombridge implementation) but when using mitmproxy the app says it can't find the server. I can see the initial OAuth traffic but that's it.
BTW, thanks for doing this!
I'm getting consistent 400 errors today, chatter on other projects seems to indicate something changed with the API to break it. The Homebridge plugin ported to v6 Oauth and seems to be still working. Any current plans to update to v6 or otherwise fix?
Receiving the same 400 issue today as well. Coincidently when I got a new garage motor, thought it was because of that 😅
Yes, I'm getting the same error:
Error received:
{ MyQError: Unidentified error returned from service.
at Function.handleServiceError (/srv/dev/cfg/openhab2/scripts/node_modules/myq-api/src/ErrorHandler.js:49:13)
at MyQ._executeServiceRequest (/srv/dev/cfg/openhab2/scripts/node_modules/myq-api/src/MyQ.js:732:27)
at process._tickCallback (internal/process/next_tick.js:68:7)
name: 'MyQError',
code: 'ERR_MYQ_INVALID_SERVICE_RESPONSE',
_serviceError:
{ Error: Request failed with status code 400
at createError (/srv/dev/cfg/openhab2/scripts/node_modules/axios/lib/core/createError.js:16:15)
at settle (/srv/dev/cfg/openhab2/scripts/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/srv/dev/cfg/openhab2/scripts/node_modules/axios/lib/adapters/http.js:244:11)
at IncomingMessage.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1145:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
We need to prioritize this now that the v5 API is turned down. I'll actively start working on this, but it won't be an overnight fix by any means.
Let me know if I can be of assistance :)
I haven't looked at what @koush did but have been updating some home automation code I have that was based on what I learned from this project. I now have it mostly working. I figured most things out by looking at the HomeBridge code along with some detective work watching network traffic. The MyQ server is very finicky and wants headers and such a certain way. Anyway, if it's helpful, the general gist of V6 is the switch to the Oauth2/PKCE flow and minor changes to the regular api. Here's some more details:
For auth:
Instead of the old security token you use an Access Code generated by the OAuth flow. It's passed along in the api with an Authorization header. [Yes, it gives you an "access_token" in a JSON reply but you put it in an Authorization header].
To do this, start at https://partner-identity.myq-cloud.com/connect/authorize with a bunch of query params (see Homebridge code) and the PKCE challenge. This will return with several redirects. Keep following them until the server returns with a 200 returns code. With this return you need to parse the html and find a __RequestVerificationToken. With that token, redo the last query as a POST and in the body of the POST put url encoded email, password and token.
This will return a page with one more redirect... don't follow the redirect! Instead, pull out the "code" and "scope" it returns and turn around and use them in a POST to https://partner-identity.myq-cloud.com/connect/token (you will also send along the PKCE verifier now), which will return an actual access code.
The reply will have an "access_token" and "token_type" which are then used in all the api commands. Basically, create a header as "Authorization: <token_type> <access_token>" which replaces prior use of the Security Token. You can also save away the refresh_token to get new access tokens when you need them without logging back in. [I have not tried that].
Now that you've got your access token everything is very similar to what it was before. First, you need to get the account ID. This is a little different. Query https://accounts.myq-cloud.com/api/v6.0/accounts and a list of accounts will be returned. Not sure why there can be more than one. Anyway, this will give you and Account ID which you use in the api as before.
To get the device list, use https://devices.myq-cloud.com/api/v5.2/Accounts/<accountID>/Devices. This list will be the same as before.
To then control a device use https://account-devices-gdo.myq-cloud.com/api/v5.2/Accounts/<accountID>/door_openers/
where command is "Open" or "Close" (used to be open or close). This is a PUT command as before with an empty body (be sure to set Content-Length: 0).
Oh, make sure to have cookie processing on as it is required.
You can find details of some of the search parameters in the HomeBridge code.
Hope it helps!
Here's what koush did... https://github.com/koush/myq/blob/main/src/myq-api.ts
Some useful bits from his commenting:
- Starting with v6 of the myQ API, myQ now uses OAuth 2.0 + PKCE to authenticate users and
- provide access tokens for future API calls. In order to successfully use the API, we need
- to first authenticate to the myQ API using OAuth, get the access token, and use that for
- future API calls.
- On the plus side, the myQ application identifier and HTTP user agent - previously pain
- points for the community when they get seemingly randomly changed or blacklisted - are
- no longer required.
- For those familiar with prior versions of the API, v6 does not represent a substantial
- change outside of the shift in authentication type and slightly different endpoint
- semantics. The largest non-authentication-related change relate to how commands are
- sent to the myQ API to execute actions such as opening and closing a garage door, and
- even those changes are relatively minor.
Here's what koush did... https://github.com/koush/myq/blob/main/src/myq-api.ts
The above is not my code, it's from the myq homebridge plugin. I stripped out the homebridge stuff for just the MyQ API bindings, which were updated to work with the v6 API. Hopefully it helps the authors of this project. Or anyone else that has a pressing need to control their MyQ devices, and want a relatively quick way to access them, albeit by targeting a different node library.
What's the best way to test this? Node won't run it, nor npm.
What's the best way to test this? Node won't run it, nor npm.
This is a library, not an application, so you would need to build an application to use this library's API. Examples are listed in the readme.
In case it helps anyone, I ended up switching my home automation to use the following API that works very well:
https://github.com/arraylabs/pymyq
What's the best way to test this? Node won't run it, nor npm.
This is a library, not an application, so you would need to build an application to use this library's API. Examples are listed in the readme.
Perfect. Just what I needed. Thanks!
What's the best way to test this? Node won't run it, nor npm.
This is a library, not an application, so you would need to build an application to use this library's API. Examples are listed in the readme.
It appears I need a little more handholding. How do you reference the v6 library since it's written in TypeScript?
The older myq-api is JS. I tried running tsc on it to convert it, but get errors about it being an ES module...
What's the best way to test this? Node won't run it, nor npm.
This is a library, not an application, so you would need to build an application to use this library's API. Examples are listed in the readme.
It appears I need a little more handholding. How do you reference the v6 library since it's written in TypeScript? The older myq-api is JS. I tried running tsc on it to convert it, but get errors about it being an ES module...
Sorry, it's been fixed. I had the incorrect package entry point. Should work from a normal js project.
Sorry, it's been fixed. I had the incorrect package entry point. Should work from a normal js project.
Thanks, so what is the proper way to call this?
Using const MyQ = require('myq-api');
still calls the v5 api and pointing the require directly to your myq-api.js doesn't work either.
Sorry, it's been fixed. I had the incorrect package entry point. Should work from a normal js project.
Thanks, so what is the proper way to call this? Using
const MyQ = require('myq-api');
still calls the v5 api and pointing the require directly to your myq-api.js doesn't work either.
Make sure you're on at least v1.0.9
npm install @koush/myq@latest
require('@koush/myq')
Make sure you're on at least v1.0.9
npm install @koush/myq@latest
require('@koush/myq')
No joy.
const MyQ = require('@koush/myq');
const account = new MyQ();
phuz@wazebot:~/MyQ$ node myq.js
/home/phuz/MyQ/myq.js:6
const account = new MyQ();
^
TypeError: MyQ is not a constructor
(that was me that DM'd you on discord earlier)
> require('@koush/myq')
{ myQApi: [Getter] }
that example is out of date I think.
that example is out of date I think.
yeah that old example won't work with this new API, but I can't even figure out my starting point on this. It also looks like multiple things need to happen during the authentication process. I wonder if we look at the homebridge code to see how they're using it specifically.
yeah, that's how I did it. it's not complicated.
this.account = new myQApi(console.log.bind(console), console, email, password);
await this.account.refreshDevices();
const devices: Device[] = [];
for (const device of this.account.devices) {
// do stuff
}
yeah, that's how I did it. it's not complicated.
I've tried very similar but I still get the myQApi is not a constructor
const {myQApi} = require('@koush/myq')
you're probably importing it wrong
you're probably importing it wrong
hah, yup. completely missed the deconstruction. but that opened up more errors. I hope this isn't all related to being on node v12 (which I need on this test box)
For the heck of it, I just wiped my code and pasted what you have above (with credentials) and it still blows up.
Did that actually work for you?
TypeError: this.devices is not iterable
For the heck of it, I just wiped my code and pasted what you have above (with credentials) and it still blows up. Did that actually work for you?
TypeError: this.devices is not iterable
yes.
const { myQApi } = require('@koush/myq')
async function start() {
const account = new myQApi(console.log.bind(console), console, 'username', 'password');
await account.refreshDevices();
for (const device of account.devices) {
console.log(device);
}
}
start();