# Solar-log 500 einlesen über MODBUS TCP



## Juergena (30 Dezember 2020)

Hallo zusammen,

erst einmal möchte ich Danke sagen an @Blockmove, der mit einem kleinen Denkanstoß dafür sorgte, dass ich mir mal schnell Gedanken machte über meine Solaranlage. Man muss dazu sagen, dass dieses Projekt erst ging, nachdem ich meinen Solar-log 500 über die Firmware 2.8.1 Build 49 gezogen hatte, aktuell Firmware 3.6.0 Build 99. Dadurch hatte ich Zugriff auf Modbus TCP. Ich habe die Bausteine nur mit der S7-1500 gemacht, bei anderen Steuerungen müssen eben Anpassungen gemacht werden.

Funktionsbaustein für den Solar-log um über Modbus TCP an die Daten zu kommen:


```
FUNCTION_BLOCK "Solarlog"
TITLE = Solarlog500
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Juergen
VERSION : 0.1
   VAR_INPUT 
      Modbus_REQ : Bool;   // Activates the requested transmission if TRUE
      Modbus_Disconnect : Bool;   // Initiates a disconnect operation
      Modbus_Mode : USInt;   // Specifies the type of request: read, write or diagnostic
      Modbus_Data_Addr : UDInt;   // Specifies the starting address of the data to be accessed in the Modbus client
      Modbus_Data_LEN : UInt;   // Specifies the number of bits or words to be accessed
      Modbus_InterfaceId : UInt;   // HW-identifier of IE-interface submodule
      Modbus_ID : CONN_OUC;   // connection reference / identifier
      Modbus_ConnectionType : Byte;   // type of connection: 11=TCP/IP, 19=UDP (17=TCP/IP)
      Modbus_ActiveEstablished : Bool;   // active/passive connection establishment
      Modbus_RemotePort : UInt;   // remote UDP/TCP port number
      "TCPIP_V4_Addr[1]" : Byte;   // Remote IP Addr 1 (IPv4)
      "TCPIP_V4_Addr[2]" : Byte;   // Remote IP Addr 2 (IPv4)
      "TCPIP_V4_Addr[3]" : Byte;   // Remote IP Addr 3 (IPv4)
      "TCPIP_V4_Addr[4]" : Byte;   // Remote IP Addr 4 (IPv4)
   END_VAR


   VAR_OUTPUT 
      Modbus_Done : Bool;   // Instruction finished without error
      Modbus_Busy : Bool;   // Modbus transaction in progress
      Modbus_Error : Bool;   // Instruction finished with error
      Modbus_Status : Word;   // Detailed error information
      "lastUpdateTime_Unix-Format" : UDInt;   // Unixtime, wann das letzte Registerupdate erfolgt ist. 0=noch keine Live-Daten (Einheit = Sec)
      "lastUpdate_DT-Format" {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // DT-Format, wann das letzte Registerupdate erfolgt ist. 0=noch keine Live-Daten (Einheit = DT-Format)
      Pac : UDInt;   // Gesamte Leistung Pac von allen Wechselrichtern und Zählern im Wechselrichtermodus (Einheit = W)
      Pdc : UDInt;   // Gesamte Leistung Pdc von allen Wechselrichtern (Einheit = W)
      Uac : UInt;   // Durchschnittliche Spannung Uac aller Wechselrichter (Einheit = V)
      Udc : UInt;   // Durchschnittliche Spannung Udc aller Wechselrichter (Einheit = V)
      "Daily yield" : UDInt;   // Summierter Tagesertrag aller Wechselrichter (Einheit = Wh)
      "Yesterday yield" : UDInt;   // Summierter gestriger Tagesertrag aller Wechselrichter (Einheit = Wh)
      "Monthly yield" : UDInt;   // Summierter Monatsertrag aller Wechselrichter (Einheit = Wh)
      "Yearly yield" : UDInt;   // Summierter Jahresertrag aller Wechselrichter (Einheit = Wh)
      "Total yield" : UDInt;   // Gesamtertrag aller Wechselrichter (Einheit = Wh)
      "Pac consumption" : UDInt;   // momentaner Gesamtverbrauch Pac aller Verbrauchszähler (Einheit = W)
      "Daily yield consumption" : UDInt;   // Summierter Tages-Verbrauch aller Verbrauchszähler (Einheit = Wh)
      "Yesterday yield consumption" : UDInt;   // Summierter Verbrauch des gestrigen Tages; alle Verbrauchszähler (Einheit = Wh)
      "Monthly yield consumption" : UDInt;   // Summierter Verbrauch des Monats; alle Verbrauchszähler (Einheit = Wh)
      "Yearly yield consumption" : UDInt;   // Summierter Verbrauch des Jahres; alle Verbrauchszähler (Einheit = Wh)
      "Total yield consumption" : UDInt;   // Summierter Gesamtverbrauch; alle Verbrauchszähler (Einheit = Wh)
      TotalPower : UDInt;   // Installierte Generatorleistung (Einheit = Wh/Wp)
   END_VAR


   VAR 
      MB_CLIENT_Instance {InstructionName := 'MB_CLIENT'; LibVersion := '5.2'} : MB_CLIENT;
      Modbus_Connection {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'} : TCON_IP_v4 := (64, 1, (), true, ([()]), 502, ());
      RAW_DATA { S7_SetPoint := 'True'} : Array[0..31] of UInt;
   END_VAR


   VAR_TEMP 
      Sekunden_Pro_Tag : UDInt;
      Tage_im_Gemeinjahr : UDInt;
      Tage_in_4_Jahren : UDInt;
      Tage_in_100_Jahren : UDInt;
      Tage_in_400_Jahren : UDInt;
      TagN_AD_1970_01_01 : UDInt;
      TagN : UDInt;
      Sekunden_seit_Mitternacht : UDInt;
      temp : UDInt;
      tJahr : UDInt;
      tMonat : UDInt;
      tTag : UDInt;
      tStunde : UDInt;
      tMinute : UDInt;
      tSekunde : UDInt;
   END_VAR




BEGIN
    // Initialisierung
        
        //ModBus-Parameter
        #Modbus_Connection.InterfaceId := #Modbus_InterfaceId;
        #Modbus_Connection.ID := #Modbus_ID;
        #Modbus_Connection.ConnectionType := #Modbus_ConnectionType;
        #Modbus_Connection.ActiveEstablished := #Modbus_ActiveEstablished;
        
        //TCPIP_Adresse initialisieren
        #Modbus_Connection.RemoteAddress.ADDR[1] := #"TCPIP_V4_Addr[1]";
        #Modbus_Connection.RemoteAddress.ADDR[2] := #"TCPIP_V4_Addr[2]";
        #Modbus_Connection.RemoteAddress.ADDR[3] := #"TCPIP_V4_Addr[3]";
        #Modbus_Connection.RemoteAddress.ADDR[4] := #"TCPIP_V4_Addr[4]";
        
    
    //ModBus-Daten lesen
    #MB_CLIENT_Instance(REQ:=#Modbus_REQ,
                        DISCONNECT:=#Modbus_Disconnect,
                        MB_MODE:=#Modbus_Mode,
                        MB_DATA_ADDR:=#Modbus_Data_Addr,
                        MB_DATA_LEN:=#Modbus_Data_LEN,
                        DONE=>#Modbus_Done,
                        BUSY=>#Modbus_Busy,
                        ERROR=>#Modbus_Error,
                        STATUS=>#Modbus_Status,
                        MB_DATA_PTR:=#RAW_DATA,
                        CONNECT:=#Modbus_Connection);
    
    //--------------------- Solarlog RAW-Daten richtig einordnen ---------------------
    //
    
        //Unix-Zeitstempel einlesen (Einheit = Sec)
        
        #"lastUpdateTime_Unix-Format".%W0 := #RAW_DATA[0];
        #"lastUpdateTime_Unix-Format".%W1 := #RAW_DATA[1];
        
        //Gesamtleistung Pac aller Wechselrichter einlesen (Einheit = W)
        
        #Pac.%W0 := #RAW_DATA[2];
        #Pac.%W1 := #RAW_DATA[3];
        
        //Gesamtleistung Pdc aller Wechselrichter einlesen (Einheit = W)
        
        #Pdc.%W0 := #RAW_DATA[4];
        #Pdc.%W1 := #RAW_DATA[5];
        
        //Durchschnittliche Spannung Uac aller Wechselrichter einlesen (Einheit = V)
        
        #Uac := #RAW_DATA[6];
        
        //Durchschnittliche Spannung Udc aller Wechselrichter einlesen (Einheit = V)
        
        #Udc := #RAW_DATA[7];
        
        
        //Summierter Tagesertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Daily yield".%W0 := #RAW_DATA[8];
        #"Daily yield".%W1 := #RAW_DATA[9];
        
        //Summierter gestriger Tagesertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Yesterday yield".%W0 := #RAW_DATA[10];
        #"Yesterday yield".%W1 := #RAW_DATA[11];
        
        //Summierter Monatsertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Monthly yield".%W0 := #RAW_DATA[12];
        #"Monthly yield".%W1 := #RAW_DATA[13];
        
        //Summierter Jahresertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Yearly yield".%W0 := #RAW_DATA[14];
        #"Yearly yield".%W1 := #RAW_DATA[15];
        
        //Gesamtertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Total yield".%W0 := #RAW_DATA[16];
        #"Total yield".%W1 := #RAW_DATA[17];
        
        //Momentaner Gesamtverbrauch Pac aller Verbrauchszaehler einlesen (Einheit = W)
        
        #"Pac consumption".%W0 := #RAW_DATA[18];
        #"Pac consumption".%W1 := #RAW_DATA[19];
        
        //summierter Tagesverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Daily yield consumption".%W0 := #RAW_DATA[20];
        #"Daily yield consumption".%W1 := #RAW_DATA[21];
        
        //summierter gestriger Tagesverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Yesterday yield consumption".%W0 := #RAW_DATA[22];
        #"Yesterday yield consumption".%W1 := #RAW_DATA[23];
        
        //summierter Monatsverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Monthly yield consumption".%W0 := #RAW_DATA[24];
        #"Monthly yield consumption".%W1 := #RAW_DATA[25];
        
        //summierter Jahresverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Yearly yield consumption".%W0 := #RAW_DATA[26];
        #"Yearly yield consumption".%W1 := #RAW_DATA[27];
        
        //summierter Gesamtverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Total yield consumption".%W0 := #RAW_DATA[28];
        #"Total yield consumption".%W1 := #RAW_DATA[29];
        
        //installierte Generatorleistung einlesen (Einheit = Wh/Wp)
        
        #TotalPower.%W0 := #RAW_DATA[30];
        #TotalPower.%W1 := #RAW_DATA[31];
        
    
    
    
    //Unix-Zeitstempel in DT-Format wandeln
    //
    //Initialisierung
    
    #Sekunden_Pro_Tag := 86400; // 24h * 60m * 60s
    #Tage_im_Gemeinjahr := 365; //kein Schaltjahr
    #Tage_in_4_Jahren := #Tage_im_Gemeinjahr * 4 + 1; // 4 * 365 +1
    #Tage_in_100_Jahren := #Tage_im_Gemeinjahr * 100 + 25 - 1; // 100 * 365 + 25 - 1
    #Tage_in_400_Jahren := #Tage_im_Gemeinjahr * 400 + 100 - 4 + 1; // 400 * 365 + 100 - 4 + 1
    #TagN_AD_1970_01_01 := 719468; //Tagnummer bezogen auf den 1. Maerz des Jahres "Null"
    
    //------------------------------------------------------------------------------------------------------
    
    #TagN := #TagN_AD_1970_01_01 + #"lastUpdateTime_Unix-Format" / #Sekunden_Pro_Tag;
    #Sekunden_seit_Mitternacht := #"lastUpdateTime_Unix-Format" MOD #Sekunden_Pro_Tag;
    
    //Schaltjahrregel des Gregorianischen Kalenders
    //Jedes durch 100 teilbare Jahr ist kein Schaltjahr, es sei denn, es ist durch 400 teilbar
    
    #temp := 4 * (#TagN + #Tage_in_100_Jahren + 1) / #Tage_in_400_Jahren - 1;
    #tJahr := 100 * #temp;
    #TagN -= #Tage_in_100_Jahren * #temp + #temp / 4;
    
    //Schaltjahrregel des Julianischen Kalenders
    //Jedes durch 4 teilbare Jahr ist ein Schaltjahr
    
    #temp := 4 * (#TagN + #Tage_im_Gemeinjahr + 1) / #Tage_in_4_Jahren - 1;
    #tJahr += #temp;
    #TagN -= #Tage_im_Gemeinjahr * #temp + #temp / 4;
    
    //TagN enthaelt jetzt nur noch die Tage des errechneten Jahres bezogen auf den 1. Maerz
    
    #tMonat := (5 * #TagN + 2) / 153;
    #tTag := #TagN - (#tMonat * 153 + 2) / 5 + 1;
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von Maerz bis Juli
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von August bis Dezember
    //      31 + 28                Tage fuer Januer und Februar (siehe unten)
    //+2: Justierung der Rundung
    //+1: Der erste Tag im Monat ist 1 (und nicht 0)
    
    #tMonat += 3; // vom Jahr, das am 1. Maerz beginnt auf unser normales Jahr umrechnen
    IF (#tMonat > 12) THEN
        //Monate 13 und 14 entsprechen 1 (Januar) und 2 (Februar) des naechsten Jahres
        #tMonat -= 12;
        #tJahr += #tJahr;
    END_IF;
    
    #tStunde := #Sekunden_seit_Mitternacht / 3600;
    #tMinute := #Sekunden_seit_Mitternacht MOD 3600 / 60;
    #tSekunde := #Sekunden_seit_Mitternacht MOD 60;
    
    //DTL zusammenbauen
    
    #"lastUpdate_DT-Format".YEAR := UDINT_TO_UINT(#tJahr);
    #"lastUpdate_DT-Format".MONTH := UDINT_TO_USINT(#tMonat);
    #"lastUpdate_DT-Format".DAY := UDINT_TO_USINT(#tTag);
    #"lastUpdate_DT-Format".HOUR := UDINT_TO_USINT(#tStunde);
    #"lastUpdate_DT-Format".MINUTE := UDINT_TO_USINT(#tMinute);
    #"lastUpdate_DT-Format".SECOND := UDINT_TO_USINT(#tSekunde);
    
END_FUNCTION_BLOCK
```

