Cookies op Tweakers

Tweakers is onderdeel van DPG Media en maakt gebruik van cookies, JavaScript en vergelijkbare technologie om je onder andere een optimale gebruikerservaring te bieden. Ook kan Tweakers hierdoor het gedrag van bezoekers vastleggen en analyseren. Door gebruik te maken van deze website, of door op 'Cookies accepteren' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt? Bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

GoodWe inverter lokaal uitlezen (USB / WiFi)

Pagina: 1
Acties:

Onderwerpen


  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
Voor de mensen die geïnteresseerd zijn in het kunnen uitlezen van een GoodWe inverter via de USB aansluiting aan de onderkant, heb ik op GitHub een eerste versie gezet van een python script dat dit mogelijk maakt.

Met hulp van het programma EZExplorer (GoodWe) en een USB sniffer, heb ik de communicatie kunnen ontrafelen.

https://github.com/sircuri/GoodWeUSBLogger

Signature van nature


  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Geinig!

Een tijdje terug heb ik @CodeIT geholpen om te zorgen dat we onze GoodWe's kunnen uitlezen via RS485.
Hij heeft er een firmware voor de ESP8266 voor geschreven: CodeIT in "Datalogging: PV systemen"

Werkt als een trein!

Edit: Ik zie nu dat jouw code gebaseerd is daarop, LOL te snel gelezen :P
Wat voor apparaat gebruik je om de GoodWe uit te lezen? Een Raspberry Pi o.i.d. ?

En dan een USB-A naar USB-A kabel ergens van eBay ofzo gehaald? Is niet echt een veelgebruikte kabel...

[Voor 35% gewijzigd door ThinkPad op 04-09-2017 16:52]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
ThinkPad schreef op maandag 4 september 2017 @ 16:50:
Geinig!

Een tijdje terug heb ik @CodeIT geholpen om te zorgen dat we onze GoodWe's kunnen uitlezen via RS485.
Hij heeft er een firmware voor de ESP8266 voor geschreven: CodeIT in "Datalogging: PV systemen"

Werkt als een trein!

Edit: Ik zie nu dat jouw code gebaseerd is daarop, LOL te snel gelezen :P
Wat voor apparaat gebruik je om de GoodWe uit te lezen? Een Raspberry Pi o.i.d. ?

En dan een USB-A naar USB-A kabel ergens van eBay ofzo gehaald? Is niet echt een veelgebruikte kabel...
Klopt, jouw naam ben ik ook erg vaak tegengekomen op internet wat betreft GoodWe inverters uitlezen.
Inderdaad heb ik het daar op gebaseerd, maar ik moet het doen via USB, want de WiFi dongle zit vastgesoldeerd op de type inverter die ik heb.

Ik heb het nu gedaan met een Ubuntu desktop, maar ben bezig om het te verbinden met een Raspberry pi zero. Moet ook werken natuurlijk. Dus dat het nu de eerst volgende stap.
[update] En dat werkt ook ondertussen.

edit: En wat betreft de USB kabels. Die heb ik nog allemaal liggen uit het USB-printer-tijdperk van de eerste HP printers. Die hadden die vierkante usb stekkers.

[Voor 8% gewijzigd door Sircuri op 04-09-2017 21:58. Reden: usb kabels]

Signature van nature


Acties:
  • +1Henk 'm!

  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
edja schreef op woensdag 30 mei 2018 @ 10:16:
Sicuri,

Op 28 mei schreef je:

"Mocht USB werken, dan wil ik best iets voor je proberen in elkaar te zetten, maar dan kan ik je geen enkele garantie/ondersteuning garanderen."

Ik snap dat je geen garantie kan geven maar ik wil het graag proberen!

Eddie
Zie PM

Signature van nature


Acties:
  • +1Henk 'm!

  • zonoskar
  • Registratie: januari 2000
  • Laatst online: 23:18

zonoskar

<-- Mika R.I.P!

Ik heb een omweg gevonden voor mijn USB probleem. Ik heb mijn USB kabel doorgeknipt en er een relais tussen gezet. Met het relais uitgeschakeld ziet de Goodwe niet dat er een PC aan hangt (PC ziet Goodwe ook niet, maar goed). Dus als ik nu voordat ik de USB poort init eerst even het relais aan schakel, dan zou ik de inverter moeten zien. Zo niet, dan schakel ik het relais weer af en wacht even tot ik weer probeer. Ik heb vandaag even handmatig geprobeerd en het lijkt er op dat het ook niet zo uitmaakt of ik de USB even inschakel als de omvormer aan het opstarten is. Dus dit moet gaan werken. Nu nog "even" het script ombutsen :)

Powermac G5 casemod. Mijn PV live output.


  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
Wat betreft de USB kabels kan ik je niks over zeggen. Dat heeft ook weinig met de GoodWe omvormer te maken, maar meer met USB kabels ;)

Dat python script van mij dropt zijn berichten gewoon op een MQTT service. Elke tool kan het daar vanaf halen. Ook Domoticz ondersteunt dit. Dat heb ik voor @edja gedaan eerder vorig jaar. Volgens mij draait het bij hem nog steeds op die manier.

Signature van nature


Acties:
  • +1Henk 'm!

  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
@ricvee en @royke als jullie nu eerst even in GoodWe.py de DEBUG log aanpassen zodat deze je serial nummer ook logt, dan weet je in ieder geval of je data krijgt op een MQTT channel.

Heb ondertussen de laatste versie van de tool op Github gezet, dus daar kun je zien wat ik bedoel met die log aanpassing.

[Voor 25% gewijzigd door Sircuri op 11-06-2019 19:05]

Signature van nature


Acties:
  • +1Henk 'm!

  • royke
  • Registratie: oktober 2000
  • Laatst online: 26-07 21:27

royke

aan het typen....

dag Ik heb je nieuwe versie binnengehaald.
Hierin is eea angepast.
Maar loglevel aanpassen in de GoodWe.py snap ik niet. wel aangepast in de /etc/goodwe/goodwe.conf (in je nieuwe py bestand kijkt hij naar /etc/goodwe.conf.
Maar nu komt er geen data meer binnen :(

Dit heb ik uit de logs gehaald:

2019-06-11 21:45:20,626 handleRegistration(421) - INFO: New inverter found. Register address.
2019-06-11 21:45:20,829 handleRegistrationConfirmation(449) - INFO: Inverter now online.
2019-06-11 21:45:21,735 run(82) - ERROR: Error in RUN-loop
Traceback (most recent call last):
File "./GoodWe.py", line 58, in run
self.gw.handle()
File "/home/pi/GoodWeUSBLogger/GoodWeCommunicator.py", line 667, in handle
self.checkIncomingData()
File "/home/pi/GoodWeUSBLogger/GoodWeCommunicator.py", line 348, in checkIncomingData
self.inputBuffer[self.curReceivePtr] = incomingData
IndexError: list assignment index out of range
2019-06-11 23:16:23,288 run(49) - INFO: Connected to MQTT 192.168.1.246
2019-06-11 23:16:24,030 run(49) - INFO: Connected to MQTT 192.168.1.246
2019-06-11 23:16:27,298 run(49) - INFO: Connected to MQTT 192.168.1.246
2019-06-11 23:16:35,670 run(49) - INFO: Connected to MQTT 192.168.1.246
2019-06-11 23:16:39,171 run(49) - INFO: Connected to MQTT 192.168.1.246
2019-06-11 23:16:43,631 run(49) - INFO: Connected to MQTT 192.168.1.246
2019-06-11 23:16:45,704 run(49) - INFO: Connected to MQTT 192.168.1.246

In je nieuwe opzet gebruik je als werk dir /opt ipv de home directory. Ik ga morgen even opnieuw alles binnenhalen en opzetten volgens je nieuwe opzet.
Alvast bedankt.

Ik vind van niet......


  • NetXtreme
  • Registratie: mei 2003
  • Laatst online: 04-08 05:45
LJed schreef op vrijdag 1 december 2017 @ 12:46:
Hmm, dan heeft jouw goodwe een andere interface denk ik.
Achter mijn wifi-dongle zit de volgende print.
[Afbeelding]
Heeft iemand een idee wat voor type stekker ik hier voor nodig heb om hier een kabel in te pluggen?

Acties:
  • +1Henk 'm!

  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
Het veld EDAY loopt gedurende de dag op en wordt inderdaad de volgende dag gereset als de omvormer weer opstart bij de eerste zonnestralen. Met PAC alleen ga je geen totale opbrengst kunnen vinden. PAC is enkel de huidige wattage die je panelen opwekken.
Naast EDAY heb je ook nog de ETOT waarde. Dit is de totale opbrengst van je omvormen tot nu toe. Deze wordt ook niet gereset. Ik zelf gebruik de waarde uit ETOT om de dag standen te berekenen. Hiermee los je het probleem op dat je geen dagstand hebt als onverhoopt een keer je geen meterstanden op een dag hebt. (regelmatig gehad, omdat mijn Raspberry zichzelf had opgehangen en geen nieuwe standen meer uitlas)

Signature van nature


Acties:
  • +2Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Sircuri schreef op donderdag 7 mei 2020 @ 21:37:
@FrankJ91 - @ThinkPad bedoelt dat je de kast wellicht open moet maken om te kijken waar die USB poort naartoe gaat. Wellicht zit er achter die USB poort een RS485 connector (meestal groen) en dan kan je de code van jantenhove gebruiken.
Zeker niet! :o Bij mij is de behuizing van de omvormer verzegeld. Bij het openmaken moet ik die zegel verbreken en ben ik de sjaak met garantie denk ik? In mijn geval kon ik de standaard WiFi-module demonteren en kwam daar toen USB en RS485 tevoorschijn. Helaas blijkt dat bij @FrankJ91 niet zo te zijn :-(

[Voor 3% gewijzigd door ThinkPad op 07-05-2020 21:43]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • FrankJ91
  • Registratie: september 2010
  • Laatst online: 04-08 10:21
Inderdaad, deze is ook verzegeld. Ik ga hem dan ook maar niet openmaken, zeker niet de eerste dag ivm garantie etc. Hopelijk dat ik hiermee meer mensen heb geadviseerd die ook naar deze omvormer kijken :)

Net de omvormer in de SemsPortal gezet en ben bezig deze nu maar te verbinden met Home Assistant. Lijkt goed te gaan. Daarna maar even in Grafana krijgen. Helaas dat het via de cloud moet lopen waardoor ik denk ik minder makkelijk accuraat verbruik in Grafana neer kan zetten (P1/Omvormer data). Maarja het is niet anders.

Bedankt in ieder geval! :)

Acties:
  • +1Henk 'm!

  • Sircuri
  • Registratie: oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Topicstarter
In mijn allereerste poging om de data te capturen van de omvormer (toen ik nog geen inzicht had op de USB poort) heb ik het verkeer naar de GoodWe servers binnen mijn netwerk omgeleid naar een eigen http server en zo de data uitgelezen. Via DNS / hosts-file elk verzoek naar de goodwe server laten resolven naar een intern ip adres.

Signature van nature


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

Ik heb ook een XS inverter en was al een tijdje aan het zoeken naar een betekenis in het TCP protocol dat ik voorbij zie komen als de inverter communiceert met de SEMS pagina.

Het is TCP 20001 op tcp.goodwe-power.com en ik herken het serienummer erin.
In een issue op de github pagina van @CodeIT zag ik dat iemand de USB poort na was gelopen en dat deze zeker NIET als USB poort gebruikt moet worden (polarisatie omgedraaid!) maar een RS232 poort is 'in disguise'

Met een logic analyser aan de RS232/USB poort zie ik wat AT commando's tussen de inverter en de wifi module, uiteindelijk zet de inverter de wifi module in 'transparent transmission' en de output wordt dan direct door de servers van Goodwe geïnterpreteerd.

De TCP packets zijn dus 1-op-1 de serial output van de inverter.

Mocht iemand suggesties hebben: https://github.com/jantenhove/GoodWeLogger/issues/28

Ik zie wel mogelijkheden de HF-LPB100 te vervangen met een ESP (Geen onnodig SSID meer van de 'setup' modus waar hij niet uit wil), maar dan kan ik hem nog niet lokaal lezen/interpreteren :)

Acties:
  • +1Henk 'm!
  • Pinned

  • brainball
  • Registratie: juni 2001
  • Laatst online: 25-06 09:22
Ik heb een GoodWe GW4000-DT hangen met de wifi module HF-LPB100.

GoodWe heeft daar een aangepaste webpagina ingezet die een hoop configuratie opties verstopt. Dit kan je omzijlen door de standaard webpagina erin te laden. :)

Het aanpassen van de webpagina is simpel maar kan impact op je garantie hebben.

Op de website van de leverancier kan je onder downloads de firmware voor de module vinden (http://www.hi-flying.com/hf-lpb100) een van de bestanden in de rar file in de folder webpage is de standaard webpagina configuratie. Deze kan je via de pagina IPADRESS/iweb.html uploaden.

Nadat je dit gedaan hebt krijg je de volledige configuratie te zien en kan je onderandere het standaard wifi netwerk uitzetten maar ook de waarnaar hij de data stuurt aanpassen. Zodat dit naar een eigen data server kan.

  • brainball
  • Registratie: juni 2001
  • Laatst online: 25-06 09:22
Lardman schreef op vrijdag 15 januari 2021 @ 17:44:
Ik heb hier een XS1500 met een nukkige WiFi die zijn AP niet meer uit zet als er verbinding is met het thuisnetwerk. De NS serie deed dit altijd wel, de XS serie daarintegen.... Zou dezelfde truuk die jij gebruikt hebt @brainball bij mij ook kunnen werken ?
als je hetzelfde type/serie wifi module hebt wel, belangrijk is wel om zeker te stellen dat je dezelfde wifi module in je omvormer hebt zitten. In mijn geval gaf mijn asus router de model naam weer van de wifi module bij de clients waardoor ik het zeker wist. Je kan ook op basis van het mac address op een site als https://uic.win/en/mac/ checken of het inderdaad een hi-flying wifi module is.

De webpage file lijkt voor de verschillende wifi modules van hi-flying hetzelfde te zijn.

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
@dirksenrdh Wat mij betreft mag dat gewoon hier op Tweakers gedeeld worden hoor, hoeft niet via DM.
Staat het gelijk veiliggesteld voor de toekomst.

[Voor 63% gewijzigd door ThinkPad op 01-02-2021 16:51]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

Ik ben met mijn XS inverter (nog) niet verder gekomen. De binaire blob heb ik niet kunnen correleren aan de hex waarden van mijn omvormer helaas.
@Robindd Voor welk type inverter was die registermap?
@ThinkPad Bedankt voor de ping! Helaas ging het blog artikel waar je op Github naar verwees niet om dezelfde omvormer.

  • geerttttt
  • Registratie: oktober 2006
  • Laatst online: 04-08 10:20

geerttttt

Manisch positief

ThinkPad schreef op vrijdag 5 februari 2021 @ 16:03:
[...]

Die mogelijkheid heeft Tweakers niet, maar screenshots kan wel. Of je moet het ding extern even ergens neerzetten en linkje plaatsen.



@No13 Ik heb inmiddels ook een GW3000-XS (ik werd met het thuiswerken gek van het geklik-klak van mijn 3000NS rond schemering of bij slecht weer, zou met de XS-serie stukken beter moeten zijn) dus kan je meehelpen met uitpluizen. Maar ik stel voor dat we dat via het Github issue laten lopen zodat ook Engelse lezers er wat aan hebben/mee kunnen helpen.

Ben ondertussen ook nog steeds benieuwd naar het script van @geerttttt, want ik begrijp dat hij het al een aantal jaren werkend heeft. Volgens mij is dat feitelijk dit verhaal, maar bij dat blog mist eigenlijk het vervolg waarmee je de data ook daadwerkelijk logt. @geerttttt Zou je alsjeblieft jouw script ergens online willen zetten? Zou je mij en vast vele anderen heel blij mee maken _/-\o_
Kan ik je voorlopig blij maken met een deel van het script wat ik zo kan pasten zonder dat er persoonlijke data van mij in zit?
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo "Vpv1: ".(hexdec(substr($file, 0, 4))/10)."|";
echo "Vpv2: ".(hexdec(substr($file, 4, 4))/10)."| ";
echo "Ipv1: ".(hexdec(substr($file, 8, 4))/10)." | ";
echo "Ipv2: ".(hexdec(substr($file, 12, 4))/10)." | ";
echo "cur: ".hexdec(substr($file, 28, 4))." | "; #curr usage
echo "Etotal: ".(hexdec(substr($file, 40, 16))/10)." | ";
//echo hexdec(substr($file, 56, 8))." | ";
echo "Etoday: ".(hexdec(substr($file, 88, 4))/10)." | ";
echo "Vac: ".(hexdec(substr($file, 16, 4))/10)." | ";
echo "Iac: ".(hexdec(substr($file, 20, 4))/10)." | ";
echo "Fac: ".(hexdec(substr($file, 24, 4))/100)." | ";
echo "Temp: ".(hexdec(substr($file, 36, 4))/10)." | ";
echo "Htotal: ".(hexdec(substr($file, 56, 8)))." | ";
echo "?: ".(hexdec(substr($file, 80, 4)))." | ";
echo "Generating: ".(hexdec(substr($file, 34, 2)))." | "; # Generating or waiting


PHP dus, je vangt de body op en zoals je ziet pak ik gewoon een klein stukje ervan elke keer en zet ik het om naar decimaal.

Ik ben zelf momenteel druk om op een of andere manier mijn wifi module weer werkend te krijgen. Als iemand mij een werkende firmware kan geven dan maak ik instant een compleet script 8)

Oost west, 127.0.0.1 best!


Acties:
  • +1Henk 'm!
  • Pinned

  • geerttttt
  • Registratie: oktober 2006
  • Laatst online: 04-08 10:20

geerttttt

Manisch positief

Belofte maakt schuld. Hierbij het script wat ik gebruik. Je moet de www.goodwe-power.com dns naam uiteraard omzetten naar je eigen webserver. Vervolgens een .htaccess aanmaken met dit:

code:
1
2
3
4
5
6
7
8
RewriteEngine on
RewriteBase /

# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s 

# pass the rest of the request into index.php to handle     
RewriteRule ^Acceptor/(.*)$ /Goodwe/logger.php/$1 [L]


Vervolgens het logger.php script:
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
<?php
$filename = './dumprequest'.time().'.txt';
$file = file_get_contents('php://input');

