Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eweLink has made some changes last week. API needs updating #21

Closed
primalnow opened this issue Oct 16, 2019 · 46 comments
Closed

eweLink has made some changes last week. API needs updating #21

primalnow opened this issue Oct 16, 2019 · 46 comments
Labels
enhancement New feature or request

Comments

@primalnow
Copy link

As of last week, ewelink made some changes in how it sends data. I don't know of the changes, but I do know that there were some changes. A similar problem was faced with the SONOFF API for homeassistant.

I would really appreciate if you can update this API to reflect the changes.

As for now,

The login with email/password - OK.
Login with accesstoken/apikiey - FAIL
Listening to the websocket (https://ewelink-api.now.sh/docs/available-methods/openwebsocket) - OK
getDevices - FAIL
ToggleDevice - FAIL

I haven't tested rest of the commands, since I just started using the API today.

Would really appreciate your attention. Thanks.

-Faisal Qureshi

Some error logs:

all devices { error: 400, msg: 'params incomplete' }
a device { code: 400, error: 'params is incomplete' }

Trying to use the accesstoken:
login details -> { error: 400, msg: 'Authentication error' }
devices { error: 401, msg: 'Authentication error' }

@skydiver
Copy link
Owner

Hello @primalnow

All tests has passed.

Did a few manual tests and get expected results on:

  • getDevices
  • setDevicePowerState

Where did you see these changes? Any link to investigate?

Thanks.-

@primalnow
Copy link
Author

primalnow commented Oct 17, 2019

Changes were discussed here: peterbuga/HASS-sonoff-ewelink#162

My server is 'as'

If I don't do the "(async () => ", I get "SyntaxError: await is only valid in async function"

Websocket is working fine. But other commands give a '400'

`
const ewelink = require('ewelink-api');
(async () => {
const connection = new ewelink({
email: 'xxx@gmail.com',
password: 'xxx',
region: 'as'
});

console.log('connection', connection);

const login = await connection.login();

const accessToken = login.at;
const apiKey = login.user.apikey

console.log('login details -> ' , login);

const socket = await connection.openWebSocket(async data => {
    console.log('data <-' , data)
});

const devices = await connection.getDevices();
console.log('all devices' , devices);

const device = await connection.getDevice('xxx');
console.log('a device' , device);

const status = await connection.toggleDevice('xxx');
console.log('bay on' , status);

})();`

Output:

connection eWeLink { region: 'as', email: 'xxx@gmail.com', password: 'xxx', at: undefined, apiKey: undefined } login details -> { at: 'xxx', rt: 'xxx', user: { _id: 'xxx', email: 'xxx@gmail.com', password: 'xxx', appId: 'xxx', createdAt: '2019-05-09T17:23:22.679Z', apikey: 'xxx', __v: 0, lang: 'en', online: true, onlineTime: '2019-10-17T04:17:05.120Z', appInfos: [ [Object], [Object] ], ip: '182.179.187.115', location: '', offlineTime: '2019-10-17T04:16:50.552Z', userStatus: '2', bindInfos: { gaction: [Array] } }, region: 'as' } data <- { error: 0, apikey: 'xxxx', config: { hb: 1, hbInterval: 145 }, sequence: 'xxx' } all devices { error: 400, msg: 'params incomplete' } a device { code: 400, error: 'params is incomplete' } data <- { action: 'sysmsg', deviceid: '1000xxx apikey: 'xxx5', ts: 0, params: { online: false } } bay on { error: 'params is incomplete', msg: 'Device does not exist' } data <- { action: 'sysmsg', deviceid: '1000xxx', apikey: 'xxx02c0e8', ts: 0, params: { online: true } }

@skydiver
Copy link
Owner

Hey @primalnow

I can't reproduce your error, everything works fine to me.

Which device are you using?
From the link you posted, i see there are errors with a Sonoff POW R2.

I've tested with this device and i was able to turn on/off, get power consumption.

Thanks.-

@primalnow
Copy link
Author

primalnow commented Oct 19, 2019 via email

@narus2
Copy link

narus2 commented Oct 30, 2019

Good afternoon.
I also see a mistake about using a token

const connection = new ewelink ({
     at: '<valid access token>',
   });

Using Email and password - works
valid access token - get with

const auth = connection.login ();
  console.log ('access token:', auth.at);

@murtaza9000
Copy link

murtaza9000 commented Oct 30, 2019

yes I also saw the issues. what I am able to do is to getdevices. You can do it by updating the following parameter under node-modules/ewelink-api/mixins/devices/getDevicesMixin.js ,

`const getDevicesMixin = {
async getDevices() {
return this.makeRequest({
uri: '/user/device',
qs: { lang: 'en', getTags: 1,

apiKey : '<insert apikey can be find by login',
getTag : '1',
version : '6',
ts : '' + Math.floor(new Date().getTime() / 1000),

// nounce : '' + nonce(),
appid : 'oeVkj2lYFGnJu5XUtWisfW4utiN4u9Mq', //this is fixed
imei : 'xxxxxxxxxxxx',
os : 'android',
model : '',
romVersion : '',
appVersion : ''

},
});

},
};

module.exports=getDevicesMixin;
`

@sanketmehta7
Copy link

sanketmehta7 commented Nov 2, 2019

Thanks @murtaza9000 that worked for me, to getDevices.
Below replacement will work. (better formatted)

async getDevices() {
    return this.makeRequest({
        uri: '/user/device',
        qs: {
            lang: 'en',
            getTags: 1,
            version: '6',
            ts: '' + Math.floor(new Date().getTime() / 1000),
            appid: 'oeVkj2lYFGnJu5XUtWisfW4utiN4u9Mq',
            imei: 'xxxxxxxxxxxx',
            os: 'android',
            model: '',
            romVersion: '',
            appVersion: ''
        }
    });
}

@skydiver
Copy link
Owner

skydiver commented Nov 2, 2019

Hello @murtaza9000 and @sanketmehta7

Do you wanna make a PR so we can add these changes?

Thanks.-

@primalnow
Copy link
Author

Thanks for the update. But the error persists. At least for the CN/AS server.

@sanketmehta7
Copy link

sanketmehta7 commented Nov 4, 2019

I can make PR...also issue with other apis still remains (having added same param to them), I couldn't get getDevice & toggleState (ws api) working...just able to get above devices list only. Any one tried mix of param with success can help with those remaining api params...Also any body know how to reverse proxy api calls from the app itself, to debug req/res data.

I tried Charles proxy but not able to decode ssl url data.

@skydiver
Copy link
Owner

skydiver commented Nov 5, 2019

Hey @sanketmehta7

This is strange because i cannot reproduce any of those errors.

Tests are passing successfully.

Can you try to run npm run test and let me know which ones are failing?

Also, which region are you using?

@murtaza9000
Copy link

I can make PR...also issue with other apis still remains (having added same param to them), I couldn't get getDevice & toggleState (ws api) working...just able to get above devices list only. Any one tried mix of param with success can help with those remaining api params...Also any body know how to reverse proxy api calls from the app itself, to debug req/res data.

I tried Charles proxy but not able to decode ssl url data.

Actually true, I was only able to make it work with getdevices. Not with other. Yes @skydiver you may do PR at least for this. But any luck for other apis @sanketmehta7 . And are you have session out issue from the application "ewelink"?

@skydiver
Copy link
Owner

skydiver commented Nov 7, 2019

Guys, i've created a new branch issue-21-test

There is a new method, getDeviceAlt.

This can be tested on this way:

  1. clone repo and switch branch
  2. create test.js file on repo root
  3. run this code:
const ewelink = require('./main');

(async () => {

  const connection = new ewelink({
    email: 'your mail',
    password: 'your password',
  });

  await connection.login();

  const device = await connection.getDeviceAlt('your device id');
  console.log(device);

})();

setDevicePowerState request was also updated, let me know if works too

Thanks

@murtaza9000
Copy link

Hi @skydiver ,

So, getDeviceAlt is working fine but setDevicePowerState is giving me the error:

const status = await connection.setDevicePowerState('device id', 'on');
{ error: 'params is incomplete', msg: 'Device does not exist' }

Once I update setDevicePowerStateMixin.js

line 17 : to const device = await this.getDeviceAlt(deviceId);

It fixed.

@skydiver
Copy link
Owner

skydiver commented Nov 7, 2019

Hey @murtaza9000

Thanks for the feedback.

I've updated setDevicePowerStateMixin.js to use the new method.

If everything works fine, we can replace the original getDevice and fix the issue.

@quan-th
Copy link

quan-th commented Nov 7, 2019

Hi @skydiver,
I'm new, I'm trying to use getDevicePowerUsage but it seems failed too. I think the reasons here:
https://github.com/skydiver/ewelink-api/blob/master/mixins/powerUsage/getDevicePowerUsageMixin.js#L14

https://github.com/skydiver/ewelink-api/blob/master/mixins/powerUsage/getDeviceRawPowerUsageMixin.js#L14

Can you check this?

By the way, do you have any other docs about ewelink-api? im reading
https://ewelink-api.now.sh/docs/available-methods

Thanks

@murtaza9000
Copy link

Hi @skydiver . Its fine working perfect.
Thanks for quick fixes

@skydiver
Copy link
Owner

skydiver commented Nov 8, 2019

Hello everyone:

This PR tries to solve errors reported on this thread: https://github.com/skydiver/ewelink-api/pull/26/files

getDevice was replaced with the new method (getDeviceAlt was removed).

Will be great if we can get someone else who can test and confirm is working.

Thanks.-

@ttz642
Copy link
Contributor

ttz642 commented Nov 8, 2019

@skydiver
= = = S O L V E D for Release 1.8.0 = = =

I'm using the current version without any of the patches...

I had the same problem trying to use ewelink-api with alternative access method using apikey, I noticed the response returned the region as the us, I'm in the EU.

with code:
const anotherNewConnection = new ewelink({ at: login.at, apiKey: login.user.apikey});
console.log("anotherNewConnection :: " + JSON.stringify(anotherNewConnection));
response = await anotherNewConnection.getDevices();
console.log("Devices :: " + JSON.stringify(response,null,4));

I get:

anotherNewConnection :: {"region":"us","at":"16c482b01afaf36e237c7329e76c7356e45d69f4","apiKey":"45b2b2ba-037e-4819-8ee5-09553a6f2119"}
Device :: {"error":401,"msg":"Authentication error"}

If I add the region to the new connection, ie:
const anotherNewConnection = new ewelink({ at: login.at, apiKey: login.user.apikey, region: login.region});

I get:
anotherNewConnection ::
{"region":"eu","at":"a128b75f15eabcf8315ca82c5a33b6ab6c88d975","apiKey":"45b2b2ba-037e-4819-8ee5-09553a6f2119"}
Devices :: [
{
"_id": "5dc29f913e1c64655f4f9890",
"name": "L1",
"type": "10",
. . .
. . .

And everything works OK !
Tried getDevice & getDevices !

--
Steve

@primalnow
Copy link
Author

Problem persists:
Used the code as given on https://ewelink-api.now.sh/docs/demos/node
My server is CN.
Have a few console.log in place to see the output. This is what I get

connection eWeLink {
region: 'cn',
email: 'xxxx',
password: 'xxx',
at: undefined,
apiKey: undefined
}

devices { error: 400, msg: 'params incomplete' }
device { code: 400, error: 'params is incomplete' }

@ttz642
Copy link
Contributor

ttz642 commented Nov 9, 2019

Problem persists:
Used the code as given on https://ewelink-api.now.sh/docs/demos/node
My server is CN.
Have a few console.log in place to see the output. This is what I get

connection eWeLink {
region: 'cn',
email: 'xxxx',
password: 'xxx',
at: undefined,
apiKey: undefined
}

devices { error: 400, msg: 'params incomplete' }
device { code: 400, error: 'params is incomplete' }

If your using the login method you don't need the at or apiKey.

See comment below on use of region during login. I'd actually keep region for all connections, seems to influence which server is used and consequently access & speed.

@skydiver
Copy link
Owner

skydiver commented Nov 9, 2019

Hey @primalnow

Does the issue-21-test branch solves your problems?

@ttz642
Copy link
Contributor

ttz642 commented Nov 9, 2019

Hey @primalnow

Does the issue-21-test branch solves your problems?

I didn't need to use the branch, just used the stock 1.8.0

@primalnow
Copy link
Author

Input:

`const ewelink = require('ewelink-api');

(async () => {

const connection = new ewelink({
email: 'xxxxxxx',
password: 'xxxxxxx',
region: 'cn'
});

console.log('connection' , connection);

/* get all devices */
const devices = await connection.getDevices();
console.log('devices' , devices)

/* get specific devide info */
const device = await connection.getDevice('100078c852');
console.log('device' , device);

/* toggle device */
await connection.toggleDevice('10007797c8');

})();
`

Output:
`

MacBook-Pro:ewelink-node faisal$ node test.js
connection eWeLink {
region: 'cn',
email: 'xxxxxxxx',
password: 'xxxxxxxxx',
at: undefined,
apiKey: undefined
}
devices { error: 400, msg: 'params incomplete' }
device { code: 400, error: 'params is incomplete' }
MacBook-Pro:ewelink-node faisal$
`

`

@skydiver
Copy link
Owner

Everyone:

The region parameter is required for everyone who is not using US servers, so, this is how you need to initialize the class:

const connection = new ewelink({
  email: 'my@email.com',
  password: 'password',
  region: 'cn'
});
// possible regions: us, eu, cn, as
const connection = new ewelink({
  at: 'access token',
  region: 'us',
});

⚠️ this is important when you're using access token as authentication method ⚠️


More context: when using email and password with the wrong region (default is us), the login request fails, and performs a second login request with the right region.

So, not using region parameter is possible with email/password but not recommended since adds a few extra seconds to login because takes 2 api requests.

When using access token without region will fail with an error 400/401, so, in this scenario you MUST provide your region.

I believe the changes on issue-21-test branch are not needed, but will left open a few more days to get some input if using region parameter works for everyone.

@primalnow
Copy link
Author

MacBook-Pro:ewelink-node faisal$ npm list
/Volumes/http/ewelink-node
└─┬ ewelink-api@1.8.1
├── delay@4.3.0
├── nonce@1.0.4
├─┬ random@2.1.1

Input:

const ewelink = require('ewelink-api');

(async () => {

const connection = new ewelink({
email: 'xxxxxxxx',
password: 'xxxxxxx',
region: 'cn'
});

console.log('connection' , connection);

/* get all devices */
const devices = await connection.getDevices();
console.log('devices' , devices);

/* get specific devide info */
const device = await connection.getDevice('');
console.log('device' , device);

/* toggle device */
await connection.toggleDevice('10006ac2c4');

})();

Output

MacBook-Pro:ewelink-node faisal$ node test.js
connection eWeLink {
region: 'cn',
email: 'xxxxxxx',
password: 'xxxxxx',
at: undefined,
apiKey: undefined
}
devices { error: 400, msg: 'params incomplete' }
device { code: 400, error: 'params is incomplete' }
MacBook-Pro:ewelink-node faisal$

@primalnow
Copy link
Author

Serverless - Copied from https://ewelink-api.now.sh/docs/demos/serverless

INPUT

const connection = new ewelink({
email: 'XXXXXXXX',
password: 'XXXXXXXX',
region: 'cn'
});

const login = await connection.login();

const accessToken = login.at;
const apiKey = login.user.apikey
const region = login.region;

const newConnection = new ewelink({
at: accessToken
region: region,
});
const devices = await newConnection.getDevices();
console.log(devices);

const thirdConnection = new ewelink({
at: accessToken
region: region,
});
const device = await thirdConnection.getDevice('10006ac2c4');
console.log(device);

const anotherNewConnection = new ewelink({
at: accessToken
region: region,
});
await anotherNewConnection.toggleDevice('10006ac2c4');

OUTPUT

MacBook-Pro:ewelink-node faisal$ node test-serverless.js
/Volumes/SD256/google_drive_20191001/http/ewelink-node/test-serverless.js:7
const login = await connection.login();
^^^^^

SyntaxError: await is only valid in async function
at Module._compile (internal/modules/cjs/loader.js:881:18)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:962:10)
at Module.load (internal/modules/cjs/loader.js:798:32)
at Function.Module._load (internal/modules/cjs/loader.js:711:12)
at Function.Module.runMain (internal/modules/cjs/loader.js:1014:10)
at internal/main/run_main_module.js:17:11
MacBook-Pro:ewelink-node faisal$

@primalnow
Copy link
Author

NODE SCRIPT - copied from https://ewelink-api.now.sh/docs/demos/node

INPUT

const ewelink = require('ewelink-api');

(async () => {

const connection = new ewelink({
email: 'XXXXXXX',
password: 'XXXXXXX',
region: 'cn'
});

const login = await connection.login();

console.log('connection' , connection);

/* get all devices */
const devices = await connection.getDevices();
console.log('devices' , devices);

/* get specific devide info */
const device = await connection.getDevice('');
console.log('device' , device);

/* toggle device */
await connection.toggleDevice('10006ac2c4');

})();

OUTPUT

MacBook-Pro:ewelink-node faisal$ node test.js
connection {
at: 'xxxxxxxxxx',
rt: 'xxxxxxxxxxx',
user: {
_id: 'xxxxxxxxx',
email: 'xxxxxxx',
password: 'xxxxxxxx',
appId: 'xxxxxxxx',
createdAt: '2019-05-09T17:23:22.679Z',
apikey: 'xxxxxxxxxxx',
__v: 0,
lang: 'en',
online: true,
onlineTime: '2019-11-11T12:13:51.533Z',
appInfos: [ [Object], [Object] ],
ip: '119.160.103.253',
location: '',
offlineTime: '2019-11-11T07:11:06.163Z',
userStatus: '2',
bindInfos: { gaction: [Array] }
},
region: 'as'
} eWeLink {
region: 'as',
email: 'fxxxxxx',
password: 'xxxxxxx',
at: 'xxxxxxxx',
apiKey: 'xxxxxxxxxxx'
}
devices { error: 400, msg: 'params incomplete' }
device { code: 400, error: 'params is incomplete' }
MacBook-Pro:ewelink-node faisal$

@ttz642
Copy link
Contributor

ttz642 commented Nov 11, 2019

I'll have a proper look tomorrow, but a few observations inline bold and I've deleted a lot of code and replaced with . . .

NODE SCRIPT - copied from https://ewelink-api.now.sh/docs/demos/node
. . .
const connection = new ewelink({
. . .
region: 'cn'

Should you use "as" as the region as that is reported later on suggesting that's where you were registered.

});
. . .
const device = await connection.getDevice('');

connection.getDevice(''); MUST include a device id, eg 0123456789

console.log('device' , device);
. . .

OUTPUT

. . .
},
region: 'as'

server has reported you as being in region as

} eWeLink {
. . .

@peterbuga
Copy link

fix for { code: 400, error: 'params is incomplete' } is in my code

@ttz642
Copy link
Contributor

ttz642 commented Nov 12, 2019

fix for { code: 400, error: 'params is incomplete' } is in my code

Don't think you need any fixes, Release 1.8.0 & 1.8.1 work fine provided region is correctly set and no missing code.

@peterbuga
Copy link

Don't think you need any fixes, Release 1.8.0 & 1.8.1 work fine provided region is correctly set and no missing code.

asian users keep getting bumped between cn and as regions, specifying a single region is not enough (also the fallback takes care of this making the "provided region is correctly" kinda useless or optional at best) this problem relies on another part of the code

@ferryariawan
Copy link

I'm using 1.8.1 and having the same issue (
Region: as
{ error: 400, msg: 'params incomplete' }

@ferryariawan
Copy link

In release 1.8.1, getDevicesMixin.js only have 2 params (lang and getTags)

@skydiver
Copy link
Owner

In release 1.8.1, getDevicesMixin.js only have 2 params (lang and getTags)

@ferryariawan 1.8.1 just includes a new method called getRegion, which i believe wrong/missing region is the cause of a lot of errors found on this thread

@ferryariawan
Copy link

qs: {
lang: 'en',
getTags: 1,
version: '6',
ts: '' + Math.floor(new Date().getTime() / 1000),
appid: 'oeVkj2lYFGnJu5XUtWisfW4utiN4u9Mq',
imei: 'xxxxxxxxxxxx',
os: 'android',
model: '',
romVersion: '',
appVersion: ''
}

I get the getDevices to work after adding this to getDevicesMixin

@skydiver
Copy link
Owner

@ferryariawan just released 1.8.2 who includes these changes

@primalnow
Copy link
Author

primalnow commented Nov 12, 2019

@peterbuga Thanks for jumping in :)

@skydiver Thanks for all your hard work. getDevices is working perfectly now.

However, nothing else is.

`
region { email: 'xxxxx', region: 'as' }

getDevicePowerState { error: 'params is incomplete', msg: 'Device does not exist' }

getDeviceCurrentTH { code: 400, error: 'params is incomplete' }

getDeviceChannelCount { error: 'params is incomplete', msg: 'Device does not exist' }

getDevice { code: 400, error: 'params is incomplete' }

toggleDevice { error: 'params is incomplete', msg: 'Device does not exist' }

`

@primalnow
Copy link
Author

@skydiver if you like I can share a few devices with you. Not sure if that would work. If you're willing to do it with me in real time, I can give you access to my ewelink account.

@ttz642
Copy link
Contributor

ttz642 commented Nov 12, 2019

After you have have done the Class Instantiation the connection has the region associated with the account, I think, can somebody having a problem with region try this?

  const connection = new ewelink({
    email: '<your ewelink email>',
    password: '<your ewelink password>',
    region: '<your ewelink region>',
  });

console.log("region / server from Class Instantiation ",connection.region);

should now contain the region required by subsequent methods.

@primalnow
Copy link
Author

@ttz642 The latest update has fixed getDevices. It's the rest of the functions that are still not working.

@peterbuga
Copy link

@ttz642 The latest update has fixed getDevices. It's the rest of the functions that are still not working.

when adding the new params to the /api/user/device due to constant inconsistencies in itead api the devices are returned differently at times, might be worth to check this

@primalnow
Copy link
Author

@peterbuga I tried with the exact device ID, returned by the getDevices command. I did not rely on the ID's in the app :-)

You know I'm thorough. :)

@skydiver
Copy link
Owner

skydiver commented Nov 13, 2019

when adding the new params to the /api/user/device due to constant inconsistencies in itead api the devices are returned differently at times, might be worth to check this

hey @peterbuga i believe we already did this change on PR #26 on this file

Didn't merged yet because i'm not sure if it was really necessary or just by always using region was enough

@primalnow
Copy link
Author

@skydiver tested with the getdevicemixin.js as given in #26, and everything works flawlessly. Kindly merge.

Thanks for all the hard work. Much appreciated.

skydiver added a commit that referenced this issue Nov 16, 2019
@skydiver skydiver mentioned this issue Nov 16, 2019
@skydiver skydiver reopened this Nov 16, 2019
@skydiver skydiver added the enhancement New feature or request label Nov 16, 2019
@skydiver
Copy link
Owner

I've merged issue-21-test branch.

I'm gonna wait after some feedback before relesing 1.9.0 to npm.

Hope this fixes everyone problems 🤞 ... and remember to keep using region when initializing the class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

9 participants