Und da ich dann auch im FB für den Solar-log die UNIX Zeit in DTL umwandeln musste und nirgends ein Baustein gerade Griffbereit hatte, griff ich auf Wikipedia zu und formte den Code in einen SCL Baustein um und falls den Jemand mal in Zukunft braucht dann kann er sich auch hier verweilen:


```
FUNCTION "Unixzeit_Nach_DTL" : Void
TITLE = Unixzeit_Nach_DTL
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Juergen
VERSION : 0.1
   VAR_INPUT 
      Unixtime : UDInt;
   END_VAR


   VAR_OUTPUT 
      Datum_Uhrzeit {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
   END_VAR


   VAR_TEMP 
      Sekunden_Pro_Tag : UDInt;
      Tage_im_Gemeinjahr : UDInt;
      Tage_in_4_Jahren : UDInt;
      Tage_in_100_Jahren : UDInt;
      Tage_in_400_Jahren : UDInt;
      TagN_AD_1970_01_01 : UDInt;
      TagN : UDInt;
      Sekunden_seit_Mitternacht : UDInt;
      temp : UDInt;
      tJahr : UDInt;
      tMonat : UDInt;
      tTag : UDInt;
      tStunde : UDInt;
      tMinute : UDInt;
      tSekunde : UDInt;
   END_VAR




BEGIN
    //Initialisierung
    
    #Sekunden_Pro_Tag := 86400; // 24h * 60m * 60s
    #Tage_im_Gemeinjahr := 365; //kein Schaltjahr
    #Tage_in_4_Jahren := #Tage_im_Gemeinjahr * 4 +1; // 4 * 365 +1
    #Tage_in_100_Jahren := #Tage_im_Gemeinjahr * 100 + 25 - 1; // 100 * 365 + 25 - 1
    #Tage_in_400_Jahren := #Tage_im_Gemeinjahr * 400 + 100 - 4 + 1; // 400 * 365 + 100 - 4 + 1
    #TagN_AD_1970_01_01 := 719468; //Tagnummer bezogen auf den 1. Maerz des Jahres "Null"
    
    //------------------------------------------------------------------------------------------------------
    
    #TagN := #TagN_AD_1970_01_01 + #Unixtime / #Sekunden_Pro_Tag;
    #Sekunden_seit_Mitternacht := #Unixtime MOD #Sekunden_Pro_Tag;
    
    //Schaltjahrregel des Gregorianischen Kalenders
    //Jedes durch 100 teilbare Jahr ist kein Schaltjahr, es sei denn, es ist durch 400 teilbar
    
    #temp := 4 * (#TagN + #Tage_in_100_Jahren + 1) / #Tage_in_400_Jahren - 1;
    #tJahr := 100 * #temp;
    #TagN -= #Tage_in_100_Jahren * #temp + #temp / 4;
    
    //Schaltjahrregel des Julianischen Kalenders
    //Jedes durch 4 teilbare Jahr ist ein Schaltjahr
    
    #temp := 4 * (#TagN + #Tage_im_Gemeinjahr + 1) / #Tage_in_4_Jahren - 1;
    #tJahr += #temp;
    #TagN -= #Tage_im_Gemeinjahr * #temp + #temp / 4;
    
    //TagN enthaelt jetzt nur noch die Tage des errechneten Jahres bezogen auf den 1. Maerz
    
    #tMonat := (5 * #TagN + 2) / 153;
    #tTag := #TagN - (#tMonat * 153 + 2) / 5 + 1;
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von Maerz bis Juli
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von August bis Dezember
    //      31 + 28                Tage fuer Januer und Februar (siehe unten)
    //+2: Justierung der Rundung
    //+1: Der erste Tag im Monat ist 1 (und nicht 0)
    
    #tMonat += 3; // vom Jahr, das am 1. Maerz beginnt auf unser normales Jahr umrechnen
    IF (#tMonat>12) THEN
        //Monate 13 und 14 entsprechen 1 (Januar) und 2 (Februar) des naechsten Jahres
        #tMonat -= 12;
        #tJahr += #tJahr;
    END_IF;
    
    #tStunde := #Sekunden_seit_Mitternacht / 3600;
    #tMinute := #Sekunden_seit_Mitternacht MOD 3600 / 60;
    #tSekunde := #Sekunden_seit_Mitternacht MOD 60;
    
    //Date and Time zusammenbauen
    
    #Datum_Uhrzeit.YEAR := UDINT_TO_UINT(#tJahr);
    #Datum_Uhrzeit.MONTH := UDINT_TO_USINT(#tMonat);
    #Datum_Uhrzeit.DAY := UDINT_TO_USINT(#tTag);
    #Datum_Uhrzeit.HOUR := UDINT_TO_USINT(#tStunde);
    #Datum_Uhrzeit.MINUTE := UDINT_TO_USINT(#tMinute);
    #Datum_Uhrzeit.SECOND := UDINT_TO_USINT(#tSekunde);
    
    
    
END_FUNCTION
```