//strip useless data
$file = substr($file, 20);
if ($file != "") {
    //echo date("d-m H:i:s", substr($filename,11, -4))." - ";
    //strip useless data
    $file = substr($file, 0, -5);
    $file = bin2hex($file);
    /*echo $file;
    echo "-";
    echo "Vpv1: ".(hexdec(substr($file, 0, 4))/10)."|";
    echo "Vpv2: ".(hexdec(substr($file, 4, 4))/10)."| ";
    echo "Ipv1: ".(hexdec(substr($file, 8, 4))/10)." | ";
    echo "Ipv2: ".(hexdec(substr($file, 12, 4))/10)." | ";
    echo "cur: ".hexdec(substr($file, 28, 4))." | "; #curr usage
    echo "Etotal: ".(hexdec(substr($file, 40, 16))/10)." | "; #eTotal :)
    //echo hexdec(substr($file, 56, 8))." | ";
    echo "Etoday: ".(hexdec(substr($file, 88, 4))/10)." | "; #eToday
    echo "Vac: ".(hexdec(substr($file, 16, 4))/10)." | ";
    echo "Iac: ".(hexdec(substr($file, 20, 4))/10)." | ";
    echo "Fac: ".(hexdec(substr($file, 24, 4))/100)." | ";
    echo "Temp: ".(hexdec(substr($file, 36, 4))/10)." | ";
    echo "Htotal: ".(hexdec(substr($file, 56, 8)))." | ";
    echo "?: ".(hexdec(substr($file, 80, 4)))." | ";
    echo "Generating: ".(hexdec(substr($file, 34, 2)))." | "; # Generating or waiting
    echo "\n";*/
    mysql_query("INSERT INTO `zonnepanelen` (`date`, `vpv1`, `vpv2`, `ipv1`, `ipv2`, `cur`, `etotal`, `etoday`, `vac`, `iac`, `fac`, `temp`, `htotal`, `generating`, `raw`)
    VALUES
        (NOW(),
        '".(hexdec(substr($file, 0, 4))/10)."',
        '".(hexdec(substr($file, 4, 4))/10)."',
        '".(hexdec(substr($file, 8, 4))/10)."',
        '".(hexdec(substr($file, 12, 4))/10)."',
        '".hexdec(substr($file, 28, 4))."',
        '".(hexdec(substr($file, 40, 16))/10)."',
        '".(hexdec(substr($file, 88, 4))/10)."',
        '".(hexdec(substr($file, 16, 4))/10)."',
        '".(hexdec(substr($file, 20, 4))/10)."',
        '".(hexdec(substr($file, 24, 4))/100)."',
        '".(hexdec(substr($file, 36, 4))/10)."',
        '".(hexdec(substr($file, 56, 8)))."',
        '".(hexdec(substr($file, 34, 2)))."',
        'Url: ".$_SERVER['REQUEST_URI']." - ".$file."');
    ");
    if(date('i')%5==0){
        $data = [];
        $data["d"] = date("Ymd"); //yyyymmdd
        $data["t"] = date("H:i"); //hh:mm
        $data["v1"] = (hexdec(substr($file, 88, 4))*100); // watt hours
        $data["v2"] = hexdec(substr($file, 28, 4)); // watt
        $data["v6"] = ((hexdec(substr($file, 0, 4))/10)+(hexdec(substr($file, 4, 4))/10));  // voltage
        $data["v5"] = (hexdec(substr($file, 36, 4))/10); // degrees
        $headers = "Content-type: application/x-www-form-urlencoded\r\n";
        $headers .= "X-Pvoutput-Apikey: PVOUTPUTAPIKEYHIER\r\n";
        $headers .= "X-Pvoutput-SystemId: SYSTEMIDHIER\r\n";
        $options = [
            "http" => [
                "header" => $headers,
                "method" => "POST",
                "content" => http_build_query($data)
            ]
        ];
        $context = stream_context_create($options);
        $output = file_get_contents("http://pvoutput.org/service/r2/addstatus.jsp", false, $context);
    }
}


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,            "http://goodwe-power.com".$_SERVER['REQUEST_URI'] );
//curl_setopt($ch, CURLOPT_URL,            "http://goodwe-power.com/Acceptor/DataCRC" );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_POST,           1 );
curl_setopt($ch, CURLOPT_POSTFIELDS,     file_get_contents('php://input'));
curl_setopt($ch, CURLOPT_HTTPHEADER,     array('Connection: Close'));

$result=curl_exec ($ch);
curl_close($ch);
//$result = substr($result, 0, -6);
//                                              Extra sec ?? (0xaa)   eindkarakter?
//$result = $result.chr(0x00).chr(0x00).chr(0x01).chr(0xFF).chr(0xaa).chr(0x00);
if ($_SERVER['REQUEST_URI'] == "/Acceptor/GetSendInterval") {
    file_put_contents($filename, file_get_contents('php://input')."\n\nreturn: ".$result);
}
print_r($result);

In mijn geval stuur ik het naar mijn mysql server en naar pvoutput.org. Doe hiermee wat je zelf wilt natuurlijk ;)

[Voor 1% gewijzigd door ThinkPad op 06-02-2021 15:17. Reden: syntax-highlighting op code :)]

Oost west, 127.0.0.1 best!


Acties:
  • +3Henk 'm!
  • Pinned

  • dirksenrdh
  • Registratie: oktober 2017
  • Laatst online: 21-06 11:05
Ik ben inmiddels wel veel verder gekomen met mijn GW8K-dt
bij Alie een HF2211 RS485 naar Wifi en ethernet converter gekocht. Die is net binnen.
De ontbrekende connectoren voor de omvormer zijn van ExceedConn (EP-serie)
Verder had ik de basale python programmatuur al voorbereid, en wonder boven wonder werkte het in één keer.
Dus ik heb nu én de wifi adapter van Goodwe in de "USB" connector zitten en die stuurt elke x minuten een update naar de SEMS portal zodat mijn pv leverancier de installatie vanuit zijn kant kan monitoren.
Én ik heb de rs485 koppeling operationeel zodat ik elke seconde mijn raspberry Pi met Domotics de actuele waarden kan laten uitlezen.
De Python software is nog niet in een stadium dat het de delen valt maar er is wel progressie.

plans without actions are dreams


  • appieroos
  • Registratie: januari 2013
  • Laatst online: 14-05 19:10
Goedendag, afgelopen vrijdag is onder garantie mijn omnik omvormer door een GW2000-XS vervangen. Maar mijn omvormer send ook op de 20001 port data inplaats van port 80 terwijl ik begrepen had dat alles na 2019 nu via poort 80 zou moeten gaan. Ik heb firmware V1.12.13 en vroeg me af of ik door het updaten van mijn firmware naar de oplossing via port 80 van geert kan komen. Ik ga mijzelf verdiepen in het datablok of ik hier patronen/waardes uit kan halen maar begreep dat nog niemand dit hier gedaan/gelukt is.
Hopelijk gaat dit lukken.

[Voor 0% gewijzigd door appieroos op 18-02-2021 15:03. Reden: Firmware versie was verkeerd.]


  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Robindd schreef op donderdag 18 februari 2021 @ 13:26:
[...]


Heel nice! Ik probeer het via Node Red te doen via een RS485 -> USB adapter ook. Heb een andere adapter besteld omdat 2 aparaten in die adapter nog niet helemaal lekker werkte.
Ik heb bij de Goodwe wel het nadeel gevonden dat er niets meer binnen komt om het moment dat die uit staat. Je gaat dus ineens van opbrengst naar niets en daarmee errors. Moet ik nog eens aan gaan werken. Het is jammer dat je de status dus niet meer kan opvragen op het moment dat hij uit staat, anders zou je kunnen zeggen -> status = off dan alles is 0 of iets in die richting..
Wat ik bij het gw2pvo script (die scraped de portal, niet meest wenselijke optie) zie is dat je een locatie meegeeft. Het script weet dan hoe laat de zon opkomt en ondergaat. Buiten dat window wordt het scrapen gepauzeerd. Zoiets zou ik in jouw geval ook in Node-RED toevoegen, genoeg astro/scheduler modules. Heb zelf node-red-contrib-schedex wel eens gebruikt om verlichting aan te laten gaan bij zonsondergang.


@appieroos Welkom. Het updaten van de firmware van de wifi-module zal geen verschil maken. Er is al door @No13 uitgepluisd dat de data in de omvormer zelf al versleuteld wordt. De wifi-module is niets meer dan een 1:1 doorgeefluik.

[Voor 16% gewijzigd door ThinkPad op 18-02-2021 15:09]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


  • appieroos
  • Registratie: januari 2013
  • Laatst online: 14-05 19:10
Goedendag, had het misschien wat duidelijker moeten zeggen, maar dit is de firmware versie van de omvormer en dus niet van de wifi module welke blijkbaar een serieel naar tcp 1 op 1 omzetter is.

  • Aiolos
  • Registratie: januari 2002
  • Niet online
inTIMidate schreef op woensdag 28 april 2021 @ 14:07:
Ik overweeg ook Goodwe omvormers, zijn er modellen die RS485 hebben samen met wifi? Want dan kan ik dat door geven aan de installateur.
Ik heb een XS2000 en XS2500 die beide RS485 hebben, en ook tegelijkertijd via WiFi verbonden zijn. @ThinkPad heeft ook een XS geloof ik, maar die heeft dan weer geen RS485. Ergens zit er dus een verschil tussen sommige versies...

