jbuehl/solaredge

SE6000 HD Wave - RS485 Connects - stuct.error when sending Get Key Commands

Opened this issue · 9 comments

Hello all -

When I run this:

./semonitor.py -t 4 -m -s 073132E72 -d stdout -vvvv /dev/ttyUSB0

I get lots of data back. Looks like a connection is being made properly via my RS485 so I think my connection is solid.

However, when I try to run the key extract commands

./semonitor.py -t 4 -m -s 073132E72 -c 12,H239/12,H23a/12,H23b/12,H23c /dev/ttyUSB0
I get

Traceback (most recent call last):
File "./semonitor.py", line 241, in
doCommands(args, mode, dataFile, recFile, outFile)
File "./semonitor.py", line 148, in doCommands
se.msg.formatMsg(nextSeq(), MASTER_ADDR, args.slaves[0], se.commands.PROT_CMD_POLESTAR_MASTER_GRANT),
File "/home/pi/solaredge/se/msg.py", line 205, in formatMsg
checksum = calcCrc(struct.pack(">HLLH", msgSeq, fromAddr, toAddr, function) + data)
struct.error: cannot convert argument to integer

I guess, I am at a loss here, it appears to be making a proper connection, but I can't seem to pull data from it... Any thoughts?

With Debug:
./semonitor.py -t 4 -m -s 073132E72 -c 12,H239/12,H23a/12,H23b/12,H23c -d stdout -vvvv /dev/ttyUSB0
append: False
baudrate: 115200
commands: 12,H239 12,H23a 12,H23b 12,H23c
datasource: /dev/ttyUSB0
follow: False
following: True
interface: None
keyfile: None
logfile: stdout
master: True
outfile: stdout
ports: 22222,22221,80
record: None
slaves: 073132E72
type: 4
updatefile: None
verbose: 4
xerror: False
opening /dev/ttyUSB0
Traceback (most recent call last):
File "./semonitor.py", line 241, in
doCommands(args, mode, dataFile, recFile, outFile)
File "./semonitor.py", line 148, in doCommands
se.msg.formatMsg(nextSeq(), MASTER_ADDR, args.slaves[0], se.commands.PROT_CMD_POLESTAR_MASTER_GRANT),
File "/home/pi/solaredge/se/msg.py", line 205, in formatMsg
checksum = calcCrc(struct.pack(">HLLH", msgSeq, fromAddr, toAddr, function) + data)
struct.error: cannot convert argument to integer

RS-485 Properly Returned Data
./semonitor.py -t 4 -m -s 073132E72 -d stdout -vvvv /dev/ttyUSB0

/dev/ttyUSB0 --> message: 2 length: 379
data:       12 34 56 79 65 01 9a fe d2 04 72 2e 13 73 fe ff
data:       ff ff 00 05 80 00 dc dc 3e 11 0d 00 71 d6 fa 5b
data:       e3 2f 11 85 e5 04 dd 00 01 80 00 4e e7 3e 11 0d
data:       00 7c d6 fa 5b ee 2f 08 81 15 05 f1 00 01 80 00
data:       9e d6 3e 11 0d 00 7f d6 fa 5b f1 2f 10 79 f5 04
data:       f3 00 01 80 00 9a 80 3d 11 0d 00 89 d6 fa 5b b6
data:       27 0a 81 b5 04 d1 00 01 80 00 69 ea 3e 11 0d 00
data:       99 d6 fa 5b 0b 30 0a 71 65 05 eb 00 01 80 00 1b
data:       d3 3e 11 0d 00 c0 d6 fa 5b 32 30 0c 7d 35 05 e7
data:       00 01 80 00 a1 d6 3e 11 0d 00 d5 d6 fa 5b 80 28
data:       04 75 b5 04 cd 00 01 80 00 c9 d7 3e 11 0d 00 e1
data:       d6 fa 5b 52 30 06 75 15 04 be 00 01 80 00 4a e7
data:       3e 11 0d 00 e9 d6 fa 5b 5a 30 04 79 a5 04 de 00
data:       01 80 00 97 df 3e 11 0d 00 fd d6 fa 5b d7 27 0d
data:       85 15 05 cb 00 01 80 00 7b ea 3e 11 0d 00 05 d7
data:       fa 5b 76 30 0a 81 65 05 e6 00 01 80 00 2e dd 3e
data:       11 0d 00 0a d7 fa 5b 7c 30 13 71 b5 04 e0 00 01
data:       80 00 70 ea 3e 11 0d 00 0f d7 fa 5b 80 30 04 71
data:       65 05 e6 00 01 80 00 af e9 3e 11 0d 00 15 d7 fa
data:       5b 86 30 0a 85 b5 04 e3 00 01 80 00 ad d6 3e 11
data:       0d 00 2d d7 fa 5b 9e 30 0a 81 d5 05 e5 00 01 80
data:       00 70 d4 3e 11 0d 00 50 d7 fa 5b c1 30 0e 71 85
data:       05 e7 00 01 80 00 b5 3e 3e 11 0d 00 5a d7 fa 5b
data:       cb 30 10 81 b5 05 e2 00 01 ea ff
dataLen:    0165
dataLenInv: fe9a
sequence:   04d2
source:     73132e72
dest:       fffffffe
function:   0500
optimizer:      113EDCDC type: 0080 len: 000d
    Uptime : 12259
    Temp : 2.0
    Vmod : 34.125
    Imod : 0.4875
    Eday : 55.25
    Vopt : 44.125
    Time : 11:05:53
    Date : 2018-11-25
    Inverter : 0
    ID : 113EDCDC

