Modbus TCP registers uitlezen Solaredge
ik zit een beetje vast.
Zijn er mensen die ervaring hebben met het uitlezen met modbus-tcp?
Ik wil mijn data uitlezen van mijn Solaredge inverter.
Ik weet dat er kant en klare oplossingen zijn op internet maar ik wil het zelf schrijven.
Om een of andere manier krijg ik geen output.
Modbus over tcp heb ik ingeschakeld op mijn inverter, heb ik getest met een werkend python scriptje en die geeft output.
(opm.: mochten er mensen zijn die willen weten hoe je modbus-tcp enabled opSolaredge wil ik dit met harte wel uitleggen)
Aan de code is te zien dat ik veel opties heb uitgeprobeerd....
in het sunspec pdf staat ook in de appendix dat er 2 methodes zijn (met en zonder offset 40001 wat erg verwarrend is)
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php
$id = 1; //1
$fc = 3;
$offset = 0; //70, ...107
$length = 122; //39, ..3
//Appendix A – Supported MODBUS Request Methods
//SolarEdge has implemented two methods of the MODBUS request procedure:
//MODBUS request without explicit addressing – supported by communication board CPU version 2.478 and above. For example:
//$offset_h = floor($offset/256);
//$offset_l = $offset-$offset_h*256;
//MODBUS request with explicit register addressing - supported by all communication board CPU versions. For example:
$offset_h = floor(($offset+40000)/256);
$offset_l = ($offset+40000)-$offset_h*256;
$length_h = floor($length/256);
$length_l = $length-$length_h*256;
//$crc = crc16(chr(0).chr($id).chr(0).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l));
$crc = crc16(chr($id).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l));
$crc_h = floor($crc/256);
$crc_l = $crc-$crc_h*256;
if ($id<10) {$id0 = "0";} else {$id0 = "";}
if ($fc<10) {$fc0 = "0";} else {$fc0 = "";}
if ($offset_h<10) {$offset_h0 = "0";} else {$offset_h0 = "";}
if ($offset_l<10) {$offset_l0 = "0";} else {$offset_l0 = "";}
if ($length_h<10) {$length_h0 = "0";} else {$length_h0 = "";}
if ($length_l<10) {$length_l0 = "0";} else {$length_l0 = "";}
if ($crc_h<10) {$crc_h0 = "0";} else {$crc_h0 = "";}
if ($crc_l<10) {$crc_l0 = "0";} else {$crc_l0 = "";}
//$senddata = chr(0).chr($id).chr(0).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l).chr($crc_l).chr($crc_h);
$senddata = chr($id).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l).chr($crc_l).chr($crc_h);
//without crc ...
//$senddata = chr($id).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l);
$senddata2 = $id0.dechex($id)." ".$fc0.dechex($fc)." ".$offset_h0.dechex($offset_h).$offset_l0.dechex($offset_l)." ".$length_h0.dechex($length_h).$length_l0.dechex($length_l)." ".$crc_l0.dechex($crc_l).$crc_h0.dechex($crc_h);
//$senddata = "11 03 006B 0003 7687";
//$senddata = "1103006B00037687";
//print $senddata."<br />\n";
print $senddata2."<br />\n";
//print dechex($id)." ".dechex($fc)." ".dechex($offset_h).dechex($offset_l)." ".dechex($length_h).dechex($length_l)." ";
//print dechex($crc_l).dechex($crc_h);
//set_time_limit(0);
$fp = fsockopen("192.168.0.192", 502, $errno, $errstr, 3);
if(!$fp)
{
print "can\'t connect modbus tcp device<br />\n";
die();
}
else{
print "Connected to modbus<br />\n";
//11 03 0046 0027 xxxx //request 40070 +27 xxxx is crc check
//stream_set_timeout($socketHandler, 2);
write($fp, $senddata);
//write($fp, $senddata,strlen($senddata));
//set_socket_blocking($fp,true);
//fputs($fp, $senddata);
$response = '';
while (!feof($fp)) {
//echo fgets($fp, 128);
//stream_set_timeout($socketHandler, 2);
//$line[] = fgets($fp, 128);
$line[] = fgets($fp);
//echo fgets($fp);
//echo fread($fp,255);
//$response = stream_get_contents($fp);
//$line[] = fread($fp);
//$response .= fgets($fp, 128); // If you expect an answer
}
print $response;
foreach ($line as $key => $value) {
print $key+$offset.":".intval($value)."<br />\n";
}
}
fclose($fp);
function crc16($data) {
$crc16 = 0xFFFF;
for ($i = 0; $i < strlen($data); $i++)
{
$crc16 ^=ord($data[$i]);
for ($j = 8; $j !=0; $j--)
{
if (($crc16 & 0x0001) !=0)
{
$crc16 >>= 1;
$crc16 ^= 0xA001;
}
else
$crc16 >>= 1;
}
}
return $crc16;
}
?>
$id = 1; //1
$fc = 3;
$offset = 0; //70, ...107
$length = 122; //39, ..3
//Appendix A – Supported MODBUS Request Methods
//SolarEdge has implemented two methods of the MODBUS request procedure:
//MODBUS request without explicit addressing – supported by communication board CPU version 2.478 and above. For example:
//$offset_h = floor($offset/256);
//$offset_l = $offset-$offset_h*256;
//MODBUS request with explicit register addressing - supported by all communication board CPU versions. For example:
$offset_h = floor(($offset+40000)/256);
$offset_l = ($offset+40000)-$offset_h*256;
$length_h = floor($length/256);
$length_l = $length-$length_h*256;
//$crc = crc16(chr(0).chr($id).chr(0).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l));
$crc = crc16(chr($id).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l));
$crc_h = floor($crc/256);
$crc_l = $crc-$crc_h*256;
if ($id<10) {$id0 = "0";} else {$id0 = "";}
if ($fc<10) {$fc0 = "0";} else {$fc0 = "";}
if ($offset_h<10) {$offset_h0 = "0";} else {$offset_h0 = "";}
if ($offset_l<10) {$offset_l0 = "0";} else {$offset_l0 = "";}
if ($length_h<10) {$length_h0 = "0";} else {$length_h0 = "";}
if ($length_l<10) {$length_l0 = "0";} else {$length_l0 = "";}
if ($crc_h<10) {$crc_h0 = "0";} else {$crc_h0 = "";}
if ($crc_l<10) {$crc_l0 = "0";} else {$crc_l0 = "";}
//$senddata = chr(0).chr($id).chr(0).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l).chr($crc_l).chr($crc_h);
$senddata = chr($id).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l).chr($crc_l).chr($crc_h);
//without crc ...
//$senddata = chr($id).chr($fc).chr($offset_h).chr($offset_l).chr($length_h).chr($length_l);
$senddata2 = $id0.dechex($id)." ".$fc0.dechex($fc)." ".$offset_h0.dechex($offset_h).$offset_l0.dechex($offset_l)." ".$length_h0.dechex($length_h).$length_l0.dechex($length_l)." ".$crc_l0.dechex($crc_l).$crc_h0.dechex($crc_h);
//$senddata = "11 03 006B 0003 7687";
//$senddata = "1103006B00037687";
//print $senddata."<br />\n";
print $senddata2."<br />\n";
//print dechex($id)." ".dechex($fc)." ".dechex($offset_h).dechex($offset_l)." ".dechex($length_h).dechex($length_l)." ";
//print dechex($crc_l).dechex($crc_h);
//set_time_limit(0);
$fp = fsockopen("192.168.0.192", 502, $errno, $errstr, 3);
if(!$fp)
{
print "can\'t connect modbus tcp device<br />\n";
die();
}
else{
print "Connected to modbus<br />\n";
//11 03 0046 0027 xxxx //request 40070 +27 xxxx is crc check
//stream_set_timeout($socketHandler, 2);
write($fp, $senddata);
//write($fp, $senddata,strlen($senddata));
//set_socket_blocking($fp,true);
//fputs($fp, $senddata);
$response = '';
while (!feof($fp)) {
//echo fgets($fp, 128);
//stream_set_timeout($socketHandler, 2);
//$line[] = fgets($fp, 128);
$line[] = fgets($fp);
//echo fgets($fp);
//echo fread($fp,255);
//$response = stream_get_contents($fp);
//$line[] = fread($fp);
//$response .= fgets($fp, 128); // If you expect an answer
}
print $response;
foreach ($line as $key => $value) {
print $key+$offset.":".intval($value)."<br />\n";
}
}
fclose($fp);
function crc16($data) {
$crc16 = 0xFFFF;
for ($i = 0; $i < strlen($data); $i++)
{
$crc16 ^=ord($data[$i]);
for ($j = 8; $j !=0; $j--)
{
if (($crc16 & 0x0001) !=0)
{
$crc16 >>= 1;
$crc16 ^= 0xA001;
}
else
$crc16 >>= 1;
}
}
return $crc16;
}
?>
$length = 122
Maar wat mij opvalt is dat $length_h = floor($length/256) is dus 0 (nul).
En $length_l = $length-$length_h*256 is dus 122 is gewoon $length ($length = 122).
En dat gebeurt bij alle $length tussen 0 en 256.
01 03 9c40 007a ebad
en dat klopt dus.
eerst is id, 2e is functiecode, 3e is de offset (weet niet of het bij 0 of 40000 moet beginnen) en 4e is de lengte (aantal registers 007a) em het laatste is de crc16 check
toegevoegd: ff nagerekend maar dat is dus de bedoeling ook ... Length_l is de lo-byte dus restgetal van het geheel minus de high-byte
Gewijzigd op 26/11/2020 11:50:49 door Rene Wennekes
Als je aanwijzingen hebt hoe ik die weer open krijg: graag.
Ik wijd het tot nu toe aan een update van de fabrikant.
Maar heb je zo een met een blauw 20x4 lcd display en 4 knoppen met hele kleine rode lampjes?
voor de modvus-tcp aan te zetten moest je wel minimaal firmware 3.x hebben en een bepaald cpu hebben.
Overigens heeft mijn inverter nooit op 80 of 443 gewerkt ......
en modbus protocol heeft normaal poort 502 (of 1502)
In ieder geval (op eigen risico) hierond de methode om modbus-tcp aan te zetten in het 'geheime' menu.
Houd de OK-knop minstens 5 seconden ingedrukt. De volgende melding verschijnt:
Druk de knoppen Omhoog (=1), Omlaag (=2) en OK (=3)in om het wachtwoord voor hetconfiguratiemenuin te voeren: ??OK ??OK ??(1 2 3 1 2 3 1 2).
Select Communication ?LAN Conf ? Modbus TCP (the default port is 502).
2 To modify the TCP port, select Modbus TCP ? TCP Port, set the port number and long-press <Enter>.
Toevoeging op 26/11/2020 16:11:51:
opm.:?? is dus omhoog en omlaag ...^v
Gewijzigd op 26/11/2020 17:01:19 door Rene Wennekes
ik heb kennelijk een ander type, want een display is er bij mij niet aanwezig....
mijne werd geinstalleerd in 2017.
Er moeten toch meer mensen zijn die een nieuwer model hebben en realtime willen kijken zonder tussenkomst via de cloud-app van Solaredge....
Overigens merk ik dat de cloud-app erg onsecuur is en nog véél trager .....
Gewijzigd op 27/11/2020 07:48:05 door Rene Wennekes
Begrijp ik wel: die data zal op gezette tijden naar de centrale server gestuurd worden en pas daarna kan de app die raadplegen.
En volgens mij ook in een wat grovere tijdsintervallen.
Is jammer dat de poorten later gesloten zijn. Ik heb eerder wel een topic op Tweakers gelezen waarin iemand het dataverkeer snoopte om een sleutel te achterhalen om zo de data met een Raspi te op te slaan.
Dat ging me te ver. Maar nu kan ik helemaal niet meer met het ding verbinden.
Maar ik moet zeggen dat na een jaar de app en de app van de energieleverancier ook wel genoeg is.
In het begin zit je er boven op, maar nu kijk ik nog een paar keer per maand.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$host = "192.168.0.192";
$port = 502;
// No Timeout
set_time_limit(0);
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
socket_connect($socket, $host, $port) or die("Could not connect to server\n");
socket_write($socket, $senddata) or die("Could not send data to server\n");
$result = socket_recv($socket, $buf , 2000 , 0 );
echo "Reply From Server :".strlen($result)." / ".strlen($result)." / ".strlen($buf);
socket_close($socket);
print "\n\n<br />\ntest1<br />\n";
$port = 502;
// No Timeout
set_time_limit(0);
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
socket_connect($socket, $host, $port) or die("Could not connect to server\n");
socket_write($socket, $senddata) or die("Could not send data to server\n");
$result = socket_recv($socket, $buf , 2000 , 0 );
echo "Reply From Server :".strlen($result)." / ".strlen($result)." / ".strlen($buf);
socket_close($socket);
print "\n\n<br />\ntest1<br />\n";
output:
11 03 138c6 0027 ea1d
Reply From Server :1 / 1 / 0
test1
Gewijzigd op 28/11/2020 09:08:46 door Rene Wennekes
<= Onderwerp gesloten =>
Toevoeging op 03/12/2020 10:10:09:
heeft me wat hersen-kraken gekost maar ik heb het kunnen oplossen.
<= Onderwerp gesloten =>
Wat was de oplossing?