Stuur me een PM voor Wemos D1 shields voor het uitlezen van slimme meters of het aansturen van Itho mechanische ventilatie (of kijk op V&A: https://tweakers.net/aanbod/user/47321/)


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Ik heb aan de praat en kan zowel aan de AP als aan de STA kant de gegevens uitlezen. De broadcast haalt het IP address van de omvormer op en leest dan de waardes.

Het script is nog niet gereed en ik moet nog twee dingen oplossen voordat ik het hier kan plaatsen.

De huidige opmerkingen;

# Read the production of a Goodwe inverter. Retrieved data can be stored in a log file with at the end of the line the time of retrieval.
# The name of the log file is the date in YYMMDD format and is unique. Each retrieved hex string has its own line.
# To retrieve data through IP needs a ARM firmware of 13 or higher. The last part of firmware is stating for ARM "1.51.14" so here 14.

# This script needs SFK to run (http://www.stahlworks.com/dev/swiss-file-knife.html)

# to-do naming the cummulative log file with the current date as name and retrieve the last log line or store the string in a variable

Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Een XS met een versie lager dan 13 kon het niet uitlezen en de mijne heeft versie 14 en kan dat wel. Nu is het verkrijgen van een update niet eenvoudig via Goodwe omdat ze hier meer zeer terughoudend zijn, dit heb ik van anderen gehoord. Het is meer de opstelling, "don't fix it, if it is not broken".

Zelf gaan updaten mocht, je zelf een update vinden, kan ik alleen maar AFRADEN.

Dit lokaal via netwerk benaderen is waarschijnlijk beschikbaar gekomen, eind 2020, sinds er een LTE+Bluetooth stick is uitgebracht voor de Goodwe omvormers, en die benodigd versie 13 of hoger.

Teaser:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@raspberrypi:/opt/goodwe# ./show.sh

Read and collect data from Goodwe inverter

Do broadcast to find the Goodwe inverter:
  SSID: Solar-WiFi20CWxxxx
  IP addr: 192.168.xxx.xxx

Value read at 11:02:07:
  Vpv:    290.1 V
  Ipv:    2.6 A
  Vac:    231.0 V
  Iac:    3.3 A
  Fac:    50.00 Hz
  Power:  0.75 kW
  Eday:   1.4 kWh
  Etotal: 33.5 kWh


En ik maar zoeken in de HEX string naar de Power waarde....is het een calculeerde waarde van de Vpv*Ipv/1000 :o

[Voor 30% gewijzigd door msatter op 03-05-2021 11:06]


Acties:
  • +3Henk 'm!
  • Pinned

  • msatter
  • Registratie: maart 2021
  • Niet online
Hierbij het script welke SFK nodig heeft om te kunnen werken.

Er worden twee bestanden gebruikt om de gegevens op te slaan, goodwe.info die het antwoord van de broadcast bevat en hex.txt die de ontvangen HEX string bevat van met waardes. Hex.txt is tijdelijk en zal vervangen worden door log bestanden.

Bash:
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
#!/usr/bin/env bash

# Read the production of a Goodwe inverter and the retrieved data can be stored in a log file. At the end of the stored line time of retrieval.
# The name of the log file is the date in YYMMDD format and is this way unique. Each retrieved hex string has it's own line with a timestamp at the end.
# To retrieve data through IP needs a ARM firmware of 13 or higher. The last part of my firmware is stating for ARM "1.51.14" so 14 number for the ARM.

# This script needs SFK to run (http://www.stahlworks.com/dev/swiss-file-knife.html) 

# to-do: config file for storing the location logfile and cron.

sfk echo ""
sfk echo "Read and collect data from Goodwe inverter"
sfk echo "" 
sfk echo "Do broadcast to find the Goodwe inverter:"
sfk cudp -broad 255.255.255.255 48899 -listen -noerror -timeout=500 0x574946494b49542d3231343032382d52454144 -flat > goodwe.info
sfk echo -pure "  SSID: " +xfind goodwe.info "/**,**,//"
sfk echo -pure "  IP addr: " +xfind goodwe.info "/,**//"

sfk xfind goodwe.info "/,**//" +setvar ipa +cudp -var "#(ipa)" 8899 -listen -noerror -timeout=500 0x7f0375940049d5c2 -pure +xed "/[eol]//" +time " hms" >> ./`date +%Y`/`date +%Y%m%d`.log

# Check if the directory exists and if not create it.
sfk ifnotexist .`date +%Y`\*.log  mkdir `date +%Y`

# Show the values stored in the log file
echo ""  
sfk sel -since today *.log +hexfile -offlen -7 6 -flat -nofile +setvar logtime +echo -var "Log time: #(logtime)"
sfk echo "" 
sfk time "Current value at h:m:s:"

sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -292 4 -flat -nofile   +dec +calc "#text*0.1"  -dig=1  +setvar vpv +echo -var     "  Vpv:      #(vpv) V"
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -288 4 -flat -nofile   +dec +calc "#text*0.1"  -dig=1  +setvar ipv +echo -var     "  Ipv:      #(ipv) A "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -232 4 -flat -nofile   +dec +calc "#text*0.1"  -dig=1  +setvar vac +echo -var     "  Vac:      #(vac) V "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -208 4 -flat -nofile   +dec +calc "#text*0.01" -dig=2  +setvar fac +echo -var     "  Fac:      #(fac) Hz "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -292 4 -flat -nofile +dec +setvar vpv +sel -since today ./`date +%Y`/*.log +hexfile -offlen -288 4 -flat -nofile +dec +setvar ipv +echo -var "#(vpv)*#(ipv)/100000" +calc "#text" -dig=2 +setvar power +echo -var    "  Power: #(power) kW "
#sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -232 4 -flat -nofile +dec +setvar vac +sel -since today ./`date +%Y`/*.log +hexfile -offlen -220 4 -flat -nofile +dec +setvar iac +echo -var "#(vac)*#(iac)/100000" +calc "#text" -dig=2 +setvar power +echo -var    "  PowerAC:  #(power) kW "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -140 4 -flat -nofile   +dec +calc "#text*0.1"  -dig=1  +setvar temp +echo -var    "  Temperature:  #(temp) celcius "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -128 4 -flat -nofile   +dec +calc "#text*0.1"  -dig=1  +setvar eday +echo -var    "  Eday:     #(eday) kWh "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -120 4 -flat -nofile   +dec +calc "#text*0.1"  -dig=1  +setvar etotal +echo -var  "  Etotal:   #(etotal) kWh "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -112 4 -flat -nofile   +dec +calc "#text*1.0"  -dig=0  +setvar work +echo -var    "  Totalruntime: #(work) hours "
sfk sel -since today ./`date +%Y`/*.log +hexfile -offlen -16  4 -flat -nofile   +dec +calc "#text*1.0"  -dig=0  +setvar rssi +echo -var    "  WiFi Signal:  #(rssi) %"


Ik kan nu eenvoudig de laatste waarden uit een log bestand lezen en het was eenvoudiger dan ik dacht. En ik had een tijdelijk bestand aangemaakt maar de methode kon ik ook direct toepassen.

De bijgewerkte lijst met de gevonden waardes door Tinkpad:

code:
1
2
3
4
5
6
7
8
9
10
11
12
Value read at 13:09:29:
  Vpv:          268.5 V
  Ipv:          1.3 A
  Vac:          229.4 V
  Iac:          1.8 A
  Fac:          49.96 Hz
  Power:        0.35 kW
  Temperature:  28.6 celcius
  Eday:         2.7 kWh
  Etotal:       42.0 kWh
  Tot. runtime: 86 hours
  WiFi Signal:  52 %


De temperatuur is ook een belangrijke waarde. Als alles erg warm wordt dan werkt alles minder en dan is het tijd om de koeling van de omvormer te bekijken.

Update.
Als er geen gevens terugkomen van fe omvormer dan gaat er ook niets naar het log. Lost ook meteen de offline zijn van de omvormer als er geen zon is.

Naast de bestandsnaam met de datum het kan ook de directory zelf een de naam van de omvormer hebben en zo kun je verschillende omvormers apart houden. Dit voor mensen zelf meer dan één omvormer hebben.

Update:
Script aangepast om de log bestanden een sub-dir te plaatsen met als naam het huidige jaar.

[Voor 36% gewijzigd door msatter op 05-05-2021 13:36. Reden: De door Thinkpad gevonden waardes toegevoegt]


Acties:
  • +6Henk 'm!
  • Pinned

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Nadat ik de firmware heb laten bijwerken door Goodwe en ik de omvormer kon uitlezen met de SolarGo app, heb ik met bovenstaande code als basis het aan de praat gekregen om de omvormer (3000XS) via Node-RED uit te lezen:


Ik stuur een hex string naar de omvormer, waarop hij reageert en de data terugstuurt. In Node-RED haal ik uit de ontvangen hexstring de waardes en zet deze om naar variabelen:


De flow in Node-RED:
code:
1
[{"id":"1114148f.9e4e3b","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"901d892e.0b27e","type":"function","z":"1114148f.9e4e3b","name":"","func":"var inverter_reply = msg.payload;\n\nvar year = \"20\" + inverter_reply.readInt8(5); // \nvar month = inverter_reply.readInt8(6); // \nvar day = inverter_reply.readInt8(7); // \nvar hour = inverter_reply.readInt8(8); // \nvar minutes = inverter_reply.readInt8(9); // \nvar seconds = inverter_reply.readInt8(10); // \n\nvar timestamp = hour+\":\"+minutes+\":\"+seconds+\" \"+day+\"-\"+month+\"-\"+year;\n\n\nvar vpv = parseFloat((inverter_reply.readInt16BE(11)*0.1).toFixed(1)); // Vpv\nvar ipv = parseFloat((inverter_reply.readInt16BE(13)*0.1).toFixed(1)); // Ipv\nvar vac = parseFloat((inverter_reply.readInt16BE(41)*0.1).toFixed(1)); // Vac\nvar iac = parseFloat((inverter_reply.readInt16BE(47)*0.1).toFixed(1)); // Iac\nvar fac = parseFloat((inverter_reply.readInt16BE(53)*0.01).toFixed(2)); // Fac\nvar dc_power = parseFloat(((vpv*ipv)).toFixed(0)); \nvar ac_power = parseFloat(((vac*iac)).toFixed(0));\nvar eday = parseFloat((inverter_reply.readInt16BE(93)*0.1).toFixed(1)); // Eday\nvar etotal = parseFloat((inverter_reply.readInt16BE(97)*0.1).toFixed(2)); // Etotal\nvar rssi = inverter_reply.readInt16BE(149); // wifi signal strength?\nvar workhours = inverter_reply.readInt16BE(101); // work hours inverter\nvar temperature = parseFloat((inverter_reply.readInt16BE(87)*0.1).toFixed(1)); // Inverter temperature\nvar power = inverter_reply.readInt16BE(61); // power\nvar status = inverter_reply.readInt16BE(63); // \n\n\nvar workmode;\nswitch (status) {\n    case 0:\n        workmode = \"Wait Mode\"\n        break;\n    case 1:\n        workmode = \"Normal\"\n        break;\n    case 2:\n        workmode = \"Error\"\n        break;\n    case 4:\n        workmode = \"Check Mode\"\n        break;\n}\n\nmsg.payload = {\n    vpv,\n    ipv,\n    vac,\n    iac,\n    fac,\n    power,\n    eday,\n    etotal,\n    rssi,\n    workhours,\n    temperature,\n    workmode,\n    timestamp\n    \n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":320,"wires":[["3a0e034d.bce714"]]},{"id":"3a0e034d.bce714","type":"debug","z":"1114148f.9e4e3b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":320,"wires":[]},{"id":"1ea4603b.d6454","type":"udp in","z":"1114148f.9e4e3b","name":"","iface":"192.168.8.21","port":"8899","ipv":"udp4","multicast":"false","group":"192.168.8.21","datatype":"buffer","x":260,"y":320,"wires":[["901d892e.0b27e"]]},{"id":"80cdaee9.19bce8","type":"udp out","z":"1114148f.9e4e3b","name":"","addr":"192.168.6.15","iface":"","port":"8899","ipv":"udp4","outport":"8899","base64":false,"multicast":"false","x":750,"y":140,"wires":[]},{"id":"46c68558.f9e15c","type":"inject","z":"1114148f.9e4e3b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":280,"y":140,"wires":[["4a16c267.f83f14"]]},{"id":"4a16c267.f83f14","type":"function","z":"1114148f.9e4e3b","name":"","func":"var inverter_ask = Buffer.from(\"7F0375940049D5C2\",\"hex\");\n\nmsg.payload = inverter_ask;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":140,"wires":[["80cdaee9.19bce8"]]},{"id":"dae4530a.7c94c","type":"comment","z":"1114148f.9e4e3b","name":"Request inverter data","info":"","x":300,"y":100,"wires":[]},{"id":"cea711ef.0e5a68","type":"comment","z":"1114148f.9e4e3b","name":"Parse received data","info":"","x":290,"y":280,"wires":[]}]


De function node heb ik intussen al weer bijgewerkt, ik bereken nu de CRC en verwerk het bericht pas als deze klopt. Merkte namelijk dat ik heel soms een incompleet bericht binnenkreeg. Hierbij de meest recente inhoud van de function node:
JavaScript:
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
var inverter_reply = msg.payload;

var message = inverter_reply.slice(2); // Remove 'AA55' from start of message
var message = message.slice(0, -2); //Remove two CRC bytes from end of message

function crc16(buffer) {
    var crc = 0xFFFF;
    var odd;

    for (var i = 0; i < buffer.length; i++) {
        crc = crc ^ buffer[i];

        for (var j = 0; j < 8; j++) {
            odd = crc & 0x0001;
            crc = crc >> 1;
            if (odd) {
                crc = crc ^ 0xA001;
            }
        }
    }
    return crc.toString(16);
}

//Calculate CRC ourselves
var calculated_crc = crc16(message);

//Get CRC from inverter reply and un-reverse it
var reply_crc = inverter_reply.slice(-2).toString('hex');
var crc1 = reply_crc.slice(0, 2);
var crc2 = reply_crc.slice(-2);
var new_crc = crc2 + crc1;

if (new_crc == calculated_crc) {
    //var year = "20" + inverter_reply.readUInt8(5);
    var year = 2000 + inverter_reply.readUInt8(5); 
    var month = inverter_reply.readUInt8(6);
    var day = inverter_reply.readUInt8(7); 
    var hour = inverter_reply.readUInt8(8); 
    var minutes = inverter_reply.readUInt8(9); 
    var seconds = inverter_reply.readUInt8(10); 
    
    var minutes = (minutes < 10 ? '0' : '') + minutes;
    var seconds = (seconds < 10 ? '0' : '') + seconds;
    var timestamp = hour + ":" + minutes + ":" + seconds + "  " + day + "-" + month + "-" + year;

    //Putting '+' in front to make it a number instead of a string
    var vpv = +(inverter_reply.readUInt16BE(11) * 0.1).toFixed(1);
    var ipv = +(inverter_reply.readUInt16BE(13) * 0.1).toFixed(1);
    var vac = +(inverter_reply.readUInt16BE(41) * 0.1).toFixed(1);
    var iac = +(inverter_reply.readUInt16BE(47) * 0.1).toFixed(1);
    var fac = +(inverter_reply.readUInt16BE(53) * 0.01).toFixed(2);
    var eday = +(inverter_reply.readUInt16BE(93) * 0.1).toFixed(1);
    var etotal = +(inverter_reply.readUInt32BE(95) * 0.1).toFixed(1);
    var rssi = inverter_reply.readUInt16BE(149);
    var workhours = inverter_reply.readUInt32BE(99);
    var temperature = +(inverter_reply.readUInt16BE(87) * 0.1).toFixed(1);
    var power = inverter_reply.readUInt32BE(59);
    var status = inverter_reply.readUInt16BE(63);
    var workmode;

    switch (status) {
        case 0:
            workmode = "Waiting"
            break;
        case 1:
            workmode = "Normal"
            break;
        case 2:
            workmode = "Error"
            break;
        case 4:
            workmode = "Checking"
            break;
    }

    msg.payload = {
        vpv,
        ipv,
        vac,
        iac,
        fac,
        power,
        eday,
        etotal,
        rssi,
        workhours,
        temperature,
        status,
        workmode,
        timestamp
    }

    var nodestate = {
        text: workmode + ' - Power: ' + power + 'W - ' + timestamp,
    };
    node.status(nodestate);

    return msg;
}

[Voor 255% gewijzigd door ThinkPad op 06-07-2021 21:43]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Hier dan de eerste versie die logbestanden opslaat die later weer kunnen worden uitgelezen. Dit is alleen de opslag van de HEX string die van uit de Goodwe omvormer komt. Hier zit alle info in, ook als je een omvormer hebben met meer dan één string dan wordt ook de gegevens opgeslagen. Later kan dan uitgebreider uitgelezen worden.

De logger:

Bash:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env bash

# Script written by msatter and is free to us as long it is for non-commercial usage. 

# Read the production of a Goodwe inverter and the retrieved data can be stored in a log file. At the end of the stored line time of retrieval.
# The name of the log file is the date in YYMMDD format and is this way unique. Each retrieved hex string has it's own line with a timestamp at the end.
# To retrieve data through IP needs a ARM firmware of 13 or higher. The last part of my firmware is stating for ARM "1.51.14" so 14 number for the ARM.

# This script needs SFK to run (http://www.stahlworks.com/dev/swiss-file-knife.html) 

# to-do: config file for storing the location logfile and cron.

# Sent a broadcast to find the Goodwe inverter
sfk cudp -broad 255.255.255.255 48899 -listen -noerror -timeout=500 0x574946494b49542d3231343032382d52454144 -flat > goodwe.info

# Check if the directory exists and if not create it.
sfk ifnotexist .`date +%Y`\*.log  mkdir `date +%Y`

# Save the retrieved values as Hex string in the log. Path ./YEAR/YEARMONTHDAY.log and in the log, each line has it's own timestamp at the end of the line. 
sfk xfind goodwe.info "/,**//" +setvar ipa +cudp -var "#(ipa)" 8899 -listen -noerror -timeout=1500 0x7f0375940049d5c2 -pure +xed "/[eol]//" +xed "/*timeout*[eol]//" +time " hms"  +xed "/[eol]//" +xed "/*timeout*[eol]//" +time " hms" +xed "/[start][314 bytes]/[all]/" >> /opt/goodwe/`date +%Y`/`date +%Y%m%d`.log


Voorbeeld cron regel om elke minuut van de dag een logregel te schrijven. Als de omvormer niet aan is dan kan er ook niets geschreven worden.

code:
1
* * * * * PATH="$PATH:/opt/goodwe/" store-pv.sh #LogGoodwe PV


Update: script aangepast opdat timeouts ook niet geschreven worden.
Update2: de tijd werd niet meer geschreven en dit opgelost door [eol] door [lstart] te gebruiken.
Update3: nu gaat het aan de andere kant niet goed van de tijd en ik laat het weten als ik het heb opgelost.
Update4: ik krijg het niet zo opgelost. Ik heb nu het filter gedeactiveerd en laat dit zo totdat ik weet hoe het wel moet. Het werkt nu maar het gebeuren dat er nu lege regels in het log staan.
Update4: OK i.p.v. te kijken wat je niet wil, kijken wat je wel wil en het zou moeten werken. Helaas is het grote licht uit dus ik kan het pas morgen test. Soms zijn oplossingen eenvoudig, eenvoudige dan je zou denken.

[Voor 20% gewijzigd door msatter op 05-05-2021 22:01]


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

Ik heb bij goodwe ook een ticket aangemaakt, now we wait...

Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Proton_ schreef op woensdag 5 mei 2021 @ 15:13:
Ik ook, inverter is 1.03.09 (sept 2020).
@ThinkPad
Is er in de nieuwe firmware nog iets verbeterd qua solar-wifi-ssid?
Nee. Dat is weer een andere firmware, die van de wifi-module. Zie GoodWe GW3600 SSID broadcast uitzetten

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • wlmpie
  • Registratie: oktober 2007
  • Laatst online: 20:10
Begrijp ik nou goed dat het script van @msatter een goodwe xs omvormer lokaal kan uitlezen via de wifi? Mits je firmware eindigt op 13 of hoger? En dan hoef je dus niet te gaan klooien met RS485 of modbus?

Nou nog uitvinden hoe je die data dan in domoticz krijgt.

Acties:
  • +2Henk 'm!
  • Pinned

  • Pinobigbird
  • Registratie: januari 2002
  • Laatst online: 01:23

Pinobigbird

doesn't share food!

Ik heb de volgende waarde uit de response van m'n 3-fase GW5K-DT:
./sfk.exe cudp 192.168.1.11 8899 -listen -noerror -timeout=500 0x7f0375940049d5c2 -pure +xed "/[eol]//"

AA557F03921505070A02290B0B001E0C79001BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FD20FDE0FE10927091C0935001900190019138813851383000006D600010000000000000000000000000000000000000000FFFF0178FFFFFFFF002600000C08000000A800140000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001017F50C4000000000000002390095000400000031AAD9

Ik kom dan uit op deze waarden:
poslengtehexdecgrootheidwaardeeenheid
14AA 55170Header43605? - vaste waarde
527F127Response type127?- vaste waarde
720333?- vaste waarde
9292146146?- vaste waarde
1121521jaar2021Y
132055maand05M
152077dag07D
1720A10uur10h
192022minuut02m
2122941seconden41S
2340B 0B2827Vdc1282,7V
27400 1E30Idc13,0A
3140C 793193Vdc2319,3V
35400 1B27Idc22,7A
394FF FF65535
434FF FF65535
474FF FF65535
514FF FF65535
554FF FF65535
594FF FF65535
634FF FF65535
674FF FF65535
7140F D24050Vac1-2405,0V
7540F DE4062Vac2-3406,2V
7940F E14065Vac3-1406,5V
83409 272343Vac1234,3V
87409 1C2332Vac2233,2V
91409 352357Vac3235,7V
95400 1925Iac12,5A
99400 1925Iac22,5A
103400 1925Iac32,5A
107413 885000Fac150,00Hz
111413 854997Fac249,97Hz
115413 834995Fac349,95Hz
119400 000
123406 D61750Power1,750kW
127400 011Work modeNormal0: Wait Mode
1: Normal
2: Error
4: Check Mode
131400 000
135400 000
139400 000
143400 000
147400 000
151400 000
155400 000
159400 000
163400 000
167400 000
1714FF FF65535
175401 78376Temperature37,6°C
1794FF FF65535
1834FF FF65535
187400 2638Today generation3,8kWh
191800 00 0C 083080Total generation308,0kWh
199800 00 00 A8168Total hours168h
207400 1420Country safetyHolland(*)
211400 000
215400 000
219400 000
223400 000
2274FF FF65535
2314FF FF65535
2354FF FF65535
2394FF FF65535
2434FF FF65535
2474FF FF65535
2514FF FF65535
2554FF FF65535
259400 1016FunBit16
263417 F56133BusVolt6133
26740C 403136NBusVolt3136
271400 000
275400 000
279400 000
283402 39569569?- vaste waarde
287400 95149149?- vaste waarde
291400 0444?- vaste waarde
295400 000
299400 3149RSSI49%
3032AA D943737CRC-16 Modbus checksum in omgekeerde volgorde

@msatter Ik zie dus wél Power er tussen staan op positie 123, en de timestamp staat in het begin vanaf positie 11 met 2 hex-karakters per decimaal-karakter.

Positie 71 t/m 83 zijn volgens mij de spanningen tussen de drie fasen (iets meer dan 400V), maar dat is een gok.

Verder zie ik de waarden FunBit, BusVolt en NBusVolt terugkomen, die ik ook terugzie in SolarGo > More > Device maintenance > Debugging information.

edit:
Waarden van Total generation en Total hours van 4 naar 8 karakters. Wellicht ook nodig voor Power.

edit:
Laatste 4 cijfers als checksum

edit:
09-05-2021 22:40 Work mode en Country safety, (*) volgens https://github.com/mleten...we/goodwe_inverter.py#L70.

edit:
11-05-2021 18:05 AA55 als header. Checksum toelichting.

[Voor 4% gewijzigd door Pinobigbird op 11-05-2021 18:05]

Joey: Nice try. See the Netherlands is this make believe place where Peter Pan and Tinkerbell come from.
https://kattenoppasleiderdorp.nl
PV: 3080Wp ZO + 3465Wp NW = 6545Wp totaal 13°tilt


Acties:
  • +1Henk 'm!

  • jfinkers
  • Registratie: februari 2012
  • Laatst online: 17:28
Hi,

Ik lees dit forum nu met veel interesse mee.
Voor zover ik zie werken de exports nu vooral op de XS en 5K versies.
Ook al iemand die een D-NS versie werkend heeft?
(Zelf heb ik een GW4200D-NS V1.14.13 waar SolarGo helaas (nog) niet mee compatible is.)

Acties:
  • +1Henk 'm!

  • Pinobigbird
  • Registratie: januari 2002
  • Laatst online: 01:23

Pinobigbird

doesn't share food!

ThinkPad schreef op vrijdag 7 mei 2021 @ 15:32:
@Pinobigbird nice find! Ik zoek zelf eigenlijk nog de 'work mode' (normal/waiting etc). Enig idee waar die in zit?
P.S. Welke tool gebruik jij om te ontcijferen? De laatste 4 tekens is de checksum trouwens. CRC-16 Modbus.
Ik heb Excel gebruikt. Zie hier m'n spreadsheet.

Ik vermoed dat positie 207 de work mode is, waarbij waarde 20 dan 'Normal' zou kunnen zijn. Geen idee hoe je die modus zou kunnen switchen om dit te testen. Dan zou ik vóór 06:55u de output moeten capturen om de 'Wait'-status te vinden.

Joey: Nice try. See the Netherlands is this make believe place where Peter Pan and Tinkerbell come from.
https://kattenoppasleiderdorp.nl
PV: 3080Wp ZO + 3465Wp NW = 6545Wp totaal 13°tilt


Acties:
  • +1Henk 'm!
  • Pinned

  • Pinobigbird
  • Registratie: januari 2002
  • Laatst online: 01:23

Pinobigbird

doesn't share food!

Ik heb via Wireshark de strings voor Shadow Scan on/off gevonden. Zo zou je de shadow scan alleen aan kunnen zetten op bepaalde tijdstippen waarop je het denkt nodig te hebben.

Shadow scan on:
7f069d8600018c51
Antwoord:
aa557f069d8600018c51

Shadow scan off:
7f069d8600004d91
Antwoord:
aa557f069d8600004d91


Waarbij
blauw = shadow scan adres
rood = waarde aan (1) of uit (0)
groen = omgekeerde CRC-16/MODBUS-checksum. Als ik de checksum bereken op https://www.lammertbies.nl/comm/info/crc-calculation van 7f069d860001 dan is dat [51 8c] i.p.v. [8c 51], en [91 4d] i.p.v. [4d 91]
aa55 is de antwoordheader, telt niet mee voor de checksum


Voorbeeld via sfk Shadow Scan aanzetten:
./sfk.exe cudp 192.168.1.11 8899 -listen -noerror -timeout=1000 0x7f069d8600018c51 -pure

Joey: Nice try. See the Netherlands is this make believe place where Peter Pan and Tinkerbell come from.
https://kattenoppasleiderdorp.nl
PV: 3080Wp ZO + 3465Wp NW = 6545Wp totaal 13°tilt


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

msatter schreef op dinsdag 11 mei 2021 @ 19:21:
[...]


Werkt het nu, of moet je nog naar 1.52.14 bijgewerkt worden?

Update:
Zou niet moeten werken zie ik nu. Je zou nog een keer een ticket zullen moeten aanmaken voor het ARM deel.
De 1e update was naar 1.52.09, daar had ik dus nu een ticket voor gemaakt om naar .14 te komen... Ticket gisteren gemaakt dus hoop voor donderdag nog eens te kunnen testen.

Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Ik heb mijn Node-RED code ook bijgewerkt. Lees de omvormer elke 10s uit. Merkte dat ik af en toe een incomplete reply kreeg, dus heb gelijk maar een functie ingebouwd die het bericht alleen verwerkt als de berekende CRC overeen komt met de meegestuurde CRC :9 Was nog even puzzelen om de juiste berekenmethode te vinden voor de CRC die Goodwe gebruikt, plus dat de CRC in het bericht is omgedraaid :?

In Node-RED heb ik dit dashboard

Ik haal de timestamp ook uit de reply van de Goodwe en toon deze, zo kan ik zien of ik wel naar recente data zit te kijken.

[Voor 19% gewijzigd door ThinkPad op 13-05-2021 16:40]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
De scripts in bash en fsk:

Bash script om via de prompt de laatste regel van het log(s) weer te geven, firmware versie of help (-help)

bestandsnaam: show-pv.sh

Bash:
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
#!/usr/bin/env bash

# scripter: msatter (name in the forum of tweakers.net)

# Version 1.68-20210514
# Only for non-commericial use

# exit 1

# Read the production of a Goodwe inverter and the retrieved data can be stored in a log file. At the end of the stored line time of retrieval.
# The name of the log file is the date in YYMMDD format and is this way unique. Each retrieved hex string has it's own line with a timestamp at the end.
# To retrieve data through IP needs a ARM firmware of 14 or higher. The last part of my firmware is stating for ARM "1.51.14" so 14 number for the ARM.

# This script needs SFK to run (http://www.stahlworks.com/dev/swiss-file-knife.html) 

# to-do: cleaning up

values_pv=0
firm_w=0
pvhelp=0
[code][/code]
case $1 in
    "showfirm" )
        firm_w=1 ;;
    "novalues" )
        values_pv=1  ;;
    "-help" )
        pvhelp=1  ;;