Gruß

Jürgen


----------



## PN/DP (30 Dezember 2020)

Juergena schrieb:


> da ich dann auch im FB für den Solar-log die UNIX Zeit in DTL umwandeln musste und nirgends ein Baustein gerade Griffbereit hatte


In der Siemens Bibliothek mit generellen Funktionen (LGF) gibt es die Functions
LGF_UnixTimeToDTL
LGF_DTLToUnixTime
für Zeiten ab 01.01.1990

Achtung! Bausteine aus dieser Bibliothek vor Verwendung ausführlich testen und Quelltexte anschauen! Es dauert anscheinend oft einige Baustein-Versionen bis die wirklich verwendbar sind. Ausgerechnet fast alle die Bausteine, die ich mir irgendwann mal genau angeschaut habe, haben/hatten irgendwelche Fehler und/oder Schlampigkeiten...

```
FUNCTION "LGF_UnixTimeToDTL" : DTL
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Siemens_Digital_Industry_Support
FAMILY : LGF
NAME : LGF_UnixTimeToDTL
   VAR_INPUT 
      timeUnix : DInt;   // Unix time to convert
   END_VAR

   VAR_OUTPUT
      error : Bool;   //  Error = TRUE: Time is outside of allowed range
      status : Word;
   END_VAR

   VAR_TEMP
      tempDate : DInt;   // Temporary Date value
      tempTime : DInt;   // Temporary Time value
      tempDTL {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // Temporary DTL value
   END_VAR

   VAR CONSTANT
      DELTA_1970_1990 : DInt := 631_152_000;   // Delta between 1970-1-1 and 1990-1-1 in seconds (IEC Time Base)
      SEC_PER_DAY : DInt := 86400;   // 86400 seconds in 1 day
      SEC_PER_HOUR : DInt := 3600;
      SEC_PER_MINUTE : DInt := 60;
      STATUS_NO_ERRROR : Word := 16#0000;
      ERR_TIME_BEFORE_1990 : Word := 16#8000;
      WARN_CONVERSION_LIMIT : Word := 16#6001;
      CONVERSION_LIMIT {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL := DTL#1990-01-01-00:00:00;
   END_VAR


BEGIN
REGION BLOCK INFO HEADER
  //===============================================================================
  // SIEMENS AG / (c)Copyright 2017
  //-------------------------------------------------------------------------------
  // Title:            LGF_UnixTimeToDTL
  // Comment/Function: This function converts Unix time to DTL
  //                   DATE type (range from 01.01.1990) is used in the function therefore the conversion limit is set.
  // Library/Family:   LGF (Library General Functions)
  // Author:           Siemens Digital Industry Support
  // Tested with:      S7-PLCSIM Advanced V2.0 SP1
  // Engineering:      TIA Portal V15
  // Restrictions:     ENO mechanism is not used, Error handling done by error and status
  // Requirements:     PLC (S7-1200 / S7-1500)
  //-------------------------------------------------------------------------------
  // Change log table:
  // Version  | Date       | Expert in charge       | Changes applied
  //----------|------------|------------------------|------------------------------
  // 01.00.00 | 16.10.2018 | Siemens Industry Online Support
  //                         First released version
  // 01.00.01 | 18.06.2019 | Siemens Industry Presale Support
  //                         Standard header and block parameters update, status parameter added
  // 01.00.02 | 10.07.2019 | Siemens Industry Presale Support
  //                         commends added and code intention addjusted
  //                         add eno handling
  // 03.00.00 | 23.04.2020 | Siemens Industry Support | Set version to V3.0.0
  //                         harmonize the version of the whole library
  //=============================================================================
END_REGION

REGION CONVERT
  // Check if timeUnix less than 01.01.1990
  IF (#timeUnix < #DELTA_1970_1990) THEN
    #LGF_UnixTimeToDTL := #CONVERSION_LIMIT;
    #error := TRUE;
    #status := #ERR_TIME_BEFORE_1990;
    RETURN;
    
    // Check if timeUnix is exactly on lower limitation of 01.01.1990
  ELSIF (#timeUnix = #DELTA_1970_1990) THEN
    #LGF_UnixTimeToDTL := #CONVERSION_LIMIT;
    #error := FALSE;
    #status := #WARN_CONVERSION_LIMIT;
    RETURN;
  END_IF;
  
  // Convert date
  #tempDate := (#timeUnix - #DELTA_1970_1990) / #SEC_PER_DAY;
  #tempDTL := DATE_TO_DTL(DINT_TO_DATE(#tempDate));
  
  // Convert time
  #tempTime := #timeUnix - #DELTA_1970_1990 - (#tempDate * #SEC_PER_DAY);
  #tempDTL.HOUR := DINT_TO_USINT(#tempTime / #SEC_PER_HOUR);
  #tempDTL.MINUTE := DINT_TO_USINT(#tempTime MOD #SEC_PER_HOUR / #SEC_PER_MINUTE);
  #tempDTL.SECOND := DINT_TO_USINT(#tempTime MOD #SEC_PER_MINUTE);
END_REGION

REGION OUTPUTS
  #LGF_UnixTimeToDTL := #tempDTL;
  #error := FALSE;
  #status := #STATUS_NO_ERRROR;
  //ENO mechanism is not used - forced to true.
  ENO := TRUE;
END_REGION

END_FUNCTION
```


----------



## Blockmove (1 Januar 2021)

Juergena schrieb:


> erst einmal möchte ich Danke sagen an @Blockmove, der mit einem kleinen Denkanstoß dafür sorgte, dass ich mir mal schnell Gedanken machte über meine Solaranlage.



Vor hundert Jahren sind wir Männer im Winter in der Stube gesessen und haben Krippen und Spielzeug geschnitzt und heute basteln wir an der Haussteuerung 

Gutes Neues Jahr und Viele Grüße
Blockmove


----------

