jblance / mpp-solar

Python package to communicate to MPP Solar PIP-4048MS inverters (and similar)
MIT License
364 stars 151 forks source link

Serial read error: unicode strings are not supported, please encode to bytes: #15

Closed volkerjaenisch closed 4 years ago

volkerjaenisch commented 4 years ago

Dear John!

Python 3.7.3 pipenv environment on a vanilla[*] buster raspberryPi Zero W.

$git clone ...; cd ...
$pipenv install
$pipenv shell
$python setup.py develop
(mpp-solar-ZAEQa1-O) pi@controller:~/workspace/mpp-solar $ mpp-solar -d /dev/ttyAMA0 
WARNING:MPP-Solar:Serial read error: unicode strings are not supported, please encode to bytes: 'QIDÖê\r'
error                           No response

The exception is purely python related and has nothing to do with the actual hardware and is easily fixed:

(mpp-solar-ZAEQa1-O) pi@controller:~/workspace/mpp-solar/mppsolar $ diff mppinverter.py mppinverter.py~
258c258
<                     s.write(command.full_command.encode())
---
>                     s.write(command.full_command)

leading to

INFO:MPP-Solar:Invalid response
Traceback (most recent call last):
  File "/home/pi/.local/share/virtualenvs/mpp-solar-ZAEQa1-O/bin/mpp-solar", line 11, in <module>
    load_entry_point('mpp-solar', 'console_scripts', 'mpp-solar')()
  File "/home/pi/workspace/mpp-solar/mppsolar/__init__.py", line 81, in main
    results = mp.getResponseDict(args.command)
  File "/home/pi/workspace/mpp-solar/mppsolar/mpputils.py", line 37, in getResponseDict
    return self.inverter.getResponseDict(cmd)
  File "/home/pi/workspace/mpp-solar/mppsolar/mppinverter.py", line 209, in getResponseDict
    return result.getResponseDict()
  File "/home/pi/workspace/mpp-solar/mppsolar/mppcommand.py", line 414, in getResponseDict
    msgs['response'] = [self.response.replace('\r', ''), '']
TypeError: a bytes-like object is required, not 'str'

Is your code not python3 compatible? The setup.py states it is up too 3.8?

Additional information: 1) I changed the boot process to avoid the HID driver to claim the usb-serial device as HID device by console=tty1 root=PARTUUID=738a4d67-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait usbhid.quirks=0x0665:0x5161:0x4

2) According to https://www.raspberrypi.org/documentation/configuration/uart.md I have deactivated the usage of Bluetooth and assigned the PLO110 UART to the GPIO Pins which I use as /dev/ttyAMA0 to access the inverter.

Tomorrow I will try the USB interface.

Any help appreciated

Volker

jblance commented 4 years ago

Hi

It's supposed to support python3, but the encoding doesnt seem to work across versions. Your fix will break the code for python2.7

Looks like I need to look at moving to unicode strings throughout.

jblance commented 4 years ago

If you have any suggestions on how to make it work for both python2 and 3, I'd love to hear them The differences seem to make it impossible to write something that will work on both versions

volkerjaenisch commented 4 years ago

@jblance We have lot of experience in Python3 migration. I will come up this weekend with a fix that support both versions.

Btw. utilizing the USB-Interface works. I have had to reenable the USB HID-Driver. But it runs as instable as my own code. Approximately one out of five request are failing. I am quite sure that this is not a software but a hardware related problem. What is your experience?

Cheers, Volker

jblance commented 4 years ago

In my setup, I use a USB-serial adapter and have no problems with the communications running every second I also have a direct USB connection to my second inverter that i use for testing, that works everytime i test it

volkerjaenisch commented 4 years ago

Looks like a hardware error at my customer.

Im am 100% due with the python2/3 code compatibility. The code is up and running perfectly from python2/3. Have a peek here

But I struggle with the testing.

"test_responses": [
       "(230.0 50.0 0030 42.0 54.0 56.4 46.0 60 0 0 2 0 0 0 0 0 1 1 0 0 1 0 54.0 0 1 000\u009e\u0060\r"
    ],

The test_responses JSON-Data undergoes a lot of transformations before it is matched against a binary response from the Inverter. Each of these transformations are prone to Python-version/language/country settings of the OS.

So I opt for the following data scheme:

"test_responses": [
       { payload: "(230.0 50.0 0030 42.0 54.0 56.4 46.0 60 0 0 2 0 0 0 0 0 1 1 0 0 1 0 54.0 0 1 000",
         crc :  "9e60"
       }
    ],

We separate the ASCII strings which are compatible between platforms from the CRC which is platform/python version dependent.

cheers, Volker