esac

case $2 in
    "showfirm" )
        firm_w=1 ;;
    "novalues" )
        values_pv=1  ;;
    "-help" )
        pvhelp=1  ;;
esac

clear 

# Call SFK script to display firmware version of the Inverter 
if [ $pvhelp -eq 1 ]; then sfk script -from=_help pv_scripts.sfk $pvhelp; exit 1; fi


# Call SFK script to display the last status of the Inverter
sfk script -from=pvinfo pv_scripts.sfk 2021 $values_pv $firm_w


FSK script [ http://stahlworks.com/dev/swiss-file-knife.html ]

bestandsnaam: pv_scripts.fsk

Bash:
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Free to use when it is for non-commericial use.
// Scripted by msatter (username in the tweakers.net forum)
//
// Different SFK scripts needed to display and log data from Goodwe Inverters
//
// Each +label can been seen as a subroutine and pvinfo calls other subs
// not all is working correctly but I think the current status is good enough
// for release.
// Bug status: does not display invertername for two or more inverters so that line is blank
// pvinfo: does show base information and calls other subs to display more information
// showvalues: shows the latest line written in the log(s)
// pvfirmware: shows the firmware version(s) of the inverters (parameter: showfirm)
// storepv: write the values retrieved from the inverter(s) in the log files
//

+label pvinfo  // last edit: 20210513 supporting one or more inverters

// +echo %1 +setvar year +echo %2 +setvar values_pv +echo %3 +setvar firm_w 
+setvar nr=
// if there is a config file with the name inverter.con the use that instead of the result of a broadcast
+ifexist inverter.conf begin copy inverter.conf goodwe.info -mirror -yes 
+echo "Warning: using config file "inverter.conf" instead of a broadcast on the local network" +echo "" +endif

+for i from 1 to 8

 // retrieve config directly from goodwe.info and if there is nodata then broadcast myself.  
 +filter -var -line=#(i) goodwe.info +xed "/[eol]//" +setvar showline
  +if -var "#(showline) = [timeout]" begin
   +cudp -broad 255.255.255.255 48899 -listen -noerror -timeout=5000 0x574946494b49542d3231343032382d52454144 -flat +xed "/[eol]//" +tofile goodwe.info
   +filter -var -line=#(i) goodwe.info +xed "/[eol]//" +setvar showline
  +endif
  +if -var "#(showline) = [timeout]" echo -var "Warning: the inverter did not answer to the broadcast within 5 seconds. Got a #(showline). Retry at a later time." +endif
 
 +setvar ipa=
 +echo -var "#(showline)" +xex "/**,**,**/[part1]/" "/[eol]//" +setvar ipa // store the IP address in the variable ipa
  
 +if -var "#(ipa) = " end +endif // emergency escape because the if still leaves an extra loop of the for..endfor
 +if -var "#(i) > 1" pause // show only one inverter info at a time
 +if -var "#(i) > 1" setvar -var nr=" #(i)" // generate a sequence number when there is more than one inverter being logged
  // only show info for inverters that exist.
  // +if -var "#(ipa) = " +begin
 
  +echo -var "Showing info from inverter#(nr):"
  // +echo -var "IP:#(ipa)adress Round: #(i)"
  
  +then +setvar tmp= +cudp -var "#(ipa)" 8899 -listen -noerror -timeout=1500 0x7f03753100280409 -flat 
  +xed "/[eol]//" +tif "rc<>0" begin xed "/[eol]//" +xex "/[start][52 chars]/[all]/"    
  +xex "/[9 chars][lend]/[all]/" +setvar tmp
  +if -var "#(tmp) <> " echo -var -pure "  Invertername:    #(tmp) " +endif  
  
  // show the info retrieved from goodwe.info  
  +echo "" +echo -pure "  SSID:   "   +echo -var "#(showline)" +xex "/**,**,**/[part5]/"       
  +echo -pure "  IP address: "        +echo -var "#(ipa)" // IP address already in variable "ipa"
  +echo -pure "  Indentifier/prefix: "    +echo -var "#(showline)" +xex "/[6 chars][eol]/[all]/"
  
  // generate the prefix of the last six characters from the serialno.
  +echo -var "#(showline)" +xex "/[6 chars][eol]/[all]/" +xed "/[eol]//" +setvar id
  +echo -var -noline "#(id)_" +setvar id // adding also an underscore to the prefix
  
  +call -var pvfirmware %3 #(ipa)
  // handing values over to showvalues to display the information from the log
  // +echo -var call "showvalues with: %1 %2 #(id)"
  +call -var showvalues %1 %2 #(id)
  // +setvar ipa= // reset variable ipa
  +echo ""
 // +endif
+endfor
+end

+label showvalues +then 

// Optimized fsk script. Closer match to table by using the start byte +4 or +8
// fill the variables. %1 %2 is given by the line that called this SFK script (parameter)
+echo %1 +setvar log_year +echo %2 +setvar values_pv +echo %3 +setvar id
// set variable log_year with the year and in front the id/prefix if present
+echo -var -noline #(id)#(log_year) +setvar log_year
// if parameter novalues is set then return and don't show any values
+if -var "#(values_pv) = 1" end +endif
// Retrieve the last log complete line from todays log
+sel -var -since today -dir #(log_year) -file #(id)*.log +hexfile -offlen -314 314 -flat -nofile +xed "/[eol]//" +setvar logstring
// Show date and time of show values
+then +list -var -today -dir #(log_year) -file #(id)*.log +xex "/[12 chars][lend]/[part1]/" +xex "/[start][8 chars]/[part2]/" +xed "/[eol]//" +setvar logday
// +sel -var -since today -dir #(log_year) -file *log +hexfile -offlen -7 5 -flat -nofile +setvar logtime
+sel -var -since today -dir #(log_year) -file #(id)*.log +hexfile -offlen -7 5 -flat -nofile +setvar logtime
+echo "" +echo -var "Values from on #(logday) at #(logtime)"

+echo -var #(logstring) +xex "/[start][26 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 0.0" echo -var "  Vpv:      #(tmp) V "
+echo -var #(logstring) +xex "/[start][34 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 0.0" echo -var "  Vpv1:     #(tmp) V "
+echo -var #(logstring) +xex "/[start][30 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 0.0" echo -var "  Ipv:      #(tmp) A "
+echo -var #(logstring) +xex "/[start][38 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 0.0" echo -var "  Ipv1:     #(tmp) A "

// value FFFF when not available
+echo -var #(logstring) +xex "/[start][74 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 6553.5" echo -var "  Vac:       #(tmp) V "
+echo -var #(logstring) +xex "/[start][78 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 6553.5" echo -var "  Vac2:      #(tmp) V "
+echo -var #(logstring) +xex "/[start][82 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1  +setvar tmp +if -var "#(tmp) <> 6553.5" echo -var "  Vac3:      #(tmp) V "

+echo -var #(logstring) +xex "/[start][86 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1"  -dig=1   +setvar vac +if -var "#(vac) <> 6553.5" echo -var "  Vac:      #(vac) V "

// value FFFF when not available
+echo -var #(logstring) +xex "/[start][98 chars]/[all]/" +xex "/[4 chars][lend]/[all]/"  +dec +calc "#text*0.1" -dig=1  +setvar tmp +if -var "#(tmp) <> 6553.5" echo -var "  Iac:       #(tmp) A "
+echo -var #(logstring) +xex "/[start][102 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1" -dig=1  +setvar tmp +if -var "#(tmp) <> 6553.5" echo -var "  Iac2:      #(tmp) A "
+echo -var #(logstring) +xex "/[start][106 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1" -dig=1  +setvar tmp +if -var "#(tmp) <> 6553.5" echo -var "  Iac3:      #(tmp) A "

// value FFFF when not available
+echo -var #(logstring) +xex "/[start][110 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.01" -dig=2  +setvar tmp +if -var "#(tmp) <> 655.35" echo -var     "  Fac:      #(tmp) Hz "
+echo -var #(logstring) +xex "/[start][114 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.01" -dig=2  +setvar tmp +if -var "#(tmp) <> 655.35" echo -var     "  Fac2:      #(tmp) Hz "
+echo -var #(logstring) +xex "/[start][118 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.01" -dig=2  +setvar tmp +if -var "#(tmp) <> 655.35" echo -var     "  Fac3:      #(tmp) Hz "

+sel -var -since today -dir #(log_year) -file *log +hexfile -offlen -292 4 -flat -nofile +dec +setvar vpv +sel -var -since today -dir #(log_year) -file *log +hexfile -offlen -288 4 -flat -nofile +dec +setvar ipv +echo -var "#(vpv)*#(ipv)/100000" +calc "#text" -dig=2 +setvar power +echo -var    "  Power:    #(power) kW "
// +sel -var -since today -dir #(log_year) -file *log +hexfile -offlen -232 4 -flat -nofile +dec +setvar vac +sel -var -since today -dir #(log_year) -file *log +hexfile -offlen -220 4 -flat -nofile +dec +setvar iac +echo -var "#(vac)*#(iac)/100000" +calc "#text" -dig=2 +setvar power +echo -var    "  PowerAC:   #(power) kW "
+echo -var #(logstring) +xex "/[start][178 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1" -dig=1  +setvar temp    +echo -var    "  Temperature:   #(temp) celcius "
+echo -var #(logstring) +xex "/[start][190 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*0.1" -dig=1  +setvar eday    +echo -var    "  Eday:      #(eday) kWh "
+echo -var #(logstring) +xex "/[start][198 chars]/[all]/" +xex "/[8 chars][lend]/[all]/" +dec +calc "#text*0.1" -dig=1  +setvar etotal  +echo -var    "  Etotal:    #(etotal) kWh "
+echo -var #(logstring) +xex "/[start][206 chars]/[all]/" +xex "/[8 chars][lend]/[all]/" +dec +calc "#text*1.0" -dig=0  +setvar work    +echo -var    "  Totalruntime:  #(work) hours "
+echo -var #(logstring) +xex "/[start][302 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*1.0" -dig=0  +setvar rssi    +echo -var    "  WiFi Signal:   #(rssi) % " 
// and return
// +pause
// +loop
+end

+label pvfirmware
 // fill the variables. %1 is given by the line that called this SFK script (parameter)
 +echo %1 +setvar firmware
 +echo %2 +setvar ipa
 // only show firmware if requested. 
 +if -var "#(firmware) <> 1" end
 // retrieve live the active firmware from the inverter(s) and store it in a variable
 +cudp -var "#(ipa)" 8899 -listen -noerror -timeout=1500 0x7f03753100280409 -pure +xed "/[eol]//" +xex "/[start]AA55**/[all]/" +tif "rc<>0" begin xed "/[eol]//" +setvar firmhex +endif
 +echo ""
 +echo "Firmware version(s):"
 +echo -var #(firmhex) +xex "/[start][146 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*1."  -dig=0  +setvar dsp1 +tell -var -noline "DSP1:#(dsp1)/"
 +echo -var #(firmhex) +xex "/[start][150 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*1."  -dig=0  +setvar dsp2 +tell -var -noline "DSP2:#(dsp2)/"
 +echo -var #(firmhex) +xex "/[start][154 chars]/[all]/" +xex "/[4 chars][lend]/[all]/" +dec +calc "#text*1."  -dig=0  +setvar arm +tell -var -noline "ARM:#(arm)"
 +echo -var #(dsp1) +xex "/[1 char][lend]/[part1]/" +setvar dsp1
 +echo -var " (V#(dsp1).#(dsp2).#(arm))"
+end

+label _help
// fill the variables. %1 is given by the line that called this SFK script (parameter)
+echo %1 +setvar pvhelp
+if -var "#(pvhelp) <> 1" end

+tell "Welcome to the help of script to display information from your inverter(s)."
+tell ""
+tell "You can use the following parameters behind the name of the script"
+tell "[Green]showfirm[def] - shows (also) the version of the current firmware."
+tell "[Green]novalues[def] - don't show the last values entry from the inverter-log file"
+tell "[Green]-help[def] - that is what you just typed."
+end



+label storepv +then // last edit: 202105014 Cleaned script by running sfk script test-pv.sfk

+setvar basedir=%1 // setting path being used to store and also to run script from
+setvar useconfigfile=inverter.conf
+ifnotexist -var #(basedir)/inverter.conf setvar useconfigfile=goodwe.info +endif
 
// compare files and overwrite goodwe.info if they are not the same
+ifexist -var #(basedir)/inverter.conf begin
  +md5 -var -quiet #(basedir)/inverter.conf #(basedir)/goodwe.info
  +if "rc<>0" copy -var #(basedir)/inverter.conf #(basedir)/goodwe.info -mirror -yes +endif 
+endif

+for i from 1 to 8
  +then +filter -var #(basedir)/#(useconfigfile) -line=#(i)
  +xex "/[6 chars][lend]/[all]/" +setvar id  // set id/prefix 
  +if -var "#(id) = " end +endif        // exit if all known inverters have been logged or if there is an error
  +if -var "#(id) = meout]" end +endif  // if there is no valid data in goodwe.info or inverter.conf

  // Check if the LOG directory and file exits and if not create it
  +date Y +setvar year
  +echo -var -noline "#(id)_#(year)" +setvar year
  +ifnotexist -var #(basedir)/#(year)/*.log mkdir -var #(basedir)/#(year) +endif

  // Add the id-part in front of the filename for the log to address more than one installed inverter.
  +date "YMD" +setvar ymd +echo -var -noline "#(id)_#(ymd)" +setvar ymd // add "id" when available
  +ifnotexist -var #(basedir)/#(year)/#(ymd).log touch -var -force #(basedir)/#(year)/#(ymd).log +endif
  
  // Retrieve the values from the inverter as an HEX string and store that in a log file
  +if -var "#(id) <> " begin
    +time " h:m " +setvar timestamp // time to be added to each log line
    +xfind -var #(basedir)/#(useconfigfile) /,**// +setvar ipa 
    +cudp -var #(ipa) 8899 -listen -noerror -timeout=1500 0x7f0375940049d5c2 -pure +xed /[eol]// 
    +xex /[start]AA55**/ +tif "rc<>0" begin +xex -var "/[lstart][306 chars]/[part2]#(timestamp)/"
                           +append -var #(basedir)/#(year)/#(ymd).log 
                         +endif 
  +endif
endfor
+end


Jouw eigen config bestand wanneer je meer dan één omvormer hebt of als je niet constant wil broadcasten. De informatie wordt naar het werkbestand goodwe.info geschreven, zowel in broadcast mode als met het config bestand.
Een eigen config bestand is niet noodzakelijk voor de werking van de scripts.

bestandsnaam: inverter.conf

code:
1
192.168.0.32,34EAE73D8B60,Solar-WiFi20DW6450


De logbestanden worden geschreven in voor elke omvormer in een eigen directory en zowel de directory als de log bestandsnaam krijgen een prefix met de laatste zes tekens van hun SSID/Serno. En dat is hier DW6450 en de daarachter komt een "_". Bestandsnaam is dan DW6450_202100514.log en directory naam is DW6450 _2021

Het schrijven naar het log doe ik direct vanuit de cron en dan elke minuut. Dit kan natuurlijk ook een langer tussentijd zijn.

De cron opdrachtregel:

code:
1
PATH="$PATH:/opt/goodwe" sfk script -from=storepv pv_scripts.sfk /opt/goodwe


Ik roep direct het FSK script "pv_scripts.sfk" aan en in dat script wordt vanaf label "storepv" de opdrachten uitgevoerd. De basis directory is "/opt/goodwe" (zonder trailing "/") en hier staan de scripts en worden de logbestanden geschreven.

Heeft veel tijd gekost vanwege het geschikt maken voor meer dan één omvormer en vanwege dat ik FSK totaal nieuw was voor mij. De syntax is af en toe vaag en je hoeft maar een " verkeerd hebben staan dan kun je gaan zoeken waar die dan is. Je krijgt er vanzelf handigheid in en het is toch een best fijne tool om dingen te doen. ;-)

Als er verbeterpunten zijn of inzichten dan hoor ik dat graag want ik zal vast wel fout gedaan hebben of niet zo efficient als het zou kunnen. Het werkt nu en ik hoop dat er geen bugs in zitten die ik gemist heb.

Update: ik had vanochtend het probleem dat het het nieuwe logbestand niet aangemaakt was en dat er daarna niet in geschreven werd. Ik heb een werkende code over de niet werkende heengezet en het werkt nu weer. Eigenlijk zit er geen verschill tussen die stukken code dus morgenvroeg weer kijken of het dan wel goed gaat.

Verder zat ik te danken hoe ik opgeslagen log regels korter kan maken zonder data te verliezen. Mijn eerste geachte was om herhalende tekens te beschrijven. Dus FFFFFFFF omschrijf ik als Fx08 --> herhaal teken F 8 maal...etc. Dit is pas efficient vanaf 5 herhalende tekens.

Een logregel gaat dan in mijn geval van 314 tekens terug naar 185 tekens.

[Voor 107% gewijzigd door msatter op 15-05-2021 10:11. Reden: Toelichting config bestand]


Acties:
  • +2Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
192.168.8.21 is het systeem waar mijn Node-RED op draait. De Goodwe zit bij mij op 192.168.6.15

Je kunt de flow pakken en daaronder heb ik de code van de onderste function node nog apart gezet. Die heb ik naderhand nog weer vaker bijgewerkt namelijk. Dubbel gedefinieerd klopt, ik maak de timestamp wat beter leesbaar.

In screenshot van mijn laatste post zie je het Node-RED dashboard. Die kun je apart installeren (via palette in NR even 'node-red-dashboard' installeren). Vervolgens aan de function node een paar dashboard output nodes hangen:

De 'value format' is dan {{msg.payload.power}} en {{msg.payload.eday}} etc.

In principe wijst het zichzelf, maar zie ook tutorial: https://randomnerdtutoria...-with-node-red-dashboard/

[Voor 5% gewijzigd door ThinkPad op 15-05-2021 10:42]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • Proton_
  • Registratie: november 2011
  • Laatst online: 22:58

Proton_

Team Welles

msatter schreef op vrijdag 14 mei 2021 @ 20:53:
Verder zat ik te danken hoe ik opgeslagen log regels korter kan maken zonder data te verliezen.
Waarom wil je dat?
Het kan natuurlijk wel:
Sla de data binair ipv als ASCII op.
Dus alleen de ruwe bytes van de omvormer opslaan en pas parsen als het verwerkt wordt.

Alternatief: pipe het resultaat door gzip.
Of... Sla het op in een timeseries database, dat is er voor gemaakt :)
Pvoutput is daar een voorbeeld van.

