serek4 / node-red-sofar-inverter

node-red server/proxy for sofar inverter
MIT License
24 stars 8 forks source link

decoded data SOFAR 4.4KTLX-G3 with LSW-3 (sn:23xxxxxxxx) #10

Closed grzegorzgrzeszkowiak closed 1 year ago

grzegorzgrzeszkowiak commented 1 year ago

Cześć,

Podsyłam fragment kodu do obsługi nowych logerów, których serial zaczyna się na 23xxxxxxxx. Nie jest to odszyfrowana cała wiadomość, ale większości wystarczy.

case 1445: // Logger 23xxxxxxxxx
    data.loggerSN = buffer.readUInt32LE(0x07);
    data.tOperationTime = buffer.readUInt32LE(0x0E);
    data.inverterSN = (buffer.toString('utf8', 0x20, 0x30));
    data.inverterPlateTemp = buffer.readUInt8(0x51) ;
    data.inverterRadiatorTemp = buffer.readUInt8(0x55);     
    data.VDC1 = buffer.readUInt16BE(0x166) / 10;
    data.VDC2 = buffer.readUInt16BE(0x16C) / 10;
    data.IDC1 = buffer.readUInt16BE(0x168) / 100;
    data.IDC2 = buffer.readUInt16BE(0x16E) / 100;
    data.PDC1 = buffer.readUInt8(0x16B) / 100;
    data.PDC2 = buffer.readUInt8(0x171) / 100;      
    data.IAC1 = buffer.readUInt16BE(0xDA) / 100;
    data.IAC2 = buffer.readUInt16BE(0xF0) / 100;
    data.IAC3 = buffer.readUInt16BE(0x106) / 100;
    data.VAC1 = buffer.readUInt16BE(0xD8) / 10;
    data.VAC2 = buffer.readUInt16BE(0xEE) / 10;
    data.VAC3 = buffer.readUInt16BE(0x104) / 10;
    data.fAC = buffer.readUInt16BE(0xC6) / 100;
    data.currentPower = buffer.readUInt16BE(0xC8)/100;
    data.eToday = buffer.readUInt32BE(0x286) / 100;
    data.eTotal = buffer.readUInt32BE(0x28A) / 10;
    data.CombinerVoltageGroup1 = buffer.readUInt16BE(0x2E0) / 10;
    data.CombinerVoltageGroup2 = buffer.readUInt16BE(0x2E6) / 10;
    data.StringCurrentGroup1 = buffer.readUInt8(0x2E3) / 100;
    data.StringCurrentGroup2 = buffer.readUInt8(0x2E9) / 100;
    data.Vbus = buffer.readUInt16BE(0x2D2) / 10;
    data.year = buffer.readUInt8(0x79);
    data.month = buffer.readUInt8(0x7B);
    data.day = buffer.readUInt8(0x7D);
    data.hour = buffer.readUInt8(0x7F);
    data.minute = buffer.readUInt8(0x81);
    data.second = buffer.readUInt8(0x83);
serek4 commented 1 year ago

jaki masz falownik?

grzegorzgrzeszkowiak commented 1 year ago

Ja mam SOFAR 4,4 KTLX - G3. Do tego jest logger LSW-3

serek4 commented 1 year ago

@grzegorzgrzeszkowiak wprowadziłem małe zmiany:

buffer.readUInt8(<offset>)

zamieniłem na

buffer.readUInt16BE(<offset> - 1)

czyli odczytuje te wartości o 1 bajt wcześniej jako UInt16, bo podejrzewam, że przed każdym z tych UInt8 jest bajt o wartości 0x00.
Dodatkowo, temperatury zamiast UInt odczytuje jako Int, żeby uwzględnić ujemne temperatury

-   data.inverterPlateTemp = buffer.readUInt8(0x51);
+   data.inverterPlateTemp = buffer.readInt16BE(0x50);
-   data.inverterRadiatorTemp = buffer.readUInt8(0x55);
+   data.inverterRadiatorTemp = buffer.readInt16BE(0x54);

-   data.PDC1 = buffer.readUInt8(0x16b) / 100;
+   data.PDC1 = buffer.readUInt16BE(0x16a) / 100;
-   data.PDC2 = buffer.readUInt8(0x171) / 100;
+   data.PDC2 = buffer.readUInt16BE(0x170) / 100;

-   data.StringCurrentGroup1 = buffer.readUInt8(0x2e3) / 100;
+   data.StringCurrentGroup1 = buffer.readUInt16BE(0x2e2) / 100;
-   data.StringCurrentGroup2 = buffer.readUInt8(0x2e9) / 100;
+   data.StringCurrentGroup2 = buffer.readUInt16BE(0x2e8) / 100;

