mjg59 / python-broadlink

Python module for controlling Broadlink RM2/3 (Pro) remote controls, A1 sensor platforms and SP2/3 smartplugs
MIT License
1.39k stars 479 forks source link

AuthorizationError: Control key is expired - Developing Eventghost Plugin - rm 3 mini #460

Closed steffenu closed 4 years ago

steffenu commented 4 years ago

Greetings ... Im trying to develop a plugin for Eventghost ...

Using the previous release try to make a rm 3 mini compatible--> 0x5f36 ... still rocking pyhton 2.7

I can run a single action , like learn a single command or send a single command but any follow up command throws

     File "C:\ProgramData\EventGhost\plugins\Broadlink\broadlink\__init__.py", line 282, in auth
       check_error(response[0x22:0x24])
     File "C:\ProgramData\EventGhost\plugins\Broadlink\broadlink\exceptions.py", line 97, in check_error
       raise exception(error_code)
   AuthorizationError: Control key is expired

Any chance you can lend me a hand figuring out the root of this problem ?

Greetings

felipediel commented 4 years ago

You need to authenticate first.

import broadlink as blk

d = blk.hello("192.168.0.17")  # Example device
d.auth()
steffenu commented 4 years ago

You need to authenticate first.

import broadlink as blk

d = blk.hello("192.168.0.17")  # Example device
d.auth()

ok will try

Im using the previous release. For my understanding ... the hello() method is necessary? Hopefully I can extract it and put it into that previous version then... (which I made running with py 2.7)

So basically the previous release isnt able at all to communicate with devices using the newer firmware ?

I still have an older rm pro plus ... which works perfectly ... and it doesnt have any auth stuff .... Also was able to use the app and the library simultanisously ... until I updated the app out of curiousity :D... now it says I need to upgrade the firmware on the app .... but I better not do that I guess... (wanted to check out the unlock feature they added to the app ... thought I could get rid of the auth error that way)

steffenu commented 4 years ago

ok I pulled over the hello() method into version 0.1.4.1 which needs new xdiscover() andscan() and a slightly modifed gendevice() as well as the newdiscover() method that basicly just runs the scan() method

I removed the type annotations for py 2.7...

now im getting this error running the discover method ;

  File "C:\ProgramData\EventGhost\plugins\Broadlink\__init__.py", line 209, in discoverDevices
    discovered = broadlink.discover(timeout=conTimeout)
  File "C:\ProgramData\EventGhost\plugins\Broadlink\broadlink\__init__.py", line 385, in discover
    return [gendevice(*resp) for resp in responses]
  File "C:\ProgramData\EventGhost\plugins\Broadlink\broadlink\__init__.py", line 1414, in scan
    devtype = response[0x34] | response[0x35] << 8
TypeError: unsupported operand type(s) for <<: 'str' and 'int'

EDIT : I fixed the error by adding this line to scan

+ response = bytearray(response)
devtype = response[0x34] | response[0x35] << 8

I can learn codes ... but sending the ones that the rm mini learned dont work ... but they send... .... but thhe ones that I learned with my rm_plus work.... ?????

Volume command recorded by rm 3 mini - sendable - but dont work (Command 2 and 0)

Volume command recorded by rm pro plus - sendable - WORK (Command 1)

[{"data": "0000260046008d941338123812381213121312131213121411391139113912131114121313131114111411141114111412131139123911141139113911391238123911141114113911000d05", "command": 0}, {"command": 1, "data": "260046009495113a1139113a10151114111411151015103a1239103a11141115101511141114113a103a1115103a111411141115101510151114113a11141139113a103a113a10000d050000"}, {"data": "0000260046008f941238123813381213121311141213111411391238133811141213111412131213123813381139121312131114121312131312121411141238123812381338123811000d05", "command": 2}]

There is still smth wrong with the codes recordeed... The ones that dont work have 4 extra zeros at the start but those zeros should be at the end if I see this right ?

This should be fixable ? If need be I do this manually ... but you probably know what im doing wrong

felipediel commented 4 years ago

You don't need blk.hello(). This line is just to examplify the instantiation of the controller. You can do it the old way if you want. All you need is d.auth().

If you want to adapt this code to Python 2, it is not only an annotations thing. We reworked all the code. Python 2 treats bytes as strings. You will need a lot of conversions.

steffenu commented 4 years ago

You don't need blk.hello(). This line is just to examplify the instantiation of the controller. You can do it the old way if you want. All you need is d.auth().

If you want to adapt this code to Python 2, it is not only an annotations thing. We reworked all the code. Python 2 treats bytes as strings. You will need a lot of conversions.

Ok now that makes sense if py3 treats bytes differently ... I was wondering how the latest code even works ....

Regarrding the problem. of the zeros shifting from left to right ... can you give me a hint on where to start looking ...

I suspect the problem is somewhere going through my code from the check data which I already "patched" a couple times (looking at open issues):

wrongly shifting zeros to the left side of the bytestring

0000260046008f941238123813381213121311141213111411391238133811141213111412131213123813381139121312131114121312131312121411141238123812381338123811000d05

-->

260046008f941238123813381213121311141213111411391238133811141213111412131213123813381139121312131114121312131312121411141238123812381338123811000d050000

You could save me a major headache if you could tell me what I can do to / need to understand to figure this out ...

I dont expect you to solve it for me :D ... but im clueless where to look. @felipediel

    def check_data(self):
        packet = bytearray(self._request_header)
        packet.append(0x04)
        response = self.send_packet(0x6a, packet)

        try:
            check_error(response[0x22:0x24])

        except (ReadError, StorageError):
            pass

        err = response[0x22] | (response[0x23] << 8)
        if err == 0:
            payload = self.decrypt(bytes(response[0x38:]))
            return payload[0x04:]

I wont try rewriting everything to pyhthon 3 ... thats way too much ...

But I already got the rm pro plus working and ... and the rm 3 mini is basically also done if it weren't for this shifting problem ....

I mean the recording and all works for the rm 3 mini... there is just some switcheroo going on that I dont know the cause of

felipediel commented 4 years ago

We use a padding mechanism to prepare the message for AES encryption. We append 0's to the payload when necessary so its length will always be multiple of 16.

steffenu commented 4 years ago

We use a padding mechanism to prepare the message for AES encryption. We append 0's to the payload when necessary so its length will always be multiple of 16.

Thank you this helped me figure it out .... all working now THANK YOU !!!!!!!!!

EDIT : Btw I will upload the plugin soon ... in case anyone uses Eventghost and using a rm 3 mini :D ...

http://www.eventghost.net/forum/viewtopic.php?f=9&t=10543&p=55689#p55689