Sfk (en node-red in mindere mate ook) is naar mijn mening een voorbeeld van een Wikipedia: Inner-platform effect . Dingen die in een gewone programmeertaal gefaciliteerd worden (interfacen met externe systemen, redeneren over invariants, testen, diffbare code) zijn opeens lastig, doordat je beperkt wordt door het gekozen platform :)

Wel heel gaaf wat je voor elkaar krijgt natuurlijk :)

'19 Kona na '15 Zoe, douchen met wtw en Auer Edel Eau


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
@ThinkPad Ik heb de oude versie aangepast opdat er geen IP adressen meer ingevoerd hoeven te worden. Wel wennen aan de werkwijze en stapje voor stapje gaat het wel. Een probleem was dat hij zijn eigen broadcast ziet en dan maar de twee antwoorden samenvoegen tot één. Daarna kon ik uitzoeken hoe ik variabelen overdraag.



https://tweakers.net/i/XKZVfIuKCS_PWUbg_0dcwtoN-_s=/full-fit-in/4920x3264/filters:max_bytes(3145728):no_upscale():strip_icc():fill(white):strip_exif()/f/image/Vm6PoPKm7jYczFykbGJjmSsH.jpg?f=user_large

Code ziet er niet uit hier en daarom niet geplaatst. Code box werkt niet.

Update: Hierboven een versie die zowel via broadcast en via een vast IP adres de waardes ophaalt. Ook worden de waardes naar een bestand geschreven ( /opt/goodwe/nodered/just.log ) met daarachter een epoch timestamp.

Dat laatste kan mooier en de bestandsnamen met prefix en datum zoals in het FSK script maar dat is iets voor later en ik ben erg content met mijzelf dat ik zo snel voor elkaar kreeg. [/i].Terugvechten deed Node Red wel maar hier is veel meer gebruikers ervaringen te vinden dus ik hoef niet elke keer zelf het wiel uit te vinden. :X

Update de zoveelste: in een dag met Node Red de basis functionalitiet van het FSK script verkegen. Prefix, datum in directory en bestands naam een eenvoudig leesbare timestamp aan het einde van logregel.

De bovenstaande code staat toe om via broadcast de omvormer te vinden, met een vast doel IP om de zoveel tijd een logregel te schrijven. Daarnaast kan het ook worden verbonden met een grafische display @ThinkPad om de actuele waardes weer te geven.

Open staat hier ondersteuning voor meer dan één string en meer dan één omvormer. Daarnaast natuurlijk ook een browse functie om via het log waardes te bekijken in het verleden.
Dan is het mischien handig om het ook in database te gooien.

Kijk, geen cloud nodig om je eigen gegevens ook jouw eigen te houden. _/-\o_

Update: de prefix destabiliseerde alles en het injecteren van de prefix ging niet goed. Waarom weet ik niet.

Prefix probleem herkent en opgelost. Tjonge nog veel te leren en er kwamen nog payloads mee uit eerdere delen van de stream. Verwijderen en isoleren en het werkt nu als een klok. Ik heb nu ook virtuele links toegepast en zo ziet het een stuk netter en begrijpelijker uit....zie plaatje.
De code wilde ik ook plaatsen maar de code-box verslikt zich erin dus een andere manier bedenken voor dat.

[Voor 242% gewijzigd door msatter op 17-05-2021 16:13. Reden: Meer Node Red]


Acties:
  • +1Henk 'm!

  • wlmpie
  • Registratie: oktober 2007
  • Laatst online: 20:10
msatter schreef op zaterdag 15 mei 2021 @ 21:32:
@wlmpie Test het eerste met de APP SolarGo van Goodwe en als dat werkt dan gaat het uitlezen via Wifi
Die werkt idd niet dus ik heb eerst een ARM firmware update nodig, maar ik wil ook niet dat mijn omvormer op 2500 watt gaat aftoppen, want nu topt hij af op ca 2760 watt. Ik las van iemand met firmware 1.52.11 dat deze aftopte op 2500 en dat wil ik niet.
Iemand met een 3000xs heeft wel goede resultaten met firmware 1.51.14 https://gathering.tweakers.net/forum/view_message/67309210
Als dat ook bij een 2500xs werkt kan ik dat evt. aan Goodwe support vragen, maar firmware 1.52.14 zou ik dus niet willen vanwege het eerder aftoppen. Edit: @ThinkPad ik lees dat jij 1.52.14 hebt en dat deze niet aftopt op het nominale vermogen? Nou snap ik het niet meer.

Ik heb nu 1.13.13 als ze daar 1.13.14 van kunnen maken zou ik dat ook al prima vinden, maar ik heb geen idee of een support aanvraag bij Goodwe mij niet van de wal in de sloot helpt dus ik ben nog een beetje huiverig.

[Voor 5% gewijzigd door wlmpie op 15-05-2021 23:13]


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Werkt weer.



code:
1
[{"id":"801b0f90.623ea8","type":"tab","label":"Control and display live values inverter","disabled":false,"info":"Adoptation of the work by ThinkPad"},{"id":"57d7a5ee.293c24","type":"function","z":"801b0f90.623ea8","name":"Gen. values","func":"var IP_address = msg.ip\nvar inverter_reply = msg.payload;\nvar message1 = inverter_reply.slice(2); // Remove 'AA55' from start of message\n//var message = message.slice(0, -2); //Remove two CRC bytes from end of message\nvar message = message1.slice(0, -2); //Remove two CRC bytes from end of message\n\nfunction crc16(buffer) {\n    var crc = 0xFFFF;\n    var odd;\n\n    for (var i = 0; i < buffer.length; i++) {\n        crc = crc ^ buffer[i];\n\n        for (var j = 0; j < 8; j++) {\n            odd = crc & 0x0001;\n            crc = crc >> 1;\n            if (odd) {\n                crc = crc ^ 0xA001;\n            }\n        }\n    }\n    return crc.toString(16);\n}\n\n//Calculate CRC ourselves\nvar calculated_crc = crc16(message);\n\n//Get CRC from inverter reply and un-reverse it\nvar reply_crc = inverter_reply.slice(-2).toString('hex');\nvar crc1 = reply_crc.slice(0, 2);\nvar crc2 = reply_crc.slice(-2);\nvar new_crc = crc2 + crc1;\n\nif (new_crc == calculated_crc) {\n    var year = \"20\" + inverter_reply.readInt8(5); // \n    var month = inverter_reply.readInt8(6); // \n    var day = inverter_reply.readInt8(7); // \n    var hour = inverter_reply.readInt8(8); // \n    var minutes1 = inverter_reply.readInt8(9); // \n    var seconds1 = inverter_reply.readInt8(10); // \n    \n    var minutes = (minutes1 < 10 ? '0' : '') + minutes1;\n    var seconds = (seconds1 < 10 ? '0' : '') + seconds1;\n    var timestamp = hour + \":\" + minutes + \":\" + seconds + \"  \" + day + \"-\" + month + \"-\" + year;\n\n    var vpv = parseFloat((inverter_reply.readInt16BE(11) * 0.1).toFixed(1));\n    var ipv = parseFloat((inverter_reply.readInt16BE(13) * 0.1).toFixed(1));\n    var vac = parseFloat((inverter_reply.readInt16BE(41) * 0.1).toFixed(1));\n    var iac = parseFloat((inverter_reply.readInt16BE(47) * 0.1).toFixed(1));\n    var fac = parseFloat((inverter_reply.readInt16BE(53) * 0.01).toFixed(2));\n    var eday = parseFloat((inverter_reply.readInt16BE(93) * 0.1).toFixed(1));\n    var etotal = parseFloat((inverter_reply.readInt16BE(97) * 0.1).toFixed(2));\n    var rssi = inverter_reply.readInt16BE(149);\n    var workhours = inverter_reply.readInt16BE(101);\n    var temperature = parseFloat((inverter_reply.readInt16BE(87) * 0.1).toFixed(1));\n    var power = inverter_reply.readInt16BE(61);\n    var status = inverter_reply.readInt16BE(63);\n    var workmode;\n\n    switch (status) {\n        case 0:\n            workmode = \"Waiting\"\n            break;\n        case 1:\n            workmode = 'Normal'\n            break;\n        case 2:\n            workmode = \"Error\"\n            break;\n        case 4:\n            workmode = \"Checking\"\n            break;\n    }\n\n    msg.payload = {\n        vpv,\n        ipv,\n        vac,\n        iac,\n        fac,\n        power,\n        eday,\n        etotal,\n        rssi,\n        workhours,\n        temperature,\n        workmode,\n        IP_address,\n        timestamp\n    }\n\n    var nodestate = {\n        text: workmode + ' - Power: ' + power + 'W - ' + timestamp,\n                    };\n    node.status(nodestate);\n\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":220,"wires":[["9dc4ea82.154658"]],"icon":"font-awesome/fa-th-list"},{"id":"9dc4ea82.154658","type":"debug","z":"801b0f90.623ea8","name":"Show values","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1070,"y":220,"wires":[]},{"id":"516a7514.fae094","type":"udp out","z":"801b0f90.623ea8","name":"","addr":"","iface":"","port":"8899","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":330,"y":220,"wires":[],"icon":"node-red/bridge.svg"},{"id":"f06e70e4.9be698","type":"function","z":"801b0f90.623ea8","name":"Req. values","func":"var inverter_ask = Buffer.from(\"7F0375940049D5C2\",\"hex\");\nvar ipaddress = msg.payload.ipa;\n\nmsg.ip = ipaddress;\nmsg.payload = inverter_ask;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":170,"y":220,"wires":[["516a7514.fae094"]],"icon":"font-awesome/fa-sticky-note"},{"id":"b7a3a1b4.793988","type":"function","z":"801b0f90.623ea8","name":"Req. values","func":"var inverter_ask = Buffer.from(\"574946494b49542d3231343032382d52454144\",\"hex\");\n\nmsg.payload = inverter_ask;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":170,"y":100,"wires":[["b03ef4a7.ce18c"]],"icon":"font-awesome/fa-sticky-note"},{"id":"b03ef4a7.ce18c","type":"udp out","z":"801b0f90.623ea8","name":"","addr":"10.10.100.253","iface":"","port":"48899","ipv":"udp4","outport":"","base64":false,"multicast":"broad","x":380,"y":100,"wires":[]},{"id":"d625fa25.026a1","type":"udp in","z":"801b0f90.623ea8","name":"Parse broadcast","iface":"","port":"48899","ipv":"udp4","multicast":"false","group":"","datatype":"utf8","x":600,"y":100,"wires":[["1e827cf5.e75863"]]},{"id":"c188a436.fa08e","type":"debug","z":"801b0f90.623ea8","name":"Msg. broadcast","active":false,"tosidebar":true,"console":true,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":100,"wires":[]},{"id":"5a0ad7a8.bfe99","type":"csv","z":"801b0f90.623ea8","name":"CVS","sep":",","hdrin":false,"hdrout":"none","multi":"one","ret":"\\n","temp":"ipa,mac,ssid","skip":"0","strings":true,"include_empty_strings":true,"include_null_values":true,"x":730,"y":140,"wires":[["2bbcda70.e9e99e"]]},{"id":"d05deb79.7f147","type":"join","z":"801b0f90.623ea8","name":"Join hex+time","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"logline","joiner":"[32]","joinerType":"bin","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"str","reduceFixup":"","x":1060,"y":340,"wires":[["f35ba234.b2a0c"]],"icon":"font-awesome/fa-indent"},{"id":"8277276e.aa4838","type":"udp in","z":"801b0f90.623ea8","name":"","iface":"","port":"8899","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":480,"y":220,"wires":[["c3f1b711.3b982"]],"icon":"node-red/bridge.svg"},{"id":"f35ba234.b2a0c","type":"file","z":"801b0f90.623ea8","name":"Save to log","filename":"","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"ascii","x":1070,"y":280,"wires":[[]],"icon":"font-awesome/fa-floppy-o"},{"id":"b7d1e792.f544b","type":"inject","z":"801b0f90.623ea8","name":"Timer & config","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"goodwe","vt":"str"}],"repeat":"300","crontab":"","once":true,"onceDelay":0.1,"topic":"","x":420,"y":380,"wires":[["7326dc17.928594"]],"icon":"font-awesome/fa-pencil-square","info":"Prefix max. 6 charactes/numbers"},{"id":"1b903bf1.27fd9c","type":"switch","z":"801b0f90.623ea8","name":"Ignore own outward broadcast","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"214028","vt":"str"},{"t":"eq","v":"payload","vt":"msg"}],"checkall":"false","repair":false,"outputs":2,"x":530,"y":140,"wires":[[],["5a0ad7a8.bfe99"]]},{"id":"9c808dd6.aae978","type":"function","z":"801b0f90.623ea8","name":"Hex2String","func":"// replace the payload buffer with the string value\nmsg.payload = msg.payload.toString('hex');\n// return the original msg with the new string payload\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":280,"wires":[["d05deb79.7f147"]],"icon":"font-awesome/fa-forward"},{"id":"8a067e8c.712a18","type":"function","z":"801b0f90.623ea8","name":"timestamp","func":"var d=new Date();\nvar hours=('00' + d.getHours()).slice(-2);\nvar minutes=('00' + (d.getMinutes()+1)).slice(-2);\n// adding a space behind the time so that the lenght of the line is 314 characters in the log\nmsg.payload = hours+\":\"+minutes+\" \"\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":320,"wires":[["d05deb79.7f147"]],"icon":"font-awesome/fa-clock-o","info":"Create timestamp in hour:minute format that will added to the end of the HEX string "},{"id":"f28cf758.5b613","type":"function","z":"801b0f90.623ea8","name":"Set Prefix","func":"var ssid = msg.payload.ssid\nvar prefix = (ssid.slice(-6))\nmsg.payload = prefix;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":180,"y":300,"wires":[["1561d519.143313"]],"icon":"font-awesome/fa-sign-in"},{"id":"420eea8b.694c34","type":"function","z":"801b0f90.623ea8","name":"prefix+dir/file","func":"var d=new Date()\nvar day=('00' + d.getDate()).slice(-2)\nvar month=('00' + (d.getMonth()+1)).slice(-2)\nvar year=d.getFullYear()\n//var prefix = msg.prefix\n\nbasedir =\"/opt/goodwe/\";\ndirdate = year+\"/\";\nfiledate = year+\"\"+month+\"\"+day;\npre = msg.prefix+\"_\";\n//pre = \"\";\n\nmsg.filename = basedir+pre+dirdate+pre+filedate;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":340,"wires":[["d05deb79.7f147"]],"icon":"font-awesome/fa-forward"},{"id":"2562ae04.bb24e2","type":"delay","z":"801b0f90.623ea8","name":"","pauseType":"delay","timeout":"50","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":650,"y":260,"wires":[["8a067e8c.712a18"]],"info":"Timestamp has to at the end of the log line so it has to be delayed a bit so that the sequencing is working."},{"id":"98370845.3723d","type":"debug","z":"801b0f90.623ea8","name":"Complete message","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":910,"y":420,"wires":[]},{"id":"74ffb5a1.3432a4","type":"switch","z":"801b0f90.623ea8","name":"has content?","property":"payload","propertyType":"msg","rules":[{"t":"empty"},{"t":"nempty"}],"checkall":"false","repair":false,"outputs":2,"x":890,"y":380,"wires":[[],[]]},{"id":"bd1163f9.78035","type":"link out","z":"801b0f90.623ea8","name":"Request Broadcast","links":["ebb5ecf5.167578","ae94db63.376f1","b57093f2.7367f"],"x":255,"y":380,"wires":[]},{"id":"f81b7c8d.7669a8","type":"inject","z":"801b0f90.623ea8","name":"Do broadcast","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":150,"y":380,"wires":[["bd1163f9.78035"]]},{"id":"301762de.e10bbe","type":"link in","z":"801b0f90.623ea8","name":"Receive prefix","links":["2bbcda70.e9e99e","7326dc17.928594"],"x":75,"y":300,"wires":[["f28cf758.5b613"]]},{"id":"7326dc17.928594","type":"link out","z":"801b0f90.623ea8","name":"TimerConfig","links":["301762de.e10bbe","ef310d19.938f58","4fac93fd.ba7f54"],"x":555,"y":420,"wires":[]},{"id":"ef310d19.938f58","type":"link in","z":"801b0f90.623ea8","name":"Req. values","links":["13a9767d.afa3aa","2bbcda70.e9e99e","7326dc17.928594"],"x":75,"y":220,"wires":[["f06e70e4.9be698"]]},{"id":"1561d519.143313","type":"change","z":"801b0f90.623ea8","name":"Clean payload + move","rules":[{"t":"delete","p":"parts","pt":"msg"},{"t":"delete","p":"fromip","pt":"msg"},{"t":"delete","p":"ip","pt":"msg"},{"t":"delete","p":"port","pt":"msg"},{"t":"delete","p":"columns","pt":"msg"},{"t":"delete","p":"ipa","pt":"msg"},{"t":"move","p":"payload","pt":"msg","to":"prefix","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":300,"wires":[["420eea8b.694c34"]],"icon":"font-awesome/fa-filter"},{"id":"e8c56e20.38afd","type":"change","z":"801b0f90.623ea8","name":"Clean payload","rules":[{"t":"delete","p":"fromip","pt":"msg"},{"t":"delete","p":"ip","pt":"msg"},{"t":"delete","p":"port","pt":"msg"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":260,"wires":[["2562ae04.bb24e2"]],"icon":"font-awesome/fa-filter"},{"id":"2bbcda70.e9e99e","type":"link out","z":"801b0f90.623ea8","name":"","links":["301762de.e10bbe","ef310d19.938f58"],"x":815,"y":140,"wires":[]},{"id":"ae94db63.376f1","type":"link in","z":"801b0f90.623ea8","name":"Req. Broadcast","links":["a86bf67d.7b4578","bd1163f9.78035"],"x":75,"y":100,"wires":[["b7a3a1b4.793988"]]},{"id":"c3f1b711.3b982","type":"delay","z":"801b0f90.623ea8","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":640,"y":220,"wires":[["9c808dd6.aae978","e8c56e20.38afd","57d7a5ee.293c24","c84a78f7.b8b6c8"]],"icon":"font-awesome/fa-hand-stop-o"},{"id":"1e827cf5.e75863","type":"delay","z":"801b0f90.623ea8","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":780,"y":100,"wires":[["c188a436.fa08e","1b903bf1.27fd9c","babc3f74.4a59f"]],"icon":"font-awesome/fa-hand-stop-o"},{"id":"63d631b.40e4ed","type":"comment","z":"801b0f90.623ea8","name":"Use broadcast to find a inverter with time-out detect","info":"","x":250,"y":60,"wires":[]},{"id":"1a9c32f4.0a6195","type":"comment","z":"801b0f90.623ea8","name":"Request and process values provided by the inverter with time-out detect","info":"","x":320,"y":180,"wires":[]},{"id":"ab4a8de3.ff053","type":"comment","z":"801b0f90.623ea8","name":"Find inverter (broadcast)","info":"","x":170,"y":340,"wires":[]},{"id":"9a620fa4.5a0e4","type":"comment","z":"801b0f90.623ea8","name":"Prepare for writing to log.","info":"","x":170,"y":260,"wires":[]},{"id":"d400b5d7.d2cad","type":"comment","z":"801b0f90.623ea8","name":"Scheduler, set IP address and prefix","info":"","x":450,"y":340,"wires":[]},{"id":"b3ee5a06.7b3c6","type":"comment","z":"801b0f90.623ea8","name":"Spare","info":"","x":750,"y":380,"wires":[]},{"id":"576863d4.d2162c","type":"inject","z":"801b0f90.623ea8","d":true,"name":"Timer & config No2","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"no2","vt":"str"}],"repeat":"","crontab":"*/5 4-22 * * *","once":true,"onceDelay":"5","topic":"","x":400,"y":420,"wires":[["7326dc17.928594"]]},{"id":"69f5a1ee.df6a48","type":"inject","z":"801b0f90.623ea8","d":true,"name":"Timer & config No3","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"no3","vt":"str"}],"repeat":"","crontab":"*/5 4-22 * * *","once":true,"onceDelay":"10","topic":"","x":400,"y":460,"wires":[["7326dc17.928594"]]},{"id":"b57093f2.7367f","type":"link in","z":"801b0f90.623ea8","name":"time-out broadcast","links":["bd1163f9.78035"],"x":635,"y":60,"wires":[["babc3f74.4a59f"]]},{"id":"a31bf69f.04fc7","type":"switch","z":"801b0f90.623ea8","name":"check for time-out","property":"payload","propertyType":"msg","rules":[{"t":"nempty"},{"t":"empty"}],"checkall":"true","repair":false,"outputs":2,"x":930,"y":60,"wires":[[],["a86bf67d.7b4578"]]},{"id":"a86bf67d.7b4578","type":"link out","z":"801b0f90.623ea8","name":"broadcast time-out detected","links":["ae94db63.376f1"],"x":1055,"y":60,"wires":[]},{"id":"babc3f74.4a59f","type":"trigger","z":"801b0f90.623ea8","name":"5 sec. wait","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"5","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"topic","topic":"payload","outputs":2,"x":730,"y":60,"wires":[[],["a31bf69f.04fc7"]]},{"id":"c84a78f7.b8b6c8","type":"trigger","z":"801b0f90.623ea8","name":"5 sec. wait","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"5","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":750,"y":180,"wires":[[],["8e3a64a5.067ae8"]]},{"id":"8e3a64a5.067ae8","type":"switch","z":"801b0f90.623ea8","name":"check for time-out","property":"payload","propertyType":"msg","rules":[{"t":"nempty"},{"t":"empty"}],"checkall":"true","repair":false,"outputs":2,"x":930,"y":180,"wires":[[],["13a9767d.afa3aa"]]},{"id":"4fac93fd.ba7f54","type":"link in","z":"801b0f90.623ea8","name":"time-out request","links":["7326dc17.928594"],"x":635,"y":180,"wires":[["c84a78f7.b8b6c8"]]},{"id":"13a9767d.afa3aa","type":"link out","z":"801b0f90.623ea8","name":"time-out detected","links":["ef310d19.938f58"],"x":1055,"y":180,"wires":[]}]



Het broadcast addres is tijdelijk 10.10.100.253 (AP) i.pv. 255.255.255.255 omdat er tijdelijk een router tussen zit om de de DHCP broadcasts van de Goodwe AP te killen met behulp van DHCP snooping + optie 82.

Ik heb een Mikrotik cAP lite onderweg. Die ga ik pal naast de Goodwe hangen en in de WiFi stick haal de antenne kabel van connector opdat die gaat fluisteren i.p.v. bazuinen.

Update: twee rate limiters geplaatst elk na iedere packet ontvangers en commentaar velden geplaatst ter verduidelijking.

Update 20 mei: De ratelimiter aangepast naar 3 seconden, just to be sure, en icons aangepast opdat de functie van de velden gemakkelijker te bepalen is.
Ook een voorbeeld erin gezet van meer dan één omvormer uitlezen en let hier op de opstart vertraging en dat de uitlees interval verder gelijke is voor alle omvormers. Zo blijft de juiste sequency goed en kan er geen overlappingen komen tussen de omvormers in de verschillende logs.

Meer dan één string en drie fase zit als standaard in het log dus daar is geen omkijken naar. Het omzetten naar waarden en is nog een uitdaging omdat ik hier een soort if-then-else voor moet verzinnen. Ik denk dat ik wel wat met Switch kan doen binnen Node-Red.

Update 21 mei: enkele dingen aangepast en nu ook een time-out op de ontvangst. Als er binnen vijf seconden geen gegevens binnenkomen dan gaat er een nieuwe aanvraag uit. Er is nog geen beperking hoevaak maar zodra er een antwoord komt dan is er geen time-out meer.

@ThinkPad

[Voor 36% gewijzigd door msatter op 21-05-2021 14:20. Reden: Flow bijgewerkt, verschillende omvormers + timers]


Acties:
  • +3Henk 'm!

  • Proton_
  • Registratie: november 2011
  • Laatst online: 22:58

Proton_

Team Welles

Het is intussen [GoodWe] Uitlezen inverters via UDP geworden ;)

