jbuehl / solaredge

SolarEdge inverter logging data capture
GNU General Public License v3.0
289 stars 60 forks source link

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

Open JohnOmernik opened 5 years ago

JohnOmernik commented 5 years ago

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
jbuehl commented 5 years ago

Look at issue #45.

JohnOmernik commented 5 years ago

I did, and the answer was here:

https://github.com/jbuehl/solaredge/issues/45#issuecomment-386836377

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)...

JohnOmernik commented 5 years ago

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

jbuehl commented 5 years ago
  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?

JohnOmernik commented 5 years ago

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}
jbuehl commented 5 years ago

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}
JohnOmernik commented 5 years ago

Ah ya, sorry about the lines.. I will see if I can edit. But yes, the first time I issue the next command, it actually gives me the value from the previous.

On Mon, Nov 26, 2018 at 12:03 PM jbuehl notifications@github.com wrote:

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}

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jbuehl/solaredge/issues/114#issuecomment-441737571, or mute the thread https://github.com/notifications/unsubscribe-auth/AB1zUctDg6O-mNzGva8UWQMZitoqQdzZks5uzC0AgaJpZM4Yx-Bf .

jbuehl commented 5 years ago

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.

geowiwi commented 4 years ago

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