vroy / python-sengled-client

A simple Python client to control Sengled [light] accessories.
MIT License
23 stars 4 forks source link

Received 'response: {'ret': '100', 'msg': 'not logined or expired' } #5

Open youzer-name opened 3 years ago

youzer-name commented 3 years ago

I received the message:

response: {'ret': '100', 'msg': 'not logined or expired' }

just after "request: device/getDeviceDetails.json, {}" when trying to run a script. (that's not a typo... it says "logined")

This occurred one day after initially starting to use your script, so it appears I was within 24 hours of my first login and the python-sengled-client was attempting to use the cached login but my login on the Sengled server had expired. I received this message twice in a row. I then deleted the contents of the pickle file and the next attempt to run the script worked.

I am not very familiar with Python although I dabble in a few other programming languages. From what I can understand of your script it doesn't attempt to detect this response and force a new login if the response is 'not logined or expired'.

For now I've changed the line in the script that sets the credentials retention from "60 60 24" to "60 60 12" in the hope that only keeping the login for 12 hours will avoid the issue. It would seem to be better though to have your script look at the response from the server when requesting the device/getDeviceDetails.json and looping back to a new login when the error is received. I could try to learn enough Python to do that but I figured it would be a fairly simple thing for the original author of the script to implement. Is this something you could add?

youzer-name commented 3 years ago

For now I've turned off the session caching as I can't understand why it keeps showing the user is not logged in when I am using the cached session.

vroy commented 3 years ago

The 24 hour session cache worked got me when I implemented this but it's possible that it changed on the server. The message logined is coming from the server and that's out of my control.

Have you had success with a shorter cache at all? If so, I would be inclined to reduce that window.

youzer-name commented 3 years ago

I was seeing really odd behavior where one command would work and within a minute or two another would return that the user wasn't logged in. I'm not sure what was going on with that. I tried a 12 hour cache and a 1 hour cache and still had issues.

I figured out enough Python to check the json return for the 'not logined' message and if that is seen, I have it perform the logon and request the device list again.

At one point I ended up in an infinite loop where i had it just logging in over and over again, but I think I figured that out this morning and have a working version. I'm going to test it for a few more days and if it doesn't fail or get stuck in a loop I can post the code to here for you to review. You can probably improve on it if you decide to merge it with your code.

fathermahoney commented 3 years ago

I am also getting this issue after roughly 24 hours. @youzer-name can you share your solution?

request: device/getDeviceDetails.json, {} response: {'ret': '100', 'msg': 'not logined or expired'

youzer-name commented 3 years ago

I've attached my still quite hacky version, but it has been working for me for some time now and I haven't had any failures. I also attached an example of a script calling the sengled.py script that I use to turn all lights off. Files have an added .txt since the site won't allow upload of .py files.

In the my-sengled.py you need to insert a UUID in two places where it says "UNIQUE.UUID.GOES.HERE". I just used an online UUID generator and pasted the results into the file. Rename that file to 'sengled.py'.

In the all_off-example.py you would need to insert your Sengled account user name and password where indicated. I also have a couple of working scripts that turn on / turn off / set color of groups of lights based on their name which I can share if needed.

It's been a little while since I worked on this, but as best I can recall what I did was check the response to see if it was the 'not logined' error and then loop back through the logon process if that was received. You'll see my code at the bottom starting at line 310 where I had it log a series of asterisks so I could see where my code was running when debugging. I don't think I changed anything above that, but I'm not sure.

So near the bottom my code starts with:

if self.debug: print ("**")

It then looks at the api response to see if the msg included the error:

    data = response.json()

    for code in data:
        try:
            msg = data['msg']
            if msg == 'not logined or expired':
                if self.debug:
                    print ("msg not logined - run login code")

If the msg contained the error message then it runs through the login code which I just copied down from above.

After that I placed:

except KeyError:
            print ("pass")
            pass

That is to bypass the error that occurs when the response doesn't contain a 'msg' element (IIRC). You might want to delete that 'print("pass") line which really isn't needed. It just let me see how many times it was looping through.

I hope this works for you also. Someone with better python skills could probably clean it up a bit, but as I said it's been working for me without fail for a couple of months.

my-sengled.py.txt all_off-example.py.txt