Een tooltje om vanuit je eigen netwerk van de omvormer naar PVOutput te pushen heb ik hier op github gezet:
https://github.com/koen-lee/GoodweUDPToPvOutput
De release is self-contained linux-arm, dus draait na uitpakken direct op een Pi.

Resultaat is https://pvoutput.org/intraday.jsp?id=20978&sid=18868

'19 Kona na '15 Zoe, douchen met wtw en Auer Edel Eau


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Ik dacht dat mijn wachtwoord voor mijn WiFi uit de settings van de Goodwe was verdwenen omdat ik die niet meer zag als ik die via Modbus uitlas. Mijn wachtwoord was er nog en ik zag dat toen ik een uitgebreidere versie van de webinterface geinstalleerd had.

Ik had weer net te weinig tijd om alles te controleren maar hier kon ik mijn wachtwoord verwijderen door andere AP te kiezen in de buurt en er een dummy wachtwoord in te voeren. Dit zou ook kunnen de standaard versie van de web interface via Wizard.

Ik wilde STA uitzetten maar dat bleef ook niet plakken en morgen maar eens uitgebreider daarna kijken.

Werkt nu en er staat nu Burn-in als router en password. Ik heb de reload knop gebruikt op de WiFi stick.

Ik kan het IP adres van de AP veranderen maar dan verlies ik toegang via SolarGo omdat die alleen werkt op IP 10.10.100.253.

Nu ook via NodeRed PVOutput voeden met de waardes die @ThinkPad uitgesplitst had. Het was even puzzelen met welke waarden ik kon doorzenden en wat het gevonden flow had. Gelukkig ging verderop in de flow dezelfde PVOutput namen gebruiken. Mooi dan kan ik daar aansluiten.

Als morgen alles nog goed werkt dan kan ik dat hier posten opdat anderen het ook kunnen gebruiken.

[Voor 33% gewijzigd door msatter op 22-05-2021 21:52. Reden: PVOtput.org en iWeb]


Acties:
  • +3Henk 'm!

  • Aiolos
  • Registratie: januari 2002
  • Niet online
Vanuit dit topic ben ik vandaag ook eens bezig gegaan met het uitlezen via UDP. Uiteraard in nog een andere taal dan hier al gedaan, en wel PHP.
Het resultaat is hier te bekijken: https://github.com/aiolos/GoodweUdpReader

De broadcast heb ik overgeslagen, in de configuratie moet je gewoon een ip-adres invullen (of meerdere als je meerdere omvormers hebt). Als je ook een PVOutput apikey en system id invult, worden de gegevens naar PVOutput gepushed.

Ik heb het vandaag in elkaar geklust, nog maar weinig getest en vooral de 'happy-path'.