-   data.year = buffer.readUInt8(0x79);
+   data.year = buffer.readUInt16BE(0x78);
-   data.month = buffer.readUInt8(0x7b);
+   data.month = buffer.readUInt16BE(0x7a);
-   data.day = buffer.readUInt8(0x7d);
+   data.day = buffer.readUInt16BE(0x7c);
-   data.hour = buffer.readUInt8(0x7f);
+   data.hour = buffer.readUInt16BE(0x7e);
-   data.minute = buffer.readUInt8(0x81);
+   data.minute = buffer.readUInt16BE(0x80);
-   data.second = buffer.readUInt8(0x83);
+   data.second = buffer.readUInt16BE(0x82);

Sprawdzisz w wolnej chwili czy po moich zmianach dane z inwertera nadal są poprawne? Tu masz cały zmodyfikowany case

    case 1445: // data - KTLX-G3
        data.loggerSN = buffer.readUInt32LE(0x07);
        data.tOperationTime = buffer.readUInt32LE(0x0E);
        data.inverterSN = (buffer.toString('utf8', 0x20, 0x30));
        data.inverterPlateTemp = buffer.readInt16BE(0x50);
        data.inverterRadiatorTemp = buffer.readInt16BE(0x54);
        data.VDC1 = buffer.readUInt16BE(0x166) / 10;
        data.VDC2 = buffer.readUInt16BE(0x16C) / 10;
        data.IDC1 = buffer.readUInt16BE(0x168) / 100;
        data.IDC2 = buffer.readUInt16BE(0x16E) / 100;
        data.PDC1 = buffer.readUInt16BE(0x16A) / 100;
        data.PDC2 = buffer.readUInt16BE(0x170) / 100;
        data.IAC1 = buffer.readUInt16BE(0xDA) / 100;
        data.IAC2 = buffer.readUInt16BE(0xF0) / 100;
        data.IAC3 = buffer.readUInt16BE(0x106) / 100;
        data.VAC1 = buffer.readUInt16BE(0xD8) / 10;
        data.VAC2 = buffer.readUInt16BE(0xEE) / 10;
        data.VAC3 = buffer.readUInt16BE(0x104) / 10;
        data.fAC = buffer.readUInt16BE(0xC6) / 100;
        data.currentPower = buffer.readUInt16BE(0xC8) / 100;
        data.eToday = buffer.readUInt32BE(0x286) / 100;
        data.eTotal = buffer.readUInt32BE(0x28A) / 10;
        data.CombinerVoltageGroup1 = buffer.readUInt16BE(0x2E0) / 10;
        data.CombinerVoltageGroup2 = buffer.readUInt16BE(0x2E6) / 10;
        data.StringCurrentGroup1 = buffer.readUInt16BE(0x2E2) / 100;
        data.StringCurrentGroup2 = buffer.readUInt16BE(0x2E8) / 100;
        data.Vbus = buffer.readUInt16BE(0x2D2) / 10;
        data.year = buffer.readUInt16BE(0x78);
        data.month = buffer.readUInt16BE(0x7A);
        data.day = buffer.readUInt16BE(0x7C);
        data.hour = buffer.readUInt16BE(0x7E);
        data.minute = buffer.readUInt16BE(0x80);
        data.second = buffer.readUInt16BE(0x82);

        // node.warn(data);
        return {
            payload: data,
            topic: 'data'
        };
grzegorzgrzeszkowiak commented 1 year ago

Sprawdziłem i wygląda, że działa poprawnie. Faktycznie, masz rację z tymi zerowymi bajtami.

Dodatkowo:

  1. W tej paczce 1445 bajtów jest jeszcze kilka wartości, które się zmieniają (np. numer wiadomości), ale nie były mi potrzebne i je wyciąłem.
  2. Nie wyciąłem InverterSN i wysłałem do Ciebie, a ta zmienna zawiera bzdury (jest niepoprawnie dekodowana) - lepiej to usuń z kodu.
  3. Mogę Ci podrzucić jakiś zestaw zapisanych buforów, jeśli chcesz się pomęczyć i poszukać jeszcze dodatkowych informacji w nich zaszytych.
serek4 commented 1 year ago

podeślij popatrzę co tam masz

grzegorzgrzeszkowiak commented 1 year ago

sofar.txt

serek4 commented 1 year ago

@grzegorzgrzeszkowiak te adresy zwracają poprawny SN inwertera?

data.inverterSN = buffer.toString('utf8', 0x8E, 0x9C);
grzegorzgrzeszkowiak commented 1 year ago

@serek4, potwierdzam - poprawny SN.