LinuxChristian / pyW215

Python interface to the d-link W215 smart plug.
MIT License
37 stars 25 forks source link

Problem with DSP-W215 HW version B2 #28

Closed mozo178 closed 5 years ago

mozo178 commented 6 years ago

Hi, Your plugin works perfect with B1 version, but not with the B2 version. The firmware version is the same (2.22) with bth devices. I tried it with 2.23 with the same result. (Only with B2).

Can you help me how to solve this?

I get the following error message, (I removed the ip address and the key):

exit code: 1, Traceback (most recent call last): File "dlink2.py", line 4, in sp = SmartPlug('xxx.xxx.xx.xx','xxxxxx') File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 61, in init self.model_name = self.SOAPAction(Action="GetDeviceSettings", responseElement="ModelName", params = "") File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 168, in SOAPAction xmlData = response.read().decode() UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 383: ordinal not in range(128)

LinuxChristian commented 6 years ago

Thanks for the bug report. Let's see if we can get your plug working.

Can I get you to print the response variable on line 168? The string is perhaps not the correct format.

mozo178 commented 6 years ago

Hi, Please help me how I can do that, which command should I use, etc. I am not good in this.

LinuxChristian commented 6 years ago

Sure and sorry for the late reply.

Find line 168 in the file pyW2115.py in the folder pyW215 and add the following print statement,

            if recursive or return_value is None:
                _LOGGER.warning("Failed to open url to {}".format(self.ip))
                self._error_report = True
                return None
            else:
                return return_value
        print(response) # <---- This is the only change on line 167
        xmlData = response.read().decode()
        root = ET.fromstring(xmlData)

Then run your normal command to execute the script and you should get more information about the response variable. Try sending that to me and we can have a look.

mozo178 commented 6 years ago

Thanks, I tried the modified script my work and the not work device.

The result with the working (old) device: <addinfourl at 3060197496L whose fp = <socket._fileobject object at 0xb666a630>> <addinfourl at 3060235800L whose fp = <socket._fileobject object at 0xb666ad70>> 147.98 <addinfourl at 3060255200L whose fp = <socket._fileobject object at 0xb66830f0>> 44 <addinfourl at 3060234840L whose fp = <socket._fileobject object at 0xb666abf0>> 23.683037

The result with the new not working device: exit code: 1, Traceback (most recent call last): File "dlink2.py", line 4, in sp = SmartPlug('192.168.1.52','392511') File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 61, in init self.model_name = self.SOAPAction(Action="GetDeviceSettings", responseElement="ModelName", params = "") File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 168, in SOAPAction xmlData = response.read().decode() UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 383: ordinal not in range(128)

LinuxChristian commented 6 years ago

Okay. So you get some object back but the object handler does not provide a lot of information. It is quite strange but the error message would suggest you get back non-ASCII chars. Try this,

            if recursive or return_value is None:
                _LOGGER.warning("Failed to open url to {}".format(self.ip))
                self._error_report = True
                return None
            else:
                return return_value
        xmlData = response.read().decode('utf-8') # <---- Edit here
        print(xmlData)                            # <---- and here
        root = ET.fromstring(xmlData)
mozo178 commented 6 years ago

exit code: 1, Traceback (most recent call last): File "dlink2.py", line 4, in sp = SmartPlug('192.168.1.52','392511') File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 61, in init self.model_name = self.SOAPAction(Action="GetDeviceSettings", responseElement="ModelName", params = "") File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 169, in SOAPAction print(xmlData) UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 383: ordinal not in range(128)

LinuxChristian commented 6 years ago

Still strange. So now the decode works... How about his,

            if recursive or return_value is None:
                _LOGGER.warning("Failed to open url to {}".format(self.ip))
                self._error_report = True
                return None
            else:
                return return_value
        xmlData = response.read().decode('utf-8')
        print(xmlData.encode('utf-8')) 
        root = ET.fromstring(xmlData)
mozo178 commented 6 years ago

"exit code: 1, Traceback (most recent call last):↵ File "dlink2.py", line 4, in ↵ sp = SmartPlug('192.168.1.52','392511')↵ File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 61, in init↵ self.model_name = self.SOAPAction(Action="GetDeviceSettings", responseElement="ModelName", params = "")↵ File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 170, in SOAPAction↵ root = ET.fromstring(xmlData)↵ File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1311, in XML↵ parser.feed(text)↵ File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1651, in feed↵ self._parser.Parse(data, 0)↵UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 383: ordinal not in range(128)↵"

LinuxChristian commented 6 years ago

Okay.. so the error is moving down 😄

You only get the error? Not the print? Would really like to see the content of xmlData.