Stuur me een PM voor Wemos D1 shields voor het uitlezen van slimme meters of het aansturen van Itho mechanische ventilatie (of kijk op V&A: https://tweakers.net/aanbod/user/47321/)


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Ik heb het gevoel dat ik niets meer kan toevoegen aan de PVOutput flow voor Node Red. Nieuw sinds de vorige versie is dat nu het opnieuw proberen om de omvormer uit te lezen is beperkt (timestamp) en zo geen overlap meer. De status van upload naar PVOutput is zichtbaar en daarbij is gekomen de het tijdstip van de laatste geslaagde uitlezing van de omvormer.

Verder is het correct zijn van de gegevens beter en zo is mogelijk om altijd geldige gegevens naar PVOutput te uploaden.



code:
1
[{"id":"801b0f90.623ea8","type":"tab","label":"Inverter2PVOutput","disabled":false,"info":"Scripted by msatter\nversion: 20210526-1.10\nOnly for non-comercial usage"},{"id":"25c26ce6.9d762c","type":"subflow","name":"Prepare for PVOutput.org","info":"Version:20210526-1.10","category":"","in":[{"x":40,"y":40,"wires":[{"id":"4e1640a7.b10de8"}]}],"out":[{"x":380,"y":160,"wires":[{"id":"e883ef0a.9d7f5","port":1}]}],"env":[],"meta":{},"color":"#AAAA66","icon":"font-awesome/fa-filter","status":{"x":540,"y":200,"wires":[{"id":"a0cff14b.2baee8","port":0}]}},{"id":"ff01618d.60809","type":"subflow","name":"PVOutput upload","info":"Provided by **Vster Lee**\n[https://community.openenergymonitor.org/t/pvoutput-org-nodered/779/3]()\n\nAdapted for Goodwe UDP over WiFi by **msatter** [https://tweakers.net/gallery/1582350/]()\n\nVersio 20210526-1.15","category":"","in":[{"x":40,"y":80,"wires":[{"id":"1a1e9c44.bce1f4"}]}],"out":[],"env":[],"meta":{},"color":"#87A980","icon":"font-awesome/fa-line-chart","status":{"x":800,"y":60,"wires":[{"id":"d68b8d43.29747","port":0},{"id":"ba0c10e4.0b273","port":0}]}},{"id":"4b48967c.fcfc3","type":"group","z":"801b0f90.623ea8","name":"Handing over to subflow nodes, status diplayed","style":{"stroke":"none","fill":"#addb7b","label":true,"label-position":"se","color":"#ffffff"},"nodes":["6e0fb1a2.416948","407e80c8.75639","930318c6.0ba1a"],"x":534,"y":199,"w":332,"h":150},{"id":"8ae4ca85.96da48","type":"group","z":"801b0f90.623ea8","name":"Retrieve values from the inverter, with time-out detection / CRC check with retry till TTL has become invalid.","style":{"stroke-opacity":"0","fill":"#7fb7df","label":true,"color":"#ffffff"},"nodes":["516a7514.fae094","f06e70e4.9be698","8277276e.aa4838","c3f1b711.3b982","2d33f88c.5b3218","39c47589.21ca4a","97508752.1cd3a8","11627800.6500a","57ba3d31.c82a94","61584504.656bb4","c48649f.4f33938","ca20bfa3.9a4018","97d4ca32.f3eab","8d4b9241.9ebfb"],"x":54,"y":19,"w":812,"h":162},{"id":"d6e3f503.b6b34","type":"group","z":"801b0f90.623ea8","name":"Request values, transfer API-key and System-id","style":{"stroke":"none","fill":"#3f5787","label":true,"label-position":"se","color":"#ffffff"},"nodes":["b7d1e792.f544b","7326dc17.928594","576863d4.d2162c","69f5a1ee.df6a48","3921663d.c36b9a"],"x":54,"y":199,"w":432,"h":210},{"id":"4e1640a7.b10de8","type":"change","z":"25c26ce6.9d762c","name":"Not needed values","rules":[{"t":"delete","p":"payload.ipa","pt":"msg"},{"t":"delete","p":"payload.TTL","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":210,"y":40,"wires":[["fdd4f465.f60b3"]],"icon":"font-awesome/fa-filter"},{"id":"fdd4f465.f60b3","type":"join","z":"25c26ce6.9d762c","name":"Put values in a array","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"[32]","joinerType":"bin","accumulate":false,"timeout":"290","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":220,"y":80,"wires":[["5edda9f.62c3158"]],"info":"A time-out of 297 seconds after the first message so that all is cleaned up for the next update. "},{"id":"e883ef0a.9d7f5","type":"switch","z":"25c26ce6.9d762c","name":"Array [0] well formed","property":"payload[0].PVOid","propertyType":"msg","rules":[{"t":"empty"},{"t":"nempty"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":160,"wires":[[],["a0cff14b.2baee8"]],"icon":"node-red/white-globe.svg"},{"id":"6e0fb1a2.416948","type":"link in","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Prepare PVO+system-id","links":["2d33f88c.5b3218","7326dc17.928594"],"x":575,"y":240,"wires":[["930318c6.0ba1a"]],"icon":"font-awesome/fa-arrow-right"},{"id":"407e80c8.75639","type":"subflow:ff01618d.60809","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Transmit values to PVOutput","env":[],"x":720,"y":300,"wires":[]},{"id":"930318c6.0ba1a","type":"subflow:25c26ce6.9d762c","z":"801b0f90.623ea8","g":"4b48967c.fcfc3","name":"Prepare values for PVOutput","env":[],"x":720,"y":240,"wires":[["407e80c8.75639"]]},{"id":"516a7514.fae094","type":"udp out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","addr":"","iface":"","port":"8899","ipv":"udp4","outport":"","base64":false,"multicast":"false","x":310,"y":60,"wires":[],"icon":"node-red/bridge.svg"},{"id":"f06e70e4.9be698","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Req. values","func":"var inverter_ask = Buffer.from(\"7F0375940049D5C2\",\"hex\");\nvar ipaddress = msg.payload.ipa;\n\nmsg.ip = ipaddress;\nmsg.payload = inverter_ask;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":150,"y":60,"wires":[["516a7514.fae094"]],"icon":"font-awesome/fa-sticky-note"},{"id":"8277276e.aa4838","type":"udp in","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","iface":"","port":"8899","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":460,"y":60,"wires":[["61584504.656bb4"]],"icon":"node-red/bridge.svg"},{"id":"c3f1b711.3b982","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"6","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":500,"y":100,"wires":[["39c47589.21ca4a"]],"icon":"font-awesome/fa-hand-stop-o"},{"id":"2d33f88c.5b3218","type":"link out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Publish","links":["6e0fb1a2.416948"],"x":780,"y":60,"wires":[],"icon":"font-awesome/fa-arrow-down","l":true},{"id":"39c47589.21ca4a","type":"switch","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Values","property":"payload.ipa","propertyType":"msg","rules":[{"t":"null"},{"t":"nnull"}],"checkall":"true","repair":false,"outputs":2,"x":650,"y":100,"wires":[["2d33f88c.5b3218"],["c48649f.4f33938"]],"inputLabels":["Valid"],"outputLabels":["YES","NO"],"icon":"font-awesome/fa-check-square"},{"id":"97508752.1cd3a8","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":320,"y":100,"wires":[["c3f1b711.3b982"]]},{"id":"11627800.6500a","type":"link in","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Retrieve values","links":["7326dc17.928594","97d4ca32.f3eab"],"x":160,"y":140,"wires":[["57ba3d31.c82a94"]],"icon":"font-awesome/fa-arrow-right","l":true},{"id":"57ba3d31.c82a94","type":"delay","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"minutes","rate":"3","nbRateUnits":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":150,"y":100,"wires":[["97508752.1cd3a8","f06e70e4.9be698"]],"icon":"font-awesome/fa-hand-stop-o"},{"id":"61584504.656bb4","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"CRC-check","func":"var inverter_reply = msg.payload;\n\nvar message1 = inverter_reply.slice(2); // Remove 'AA55' from start of message\n//var message = message.slice(0, -2); //Remove two CRC bytes from end of message\nvar message = message1.slice(0, -2); //Remove two CRC bytes from end of message\n\nfunction crc16(buffer) {\n    var crc = 0xFFFF;\n    var odd;\n\n    for (var i = 0; i < buffer.length; i++) {\n        crc = crc ^ buffer[i];\n\n        for (var j = 0; j < 8; j++) {\n            odd = crc & 0x0001;\n            crc = crc >> 1;\n            if (odd) {\n                crc = crc ^ 0xA001;\n            }\n        }\n    }\n    return crc.toString(16);\n}\n\n//Calculate CRC ourselves\nvar calculated_crc = crc16(message);\n\n//Get CRC from inverter reply and un-reverse it\nvar reply_crc = inverter_reply.slice(-2).toString('hex');\nvar crc1 = reply_crc.slice(0, 2);\nvar crc2 = reply_crc.slice(-2);\nvar new_crc = crc2 + crc1;\n\nif (new_crc == calculated_crc) {\n// If the checksum is not correct retry to get a good string.\n    msg.complete=true\n    return msg;\n// Also the wait for power delevery to the net could here be checked.\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":60,"wires":[["c3f1b711.3b982"]],"icon":"font-awesome/fa-arrows-h"},{"id":"b7d1e792.f544b","type":"inject","z":"801b0f90.623ea8","g":"d6e3f503.b6b34","name":"PVOutput config & timer","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.PVOid","v":"nnnnn","vt":"str"},{"p":"payload.APIkey","v":"nnnnnnnnnnnnn.......","vt":"str"},{"p":"payload.TTL","v":"","vt":"date"}],"repeat":"","crontab":"*/5 5-22 * * *","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":210,"y":240,"wires":[["7326dc17.928594"]],"icon":"font-awesome/fa-pencil-square","info":"Prefix max. 6 charactes/numbers\nWhen sending also to PVOoutput.org then add the\nfollowing string (a-z)\n\npayload.PVOid = your PVO system-id (five numbers)"},{"id":"576863d4.d2162c","type":"inject","z":"801b0f90.623ea8","d":true,"g":"d6e3f503.b6b34","name":"Timer & config No2","props":[],"repeat":"","crontab":"*/5 5-22 * * *","once":false,"onceDelay":"5","topic":"","payloadType":"str","x":200,"y":280,"wires":[["7326dc17.928594"]]},{"id":"69f5a1ee.df6a48","type":"inject","z":"801b0f90.623ea8","d":true,"g":"d6e3f503.b6b34","name":"Timer & config No3","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"no3","vt":"str"}],"repeat":"","crontab":"*/5 4-22 * * *","once":true,"onceDelay":"10","topic":"","x":200,"y":320,"wires":[["7326dc17.928594"]]},{"id":"3921663d.c36b9a","type":"inject","z":"801b0f90.623ea8","d":true,"g":"d6e3f503.b6b34","name":"To PVoutput at midnight ","props":[{"p":"payload.ipa","v":"10.10.100.253","vt":"str"},{"p":"payload.ssid","v":"goodwe","vt":"str"},{"p":"payload.PVOid","v":"nnnnn","vt":"str"},{"p":"payload.APIkey","v":"nnnnnnnnnnnnnnn......","vt":"str"}],"repeat":"","crontab":"59 23 * * *","once":false,"onceDelay":0.1,"topic":"","x":210,"y":360,"wires":[["7326dc17.928594"]],"info":"This needed when also sending not only generated power but also consumed power."},{"id":"d68b8d43.29747","type":"http request","z":"ff01618d.60809","name":"Post","method":"POST","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":60,"wires":[["d7346137.28cba","b638e83a.a1c888"]]},{"id":"71cd2d97.8e32d4","type":"function","z":"ff01618d.60809","name":"Prepare Post","func":"msg.action = msg.payload;\nPVOsystemid = msg.payload.PVOsystemid;\nPVOAPIkey = msg.payload.PVOAPIkey;\n\nmsg.headers = {};\n//msg.headers['X-Pvoutput-Apikey'] = 'b9ebfcaa419189c2a8595617ad6bd8250ed8a2d9';\nmsg.headers['X-Pvoutput-Apikey'] = PVOAPIkey;\nmsg.headers['X-Pvoutput-SystemId'] = PVOsystemid;\nmsg.headers['Content-Type'] = 'application/x-www-form-urlencoded';\n\n////////////////////////////////////////////\nmsg.url = \"http://pvoutput.org/service/r2/addstatus.jsp\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":80,"wires":[["d68b8d43.29747","ac542fdb.fa626"]],"icon":"font-awesome/fa-align-left"},{"id":"d7346137.28cba","type":"function","z":"ff01618d.60809","name":"Check Status 1st","func":"var d=new Date();\nvar hours=('00' + d.getHours()).slice(-2);\nvar minutes=('00' + (d.getMinutes()+1)).slice(-2);\n// adding a space behind the time so that the lenght of the line is 314 characters in the log\nTime = hours+\":\"+minutes+\" \"\n\nif (msg.statusCode == 200) { \n   var stat = \"\";\n   flow.set('pvostat','200');  // this clears the outstanding PVO data, so it won't be uploaded again\n   var msg1 = null;\n   var msg2 = null;\n   // new status message\n   //msg.status.text =Time + \" \" + msg.status;\n} else {\n   var time = new Date().toString();\n   flow.set('pvostat', msg.statusCode);\n   stat = \"FAILED: Time:\" + time + \"  StatusCode:\" + msg.statusCode + \"  StatusMsg:\" + msg.payload;\n   //var msg1 = null;\n   //var msg2 = null;\n   msg1.payload = stat;\n   msg2.payload = stat;\n   var msg1 =  { payload: stat };\n   var msg2 =  { payload: stat };\n   //msg.status.text = Time + \" \" + msg.status;\n}\nreturn msg;\nreturn (msg1, msg2);","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":730,"y":100,"wires":[[],["fe3a3389.3b9b2"]],"icon":"font-awesome/fa-search"},{"id":"fe3a3389.3b9b2","type":"file","z":"ff01618d.60809","name":"PVO error log","filename":"/opt/goodwe/pvoutput/pvo_errors.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":920,"y":120,"wires":[[]]},{"id":"ac542fdb.fa626","type":"function","z":"ff01618d.60809","name":"Store PVO data","func":"//store the PVO data in case it doesn't upload correctly\nflow.set ('pvodata',msg.payload)\nreturn msg;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":100,"wires":[],"icon":"node-red/redis.png"},{"id":"ba0c10e4.0b273","type":"http request","z":"ff01618d.60809","name":"Re-Post","method":"POST","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":520,"y":200,"wires":[["82678181.eee75"]]},{"id":"9f08c692.4c46a8","type":"function","z":"ff01618d.60809","name":"Prepare retransmit","func":"msg.action = msg.payload;\nPVOsystemid = msg.payload.PVOsystemid;\nPVOAPIkey = msg.payload.PVOAPIkey;\n\nmsg.headers = {};\nmsg.headers['X-Pvoutput-Apikey'] = PVOAPIkey;\nmsg.headers['X-Pvoutput-SystemId'] = PVOsystemid;\nmsg.headers['Content-Type'] = 'application/x-www-form-urlencoded';\n\n////////////////////////////////////////////\nmsg.url = \"http://pvoutput.org/service/r2/addstatus.jsp\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":200,"wires":[["ba0c10e4.0b273"]],"icon":"node-red/white-globe.svg"},{"id":"82678181.eee75","type":"function","z":"ff01618d.60809","name":"Check Status 2nd","func":"if (msg.statusCode == 200) { \n   var time = new Date().toString();\n   var stat =\"\";\n   flow.set('pvostat', 200);  // this clears the outstanding PVO status, so it won't be uploaded again\n   var stat = \"RetransmitOK: Time:\" + time + \"  StatusCode:\" + msg.statusCode + \"  StatusMsg:\" + msg.payload;\n//   var msg1 = null;\n//   var msg2 = null;\n   var msg1 =  { payload: stat };\n   var msg2 =  { payload: stat };\n} else {\n   var time = new Date().toString();\n   flow.set('pvostat', msg.statusCode);\n   var stat = \"RetransmitFAIL: Time:\" + time + \"  StatusCode:\" + msg.statusCode + \"  StatusMsg:\" + msg.payload;\n//   var msg1 = null;\n//   var msg2 = null;\n   var msg1 =  { payload: stat };\n   var msg2 =  { payload: stat };\n}\nreturn (msg1, msg2);","outputs":"2","noerr":0,"initialize":"","finalize":"","libs":[],"x":730,"y":200,"wires":[["bc2c0f21.a7735"],["30cf215d.ab8d0e"]],"icon":"font-awesome/fa-search"},{"id":"30cf215d.ab8d0e","type":"file","z":"ff01618d.60809","name":"Retransmit fail","filename":"/opt/goodwe/pvoutput/pvo_errors.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":920,"y":220,"wires":[[]]},{"id":"b638e83a.a1c888","type":"function","z":"ff01618d.60809","name":"Fetch PVO data","func":"// Retransmit the PVO data in case it doesn't upload correctly the first time\n\nif (msg.statusCode != 200) { \n    \n// retrieve local stored data\n   var pvodata = flow.get('pvodata')||\"\";\n    msg.payload = pvodata;\n\nreturn msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":200,"wires":[["9f08c692.4c46a8"]],"icon":"node-red/redis.png"},{"id":"8d14e679.b29678","type":"file","z":"ff01618d.60809","name":"PVO Data","filename":"/opt/goodwe/pvoutput/PVO_data.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":900,"y":80,"wires":[[]]},{"id":"2696b14a.d9694e","type":"comment","z":"ff01618d.60809","name":"Check data sent OK and if not retransmit once","info":"The PVO website is busy and sometimes can't respond quickly enough and we get timeouts.\nThe next bit of code catches any errors and resubm its the code until it's sent OK.\n\nThat said, if it can't resend the data before the next data packet has to be sent (5 mins) then\nthe current packet will be lost. This is pretty rare though and won't be noticable on the graphs.\n","x":200,"y":160,"wires":[]},{"id":"5f830eb6.38a358","type":"comment","z":"ff01618d.60809","name":"Prepare values and then transfer those to PVOuput.org","info":"","x":220,"y":40,"wires":[]},{"id":"1a1e9c44.bce1f4","type":"function","z":"ff01618d.60809","name":"Prepare values","func":"var PVOsystemid = msg.payload[0].PVOid;\nvar PVOAPIkey = msg.payload[0].APIkey\nvar inverter_reply = msg.payload[1];\n\nvar message1 = inverter_reply.slice(2); // Remove 'AA55' from start of message\n//var message = message.slice(0, -2); //Remove two CRC bytes from end of message\nvar message = message1.slice(0, -2); //Remove two CRC bytes from end of message\n\nfunction crc16(buffer) {\n    var crc = 0xFFFF;\n    var odd;\n\n    for (var i = 0; i < buffer.length; i++) {\n        crc = crc ^ buffer[i];\n\n        for (var j = 0; j < 8; j++) {\n            odd = crc & 0x0001;\n            crc = crc >> 1;\n            if (odd) {\n                crc = crc ^ 0xA001;\n            }\n        }\n    }\n    return crc.toString(16);\n}\n\n//Calculate CRC ourselves\nvar calculated_crc = crc16(message);\n\n//Get CRC from inverter reply and un-reverse it\nvar reply_crc = inverter_reply.slice(-2).toString('hex');\nvar crc1 = reply_crc.slice(0, 2);\nvar crc2 = reply_crc.slice(-2);\nvar new_crc = crc2 + crc1;\n\nif (new_crc == calculated_crc) {\n    var year = \"20\" + inverter_reply.readInt8(5); // \n    var month = inverter_reply.readInt8(6); // \n    var day = inverter_reply.readInt8(7); // \n    var hour = inverter_reply.readInt8(8); // \n    var minutes1 = inverter_reply.readInt8(9); // \n\n    if(month.toString().length == 1)  { var month = '0'+month; }\n    if(day.toString().length == 1)    { var day = '0'+day;}\n    if(hour.toString().length == 1)   { var hour = '0'+hour; }\n    //if(minutes1.toString().length == 1) { var minutes1 = '0'+minutes1; }\n    var minutes = (minutes1 < 5 ? '0' : '') + minutes1;\n\nvar d = year + month + day;\nvar t = hour + \":\" + minutes;\nvar v1 = parseFloat((inverter_reply.readInt16BE(93) * 100).toFixed(1)); // eDay\nvar v2 = inverter_reply.readInt16BE(61);                                // production in Watt\nvar v5 = parseFloat((inverter_reply.readInt16BE(87) * 0.1).toFixed(1)); // v5 temperature\nvar v6 = parseFloat((inverter_reply.readInt16BE(41) * 0.1).toFixed(1)); // AC zijde\n\n    msg.payload = {\n        d,\n        t,\n        v1,\n        v2,\n        v5,\n        v6,\n        PVOsystemid,\n        PVOAPIkey\n    }\n\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":80,"wires":[["71cd2d97.8e32d4","106f84dd.f8d73b"]],"icon":"node-red/batch.svg"},{"id":"106f84dd.f8d73b","type":"file","z":"ff01618d.60809","name":"save-values","filename":"/opt/goodwe/nodered/saved-values.txt","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"ascii","x":530,"y":20,"wires":[[]]},{"id":"bc2c0f21.a7735","type":"file","z":"ff01618d.60809","name":"Retransmit OK","filename":"/opt/goodwe/pvoutput/PVO_data.log","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":920,"y":180,"wires":[[]]},{"id":"5edda9f.62c3158","type":"switch","z":"25c26ce6.9d762c","name":"Array [1] well formed?","property":"payload[1]","propertyType":"msg","rules":[{"t":"istype","v":"buffer","vt":"buffer"},{"t":"istype","v":"object","vt":"object"}],"checkall":"false","repair":false,"outputs":2,"x":220,"y":120,"wires":[["e883ef0a.9d7f5"],[]],"info":"When the inverter is offline the PVOutput credentials are still being injected.\n\nThis will check if the payload in the second array field is of the type buffer (contain the inverter values) and not a later injected PVOuput credentials."},{"id":"c48649f.4f33938","type":"function","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"TTL","func":"var timediff = 0\ntimediff = (Date.now() / 1000 ) - (msg.payload.TTL / 1000 );\nif (timediff > 124){\n    delete msg.payload\n    return msg\n}\n //msg.payload.diff = timediff;\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":140,"wires":[["ca20bfa3.9a4018"]],"icon":"font-awesome/fa-calculator"},{"id":"ca20bfa3.9a4018","type":"switch","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"TTL","property":"payload","propertyType":"msg","rules":[{"t":"nnull"},{"t":"null"}],"checkall":"true","repair":false,"outputs":2,"x":650,"y":140,"wires":[["97d4ca32.f3eab"],["8d4b9241.9ebfb"]],"outputLabels":["TTL valid","TTL invalid"],"icon":"font-awesome/fa-question-circle-o"},{"id":"97d4ca32.f3eab","type":"link out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Retry","links":["11627800.6500a"],"x":790,"y":100,"wires":[],"icon":"font-awesome/fa-refresh","l":true},{"id":"8d4b9241.9ebfb","type":"link out","z":"801b0f90.623ea8","g":"8ae4ca85.96da48","name":"Stop","links":[],"x":790,"y":140,"wires":[],"icon":"font-awesome/fa-chain-broken","l":true},{"id":"7326dc17.928594","type":"link out","z":"801b0f90.623ea8","g":"d6e3f503.b6b34","name":"Begin","links":["11627800.6500a","6e0fb1a2.416948"],"x":410,"y":300,"wires":[],"icon":"font-awesome/fa-arrow-up","l":true},{"id":"a0cff14b.2baee8","type":"function","z":"25c26ce6.9d762c","name":"Timestamp","func":"var inverter_reply = msg.payload[1];\n\nvar message1 = inverter_reply.slice(2); // Remove 'AA55' from start of message\nvar message = message1.slice(0, -2); //Remove two CRC bytes from end of message\n\n\nvar hour = inverter_reply.readInt8(8); // \nvar minute = inverter_reply.readInt8(9); // \n\nif(hour.toString().length == 1)   { var hour = '0'+hour; }\n// var minutes = (minutes1 < 5 ? '0' : '') + minutes1;\nif(minute.toString().length == 1)   { var minute = '0'+minute; }\n\nmsg.payload = \"Last-time values: \" + hour + \":\" + minute;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":200,"wires":[[]],"icon":"node-red/status.svg"}]


Het project om de WiFi van de omvormer minder sterk te maken is gedaan en de Cap lite (STA) hangt dicht bij de omvormer en wordt gevoed vanaf de switch met een PoE adaptor. Het eerste PoE device alhier.

Het volgende project is een KWh meter in de meterkast te plaatsen tussen de hoofdschakelaar en de aardlekschakelaars (huis+PV) en zo te kunnen zien wat het verbruik is en de teruglevering.
Dit gaat later ook naar PVOutput met behulp van RS485.

Het was een een interessante tijd en veel nieuwe dingen erbij geleerd en ik hoop dat ik met hetgeen ik hier heb geschreven en NodeRed flows anderen te hebben geholpen.

Verder is het super dat Goodwe de MODBUS RTU toegankelijk heeft gemaakt via WiFi en zo het uitlezen zoveel gemakkelijker heeft gemaakt en het scapen van Sems overbodig heeft gemaakt.

[Voor 1% gewijzigd door msatter op 27-05-2021 16:11. Reden: Afbeelding NOdeRed interface toegevoegd.]


Acties:
  • +2Henk 'm!
  • Pinned

  • hpmkruit
  • Registratie: november 2009
  • Laatst online: 22:31
Even een bevestiging vanuit mijn kant dat het lokaal uitlezen van een 5000D-NS ook lukt na een firmware update door GoodWe.

Acties:
  • +1Henk 'm!

  • The Fatal
  • Registratie: maart 2009
  • Laatst online: 20:47
ThinkPad schreef op maandag 31 mei 2021 @ 17:00:
@The Fatal Kijk even in het menu van je omvormer welke firmware hij heeft. Laatste twee cijfers moet 14 of hoger zijn.

@No13 Even met het NL-talige nummer bellen?
2500xs is v1.13.13
2000xs is v1.02.08

Zal wel een mailtje sturen naar de support afdeling voor nieuwe firmware.

Acties:
  • +2Henk 'm!

  • Pinobigbird
  • Registratie: januari 2002
  • Laatst online: 01:23

Pinobigbird

doesn't share food!

@hpmkruit Zie Pinobigbird in "[GoodWe] Uitlezen inverters via USB"
0: Wait Mode
1: Normal
2: Error
4: Check Mode

Joey: Nice try. See the Netherlands is this make believe place where Peter Pan and Tinkerbell come from.
https://kattenoppasleiderdorp.nl
PV: 3080Wp ZO + 3465Wp NW = 6545Wp totaal 13°tilt


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

No13 schreef op maandag 31 mei 2021 @ 17:46:
[...]

Update: net wel iemand aan de lijn gekregen, mn ticket was inmiddels overdue en ze gaan informeren wat er mis gaat.
Great succes! 1.52.15 is nu de actuele versie, vanavond eens met python spelen 8)

Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

Op basis van de scripts die jullie allemaal al gemaakt hebben ben ik bezig geweest met een 'kale' python functie die zonder extra tools de communicatie met de omvormer voor zn rekening kan nemen. Deze komt dan in een docker containertje te draaien om iedere xx sec influx te voorzien van de data :)

Uiteindelijk is dit het verhaal geworden:
code:
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
import socket, time

def crc16(data: bytes):
    '''
    CRC-16-ModBus Algorithm
    '''
    data = bytearray(data)
    poly = 0xA001
    crc = 0xFFFF
    for b in data:
        crc ^= (0xFF & b)
        for _ in range(0, 8):
            if (crc & 0x0001):
                crc = ((crc >> 1) & 0xFFFF) ^ poly
            else:
                crc = ((crc >> 1) & 0xFFFF)
    return crc

def get_int(in_bytes):
    if type(in_bytes) is int:
        return in_bytes
    else:
        return int.from_bytes(in_bytes[:len(in_bytes)],'big')

def get_inverter_data(hostname,timeout=0.5):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
    s.settimeout(timeout)
    try:
        s.sendto(bytes.fromhex('7f0375940049d5c2'),(hostname,8899))
        data,address = s.recvfrom(4096)
        # do CRC check
        crc_data = data[-1:].hex()+data[-2:-1].hex() 
        crc_calc = hex(crc16(data[2:-2]))[2:]
        if(crc_data == crc_calc):
            inverter_data = {
                'error': 'no error',
                'vpv1': round(get_int(data[11:13])*0.1,2),
                'ipv1': round(get_int(data[13:15])*0.1,2),
                'vpv2': round(get_int(data[15:17])*0.1,2),
                'ipv2': round(get_int(data[17:19])*0.1,2),
                'vac': round(get_int(data[41:43])*0.1,2),
                'iac': round(get_int(data[47:49])*0.1,2),
                'fac': round(get_int(data[53:55])*0.01,2),
                'eday': round(get_int(data[93:95])*0.1,2),
                'etot': round(get_int(data[97:99])*0.1,2),
                'rssi': get_int(data[149:151]),
                'hours': get_int(data[101:103]),
                'temp': round(get_int(data[87:89])*0.1,2),
                'power': get_int(data[61:63]),
                'status': get_int(data[63:65]),
                'timestamp': time.mktime((2000+get_int(data[5]),get_int(data[6]),get_int(data[7]), get_int(data[8]), get_int(data[9]), get_int(data[10]),-1,-1,-1))
            }
            return(inverter_data)
        return {"error": "crc error"}
    except socket.timeout:
        return {"error": "timeout"}
    except Exception as e:
        return {"error":str(e)}


Dan nu nog een timer maken die met enige interval de output van get_inverter_data('ip van inverter') naar influx duwt (mits data['error'] == 'no error') :)