Look at issue #45.

I did, and the answer was here:

#45 (comment)

I found a possible issue in semonitor.py,
line 148 should read:
se.msg.formatMsg(nextSeq(), MASTER_ADDR, int(args.slaves[0], 16), se.commands.PROT_CMD_POLESTAR_MASTER_GRANT),

instead of:
se.msg.formatMsg(nextSeq(), MASTER_ADDR, args.slaves[0], se.commands.PROT_CMD_POLESTAR_MASTER_GRANT),

This fix solved the error when sending a command (struct.error: cannot convert argument to integer).

The communication problem with the inverter remains though (RS485 master ack timeouts)...

So, to clean things up, the answer was above, I have two points

  1. Can we roll that change into the repo or is there a reason it has to stay without the the int() function? Perhaps if it's unique to the HDWave inverters, we should set a flag.

  2. Even when I had this, I basically had to run the pipe to sekey.py multiple times until it finally wrote a key out. sekey.py didn't give any feed back, and I wouldn't have known if it worked.

I got this error a lot

Checksum error. Expected 0x53c1, got 0x8709
Traceback (most recent call last):
File "./utilities/sekey.py", line 25, in
key += struct.pack("<L", data["data"]["value"])
TypeError: string indices must be integers

  1. I made the change to semonitor.py. No reason it wasn't done before, other than it fell through the cracks.

  2. I suspect that the output of running semonitor.py to extract the key is different between running it over RS232 and RS485. Can you run it without piping it to sekey.py and post the output here?

So, This is probably not what you want, but it may help others when getting the keys. On the HDWave, I started issuing the commands one at a time. What I realized is that the first request of the next command, actually returned the previous key return.

So the 4 commands 12,H239 12,H23a 12,H23b 12,H23c, when I first returned the value of 12,H23a, it actually returned the previous value. That could be messing with some folks.

pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H239 /dev/ttyUSB0|tee  key1.raw
{"data": {"type": 0, "value": VALUE1}, "command": 18, "response": 144, "sequence": 296}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H239 /dev/ttyUSB0|tee  key1.raw
{"data": {"type": 0, "value": VALUE1}, "command": 18, "response": 144, "sequence": 298}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H239 /dev/ttyUSB0|tee  key1.raw
{"data": {"type": 0, "value": VALUE1}, "command": 18, "response": 144, "sequence": 300}

pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23a /dev/ttyUSB0|tee  key2.raw
{"data": {"type": 0, "value": VALUE1}, "command": 18, "response": 144, "sequence": 302}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23a /dev/ttyUSB0|tee  key2.raw
{"data": {"type": 0, "value": VALUE2}, "command": 18, "response": 144, "sequence": 304}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23a /dev/ttyUSB0|tee  key2.raw
{"data": {"type": 0, "value": VALUE2}, "command": 18, "response": 144, "sequence": 306}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23a /dev/ttyUSB0|tee  key2.raw
{"data": {"type": 0, "value": VALUE2}, "command": 18, "response": 144, "sequence": 308}

pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23b /dev/ttyUSB0|tee  key3.raw
{"data": {"type": 0, "value": VALUE2}, "command": 18, "response": 144, "sequence": 310}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23b /dev/ttyUSB0|tee  key3.raw
{"data": {"type": 0, "value": VALUE3}, "command": 18, "response": 144, "sequence": 312}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23b /dev/ttyUSB0|tee  key3.raw
{"data": {"type": 0, "value": VALUE3}, "command": 18, "response": 144, "sequence": 314}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23b /dev/ttyUSB0|tee  key3.raw
{"data": {"type": 0, "value": VALUE3}, "command": 18, "response": 144, "sequence": 316}

pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23c /dev/ttyUSB0|tee  key4.raw
{"data": {"type": 0, "value": VALUE3}, "command": 18, "response": 144, "sequence": 318}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23c /dev/ttyUSB0|tee  key4.raw
{"data": {"type": 0, "value": VALUE4}, "command": 18, "response": 144, "sequence": 320}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23c /dev/ttyUSB0|tee  key4.raw
{"data": {"type": 0, "value": VALUE4}, "command": 18, "response": 144, "sequence": 322}
pi@FARMPI1:~/solaredge $ ./semonitor.py -t 4 -m -s 073132E72 -c 12,H23c /dev/ttyUSB0|tee  key4.raw
{"data": {"type": 0, "value": VALUE4}, "command": 18, "response": 144, "sequence": 324}