One final suggestion (a bit of going over the bridge but let's see),

        xmlData = response.read().decode('utf-8')
        print(xmlData.encode('utf-8')) 
        root = ET.fromstring(xmlData.encode('utf-8'))
mozo178 commented 6 years ago

It is alive!!!!!! :D Thank you very much. Now your script can work with DSP-W215 H/W Ver.:B2! :)

LinuxChristian commented 6 years ago

That great! Perhaps we can clean it up a bit then I can add it to the master branch. Can you check if this works,

        try:
             xmlData = response.read().decode()
       except UnicodeEncodeError:
            xmlData = response.read()
        root = ET.fromstring(xmlData)

If is say something like: UnicodeEncodeError not defined then try,

        try:
             xmlData = response.read().decode()
       except:
            xmlData = response.read()
        root = ET.fromstring(xmlData)
mozo178 commented 6 years ago

First version: exit code: 1, Traceback (most recent call last): File "dlink2.py", line 2, in from pyW215.pyW215 import SmartPlug, ON, OFF File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 169 except UniCodeEncodeError: ^ SyntaxError: invalid syntax

Second version: exit code: 1, Traceback (most recent call last): File "dlink2.py", line 2, in from pyW215.pyW215 import SmartPlug, ON, OFF File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 169 except: ^ SyntaxError: invalid syntax

LinuxChristian commented 6 years ago

Sorry. My bad. All the lines should be the same indentation (align). So I think the line with except needs a space?

mozo178 commented 6 years ago

No, no, my bad, I missec to write try. :D First version: exit code: 1, Traceback (most recent call last): File "dlink2.py", line 4, in sp = SmartPlug('192.168.1.52','392511') File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 61, in init self.model_name = self.SOAPAction(Action="GetDeviceSettings", responseElement="ModelName", params = "") File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 169, in SOAPAction except UniCodeDecodeError: NameError: global name 'UniCodeDecodeError' is not defined

Second version: exit code: 1, Traceback (most recent call last): File "dlink2.py", line 2, in from pyW215.pyW215 import SmartPlug, ON, OFF File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 171 root = ET.fromstring(xmlData) ^ IndentationError: unexpected indent

LinuxChristian commented 6 years ago

Okay.. Version 2 should work but is not aligned with the other lines. Perhaps it is missing a space or has one too many?

mozo178 commented 6 years ago

If the lines aligned like this: try: xmlData = response.read().decode() except: xmlData = response.read() root = ET.fromstring(xmlData)

Then:

exit code: 1, Traceback (most recent call last): File "dlink2.py", line 4, in sp = SmartPlug('192.168.1.52','392511') File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 61, in init self.model_name = self.SOAPAction(Action="GetDeviceSettings", responseElement="ModelName", params = "") File "/usr/local/lib/python2.7/dist-packages/pyW215/pyW215.py", line 173, in SOAPAction root = ET.fromstring(xmlData) File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1312, in XML return parser.close() File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1665, in close self._raiseerror(v) File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1517, in _raiseerror raise err xml.etree.ElementTree.ParseError: no element found: line 1, column 0

mozo178 commented 6 years ago

It removed my tabs. :( try: xmlData = response.read().decode() except: xmlData = response.read() root = ET.fromstring(xmlData)

Edit: and my spaces...

LinuxChristian commented 6 years ago

Think I lost the overview of what your code looks like now 😄

In Python spaces are part of the language. So you normally use 4 space indentation. So the line after try should have four spaces more than try. The line after except should also have four spaces more than the except line. Try and except are indented by 8 spaces because they are part of the function that is part of a class. The class is zero spaces. All function below that start at 4 spaces. All code within a function starts at 8 spaces and so on.

I have added the number of spaces I have on each line to the beginning of the line,

8    try:
12        xmlData = response.read().decode()
8    except:
12        xmlData = response.read()
8    root = ET.fromstring(xmlData)

Does that make sense?

mozo178 commented 5 years ago

Hi, sorry for the late answer, but I killed my raspberry zero with a modbus test and tried to make it work again. I installed it with pip install pyW215 when use the command python dlink1.py (I have 2 dlinks and renamed the files to dlink1.py and dlink2.py) There is an error:

Traceback (most recent call last): File "dlink1.py", line 2, in from pyW215.pyW215 import SmartPlug, ON, OFF ImportError: No module named pyW215

I found the path where the pip installed the py: /home/pi/.local/lib/python2.7/site-packages/pyW215

There can be the problem?

LinuxChristian commented 5 years ago

Sorry for the late reply.

Try running which python My guess is that you are running python3 but pip is installed on python2.7.

If that is the case you need to run python2.7 dlink1.py

mozo178 commented 5 years ago

kepernyokep errol 2018-12-02 08-54-04 Hi, now everything work like a charm. :) I did not modificate the pyW215.py file, only installed it with pip install pyW215.

You can close the issue. ;)