Acties:
  • +1Henk 'm!

  • theredone51
  • Registratie: januari 2004
  • Laatst online: 23:42
Proton_ schreef op donderdag 20 mei 2021 @ 15:53:
Het is intussen [GoodWe] Uitlezen inverters via UDP geworden ;)

Een tooltje om vanuit je eigen netwerk van de omvormer naar PVOutput te pushen heb ik hier op github gezet:
https://github.com/koen-lee/GoodweUDPToPvOutput
De release is self-contained linux-arm, dus draait na uitpakken direct op een Pi.

Resultaat is https://pvoutput.org/intraday.jsp?id=20978&sid=18868
Vandaag om 9u het topic gevonden + ticket aangemaakt, om 12u al de laatste firmware op de omvormer en zojuist de logging op kunnen zetten op basis jouw code / van lokale data. Bedankt _/-\o_

Acties:
  • +2Henk 'm!

  • wimpie
  • Registratie: september 1999
  • Niet online
JeroenE schreef op zondag 6 juni 2021 @ 18:13:
@wimpie Wij zijn in Nederland natuurlijk niet afhankelijk van zonnepanelen op daken; bovendien doet een beetje grote wolk voor de zon dat bijna net zo effectief.
Verkeerde tag, andere "wimpie" was paar jaar te laat :)

Divide and conquer.


Acties:
  • +4Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Toch de topictitel maar even wat gewijzigd ;)

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • Maasluip
  • Registratie: april 2002
  • Laatst online: 04-08 14:57

Maasluip

Frontpage Admin

Kabbelend watertje

In Nederland is ruim meer dan 7 GWp geïnstalleerd, als je dat op een zonnige dag in een keer af zou schakelen dan heb je wel een probleem. Misschien nog niet een blackout maar wel heel dicht in de buurt.

Als voorbeeld, dit is 3,9 GW die in een keer van het net gaat. Dat is zoals je ziet nog te verhapstukken

Áls de frequentie onder de 49 Hz komt moet volgens de richtlijnen de eerste stap worden genomen om belasting per direkt van het net te verwijderen.

In Duitsland kun je op een beetje zonnige dag op de piek wel 30 GW verwachten. Als dat in een keer van het net gaat is dat niet meer op te vangen. Dus ja, dit is een risico.

[Voor 11% gewijzigd door Maasluip op 07-06-2021 10:43]

Dat slof sigaretten met de pak melk - D/T-regels
Open Source landkaart


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

Maar in dat scenario zou je aannemen dat 1 'fabrikant' of 'actor' controle heeft over alle installaties (diverse merken).

De impact is niet te verwaarlozen maar het is ook niet waarschijnlijk dat 1 'partij' op de knop kan drukken om dit te veroorzaken.

Edit: Neemt niet weg dat ik voorstander ben van een lokale oplossing waar externe partijen alleen op uitnodiging toegang krijgen.

[Voor 20% gewijzigd door No13 op 07-06-2021 10:49]


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

wlmpie schreef op maandag 7 juni 2021 @ 20:16:
Ik gebruik nu de plugin "GoodWe inverter (via SEMS portal)" in domoticz. Die zou ik graag vervangen door de plugin "GoodWe inverter (local readout via UDP over wifi)" alleen moet iemand die laatste plugin nog schrijven ;-)
Of zou ik dat zelf in elkaar kunnen fabrieken? Wie helpt mij op weg?
Staat op mn todo 8)

Acties:
  • +1Henk 'm!

  • borft
  • Registratie: januari 2002
  • Laatst online: 03-08 10:16
wlmpie schreef op maandag 7 juni 2021 @ 20:16:
Ik gebruik nu de plugin "GoodWe inverter (via SEMS portal)" in domoticz. Die zou ik graag vervangen door de plugin "GoodWe inverter (local readout via UDP over wifi)" alleen moet iemand die laatste plugin nog schrijven ;-)
Of zou ik dat zelf in elkaar kunnen fabrieken? Wie helpt mij op weg?
nja, met de python lib van mij is het zo simpel als:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
from goodwe import Goodwe,GoodweStatus

ip = your_ip_here
gw = Goodwe(ip=ip)

try:
    data = gw.getData()
except Exception as e:
    print(f"failed: {e}")
    exit(0)

print(data)


je moet dan nog wel wat met de data doen natuurlijk, maar mogelijk dat je dat in de bestaande plugin kunt hangen.

Acties:
  • +1Henk 'm!
  • Pinned

  • Pinobigbird
  • Registratie: januari 2002
  • Laatst online: 01:23

Pinobigbird

doesn't share food!

@Onno ! Ik heb 808.808.06 op m'n GW5K-DT en het lokaal uitlezen kan gewoon. De voorwaarde "ARM firmware of 13 or higher" die je in dit topic regelmatig tegenkomt is alleen voor sommige modellen van toepassing.
De test is of je met de app SolarGo kan werken. Zo ja, dan zit je goed.

Joey: Nice try. See the Netherlands is this make believe place where Peter Pan and Tinkerbell come from.
https://kattenoppasleiderdorp.nl
PV: 3080Wp ZO + 3465Wp NW = 6545Wp totaal 13°tilt


Acties:
  • +1Henk 'm!

  • Onno !
  • Registratie: december 2004
  • Laatst online: 03-08 14:53
Thanks! SolarGo werkt bij mij, dus dat zit dan wel goed! Binnenkort dan eens hardware aanschaffen om te gaan spelen (RPi, P1 port splitter, Domoticz installaren etc.)

Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
De AP (access point) kant van de omvormer is niet uitschakelbaar en die zou moeten luisteren op 10.10.100.253.

De STA (station) kant verbind zich met de router. SolarGo doet een broadcast om de omvormer te vinden en ik kan dat dus alleen via de AP.

De hier getoonde software kan zowel via AP en/of via de STA werken zolang je maar het juiste IP adres gebruikt.....van de omvormer en hetzelfde netwerksegment zit. Ik pas zelf routing/NAT toe om vanuit een 192.168.x.x/24 netwerk te communiceren met de omvormer in het 10.10.100.253/24.

Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Gewoon een vast IP-adres toewijzen aan de Goodwe vanuit je router, dan is het hele broadcast gebeuren om hem te vinden niet nodig.

Kun je daarna gelijk in je router het internetverkeer voor dat IP-adres van de Goodwe blokkeren zodat hij geen contact meer legt met het Goodwe moederschip (ter voorkoming van bijv. een ongevraagde firmware update waardoor lokaal uitlezen misschien niet meer werkt). In de meeste routers zit wel iets van 'parental controls' waarmee je dit voor elkaar kunt krijgen (normaal bedoeld voor de tablet van je kids bijv. :+ ).

[Voor 7% gewijzigd door ThinkPad op 23-06-2021 08:43]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Houd er wel rekening mee dat de omvormer uitschakelt zodra het donker is. Tijdens je nachtdienst zul je dus geen communicatie met de omvormer voor elkaar kunnen krijgen :P

Hij zit bij mij ook in een apart netwerk (omdat hij ook eigen netwerk blijft uitzenden en daar het wachtwoord van je wifi zichtbaar blijft :/ ), als je je firewall regels in je router goed hebt staan zou dat moeten kunnen. De omvormer kunnen pingen is een goede eerste diagnose.

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • msatter
  • Registratie: maart 2021
  • Niet online
Zodra je de omvormer aanmeld bij een router (STA) is het router wachtwoord uit te lezen zolang je ook niet het wachtwoord aan de AP kant van de omvormer aanpast.

Ik ben helemaal overgegaan op het benaderen via de AP en de STA zijde van de omvormer is niet meer actief. Ook heb ik een fysieke aanpassing gemaakt door de antenne in de WiFi stick los te koppelen.

Ik heb daarom een WiFi module vlakbij moeten plaatsen om dan via een netwerkkabel de omvormer te benaderen.

Als de firmware wil laten bijwerken dan heeft de omvormer wel contact nodig met het internet. De WiFi module die ik geplaatst heb is ook een router met een compleet instelbare firewall. Ik dan ook via de AP het Internet vrijgeven.

[Voor 19% gewijzigd door msatter op 25-06-2021 10:48]


Acties:
  • +1Henk 'm!

  • wlmpie
  • Registratie: oktober 2007
  • Laatst online: 20:10
Ik heb inmiddels alles werkend en ook het sturen van de data naar domoticz.
Ik heb de flow van @ThinkPad als basis gebruikt en ik maak vervolgens in aparte functies mqtt berichtjes aan voor domoticz (met mosquito als broker)
Hieronder wat screenshots ter inspiratie.
Een echte programmeur zou dit waarschijnlijk veel slimmer doen, maar het werkt.

Acties:
  • +1Henk 'm!

  • Proton_
  • Registratie: november 2011
  • Laatst online: 22:58

Proton_

Team Welles

@ThinkPad De waarde begint dan dus ook twee bytes eerder :)

'19 Kona na '15 Zoe, douchen met wtw en Auer Edel Eau


Acties:
  • +2Henk 'm!

  • Proton_
  • Registratie: november 2011
  • Laatst online: 22:58

Proton_

Team Welles

@ThinkPad nu haal je etotal van offset 97 (0x61). Daar staat in twee bytes, 16 bit, 83 D5 (33739->3373.9 kWh). Als je meer dan 6553.5 kWh opgewekt hebt past dat niet meer, en dat haalt je omvormer wel in zijn levensduur.

Als je vier bytes, 32 bits, van offset 95 (0x59) haalt, staat er 00 00 83 D5. Dat is ook 3373.9 kWh, maar dan kan je 429496729.5 kWh opwekken tot het niet meer past :)

Alleen etotal is volgens mij 32 bit. Voor de rest is 16 bits genoeg.

[Voor 8% gewijzigd door Proton_ op 27-06-2021 20:24]

'19 Kona na '15 Zoe, douchen met wtw en Auer Edel Eau


Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Ik snap hem nu, dankje :) Zowel etotal, power, workhours zijn 32-bit inderdaad. Alle overige waardes lijken 16-bit te zijn. Zal zo m'n code in eerdere post even weer bijwerken.

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • The Fatal
  • Registratie: maart 2009
  • Laatst online: 20:47
borft schreef op donderdag 10 juni 2021 @ 09:18:
[...]


haha, ik ben blij dat het werkt, maar nu returned de functie dus soms een dictionary en soms een int ;) dit is eigenlijk precies waar de excepties voor zijn. Maar ik raak off-topic. Mooi dat het werkt!
om toch nog eventjes hier op terug te komen.
Ik merkte in logging wat issues, als bv de omvormer offline gaat, was de laatste status online. Dit omdat de laatste keer dat het script de omvormer kon bereiken, was hij nog online.
Ook het opgewekte actuele vermogen bleef op de laatste waarde staan. Dat is immers de laatste valide waarde die opgehaald is. Dat ziet er een beetje vreemd uit in de grafieken en statussen.

Dit heb ik nu opgelost door als de omvormer niet te bereiken is (geen int 0 meer sturen :) ) ,maar een status offline te sturen en een vermogen van 0.
Zo worden ook mijn statussen in HA goed weer gegeven.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    def getData(self, retries=3):
        while retries > 0:
            retries -= 1
            try:
                return self._getData(self._ip, self._port)
            except Exception as e:
                print(f'Retrying {retries}')
                if retries == 0:
                    defaultData = {
                        'voltage_dc_1': None, 
                        'current_dc_1': None, 
                        'voltage_ac_1': None, 
                        'current_ac_1': None, 
                        'frequency_ac_1': None, 
                        'power_ac': 0, 
                        'status': 'Offline', 
                        'temperature': None, 
                        'power_dc_1': 0}
                    return defaultData
                pass

Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Stap 1 bij lokaal uitlezen is eerst kijken of je de omvormer kunt uitlezen met de ‘SolarGo’ app. Als dat niet werkt dan moet je eerst Goodwe support contacten om je firmware bij te werken.

[Voor 31% gewijzigd door ThinkPad op 06-07-2021 21:12]

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +2Henk 'm!

  • Tribunus
  • Registratie: juni 2004
  • Laatst online: 04-08 15:22
ThinkPad schreef op dinsdag 6 juli 2021 @ 21:11:
Stap 1 bij lokaal uitlezen is eerst kijken of je de omvormer kunt uitlezen met de ‘SolarGo’ app. Als dat niet werkt dan moet je eerst Goodwe support contacten om je firmware bij te werken.
Dat lukt,

En ik kan deze ook uitlezen via node red op HA. Dus ik krijg netjes de waardes terug in node-red. Nu is het alleen zaak dat ik deze waarden ook fatsoenlijk in HA krijg als zijnde een sensor die ik kan toevoegen aan het dashbord en later via Grafana etc.

Alleen krijg ik dus een API error, maar wellicht past deze vraag wat beter in het home assistant topic :9

[Voor 24% gewijzigd door Tribunus op 06-07-2021 21:17]


Acties:
  • +1Henk 'm!

  • ThinkPad
  • Registratie: juni 2005
  • Laatst online: 22:59

ThinkPad

Moderator Duurzame Energie & Domotica
Ja, dat is dan meer een HASS vraagstuk inderdaad.

Gas besparen door CV-tuning | Elektriciteit besparen
Geen vragen via privébericht die ook via het forum kunnen a.u.b.


Acties:
  • +1Henk 'm!

  • Proton_
  • Registratie: november 2011
  • Laatst online: 22:58

Proton_

Team Welles

Proton_ schreef op donderdag 20 mei 2021 @ 16:24:
De temperatuur stuur ik mee op https://github.com/koen-l...eUdpPoller/Program.cs#L68 , ik weet niet waarom PvOutput dat niet slikt...
Het lek is boven; vanuit de installatie op mijn vorige huis uit 2013 stond er nog een Weather Underground koppeling in PVOutput die niet meer werkt.
Sinds die weggehaald is, wordt ook de invertertemperatuur netjes in PVOutput gelogd.

'19 Kona na '15 Zoe, douchen met wtw en Auer Edel Eau


Acties:
  • +1Henk 'm!

  • No13
  • Registratie: januari 2001
  • Laatst online: 03-08 22:02

No13

/me was here

Ik heb hier een losse kWh meter met s0 aansluiting, die wijkt minder dan 1% af vergeleken met de cijfers van mn omvormer. Soms net wat meer, soms net minder maar geen structurele afwijkingen...

Acties:
  • +1Henk 'm!

  • Proton_
  • Registratie: november 2011
  • Laatst online: 22:58

Proton_

Team Welles

Om verwarring te voorkomen; apparent power is in VA en niet in watt.
Voor elk sommetje over opslag, benodigd vermogen, eigen verbruik, stroom op 0 zetten etc is VA ook niet bijster interessant, het is immers altijd gratis op te wekken (binnen de stroom die de wisselrichter aan kan).

'19 Kona na '15 Zoe, douchen met wtw en Auer Edel Eau

Pagina: 1


Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Microsoft Xbox Series X LG CX Google Pixel 5a 5G Sony XH90 / XH92 Samsung Galaxy S21 5G Sony PlayStation 5 Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True