I'm not sure what your last post is showing. What's with the crossed out lines?

If you say the commands only work one at a time and the output is from the previous command, I think I see what the problem is. The master grant message is only being sent once before the commands are sent, so the slave is only responding to the previous command. I don't currently have an RS485 connection, so I can't test it myself. Here is a modification that may fix the problem. Move the if block that is in lines 145-150 of semonitor.py to after line 160 and increase the indent of the block by 4 spaces:

diff --git a/semonitor.py b/semonitor.py
index 578225a..913337e 100755
--- a/semonitor.py
+++ b/semonitor.py
@@ -142,12 +142,6 @@ def masterCommands(dataFile, recFile, slaveAddrs):
 
 # perform the specified commands
 def doCommands(args, mode, dataFile, recFile, outFile):
-    if mode.masterMode:  # send RS485 master command
-        # grant control of the bus to the slave
-        se.msg.sendMsg(dataFile,
-                se.msg.formatMsg(nextSeq(), MASTER_ADDR, int(args.slaves[0], 16), 
-                se.commands.PROT_CMD_POLESTAR_MASTER_GRANT), 
-                recFile)
     for command in args.commands:
         # format the command parameters
         function = int(command[0], 16)
@@ -158,6 +152,12 @@ def doCommands(args, mode, dataFile, recFile, outFile):
         se.msg.sendMsg(dataFile,
                 se.msg.formatMsg(seq, MASTER_ADDR, int(args.slaves[0], 16), function,
                           struct.pack(format, *tuple(params))), recFile)
+        if mode.masterMode:  # send RS485 master command
+            # grant control of the bus to the slave
+            se.msg.sendMsg(dataFile,
+                    se.msg.formatMsg(nextSeq(), MASTER_ADDR, int(args.slaves[0], 16), 
+                    se.commands.PROT_CMD_POLESTAR_MASTER_GRANT), 
+                    recFile)
         # wait for the response
         (msg, eof) = se.msg.readMsg(dataFile, recFile, mode)
         (msgSeq, fromAddr, toAddr, response, data) = se.msg.parseMsg(msg)

You should see output that looks something like this

{"data": {"type": 0, "value": VALUE1}, "command": 18, "response": 144, "sequence": xx1}
{"data": {"type": 0, "value": VALUE2}, "command": 18, "response": 144, "sequence": xx2}
{"data": {"type": 0, "value": VALUE3}, "command": 18, "response": 144, "sequence": xx3}
{"data": {"type": 0, "value": VALUE4}, "command": 18, "response": 144, "sequence": xx4}

That proposed change would not have worked. I just pushed a change that has a better chance of fixing it. If you could try it and let me know what happens it would be appreciated. The reason I don't have an RS485 connection is because I don't need it, so fixing this bug is solely for the benefit of other people. Thanks.

Hello,

I'm currently experimenting to extract the key from my SE3500H via RS485 and came here because I have a similiar issue:

$ python3 semonitor.py -c 12,H239/12,H239/12,H23a/12,H23a/12,H23b/12,H23b/12,H23c/12,H23c -s 7312XXXX -t 4 /dev/cu.usbserial-1410
{"command": 18, "data": "", "response": 0, "sequence": 115}
{"command": 18, "data": {"type": 0, "value": 1084732775}, "response": 144, "sequence": 116}
{"command": 18, "data": {"type": 0, "value": 1084732775}, "response": 144, "sequence": 117}
{"command": 18, "data": {"type": 0, "value": 1494584196}, "response": 144, "sequence": 118}
{"command": 18, "data": {"type": 0, "value": 1494584196}, "response": 144, "sequence": 119}
{"command": 18, "data": {"type": 0, "value": 382591637}, "response": 144, "sequence": 120}
{"command": 18, "data": {"type": 0, "value": 382591637}, "response": 144, "sequence": 121}
{"command": 18, "data": {"type": 0, "value": 853491439}, "response": 144, "sequence": 122}

Note that I send every command twice and the replies are shifted one to the "back". Also "command" is printed first.

When I shuffle things around to look according to the expected format, sekey complains.

$ cat sekeyraw
{"data": {"type": 0, "value": 1084732775}, "command": 18, "response": 144, "sequence": 89}
{"data": {"type": 0, "value": 1494584196}, "command": 18, "response": 144, "sequence": 91}
{"data": {"type": 0, "value": 382591637}, "command": 18, "response": 144, "sequence": 93}
{"data": {"type": 0, "value": 853491439}, "command": 18, "response": 144, "sequence": 95}
$ python3 utilities/sekey.py sekeyraw 
Traceback (most recent call last):
  File "utilities/sekey.py", line 25, in <module>
    key += struct.pack("<L", data["data"]["value"])
TypeError: can only concatenate str (not "bytes") to str

Any ideas?
Regards,
-m