INI File Utility

Micks

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo miteinander,

mit einem Pixtend V2-L (Raspberry) steuere ich meine Solaranlage. Die Regelparameter und ein paar Statistikdaten möchte ich in einer ini-Datei speichern. Dazu habe ich mir die Erweiterung IIoT Libraries SL gekauft. Das schreiben der ini-Datei schaut folgendermaßen aus:

CASE State OF

//0...7:

8:
GVL.INIEntry.sSection := 'Ertrag';
GVL.INIEntry.sKey := 'PreviousYear.W_PV';
GVL.INIEntry.sValue := REAL_TO_STRING(GVL_Retain.Ertrag.PreviousYear.W_PV);
GVL.iniEntryManager.DeleteEntry (strIniFileEntry := GVL.INIEntry);
IF GVL.iniEntryManager.AddEntry (strIniFileEntry := GVL.INIEntry) <> INI_UTIL.ERROR.NO_ERROR THEN
JMP Error;
END_IF;
State := 9;
9:
fbDelete(xExecute := TRUE, sFileName := GVL.iniFileName);
IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = FILE.ERROR.NOT_EXIST) THEN
fbDelete(xExecute:=FALSE);
iniWriter.sFileName := GVL.iniFileName;
iniWriter.paIniFileEntry := ADR (GVL.aIniFileEntry);
iniWriter.uiSizeIniFileEntry := GVL.iniMaxEntries;
iniWriter.psBuffer := ADR (GVL.iniBuffer);
iniWriter.udiBufferSize := GVL.iniBufferSize;
iniWriter.xExecute := TRUE;
State := 10;
END_IF
10:
iniWriter();
IF NOT iniWriter.xBusy THEN
IF iniWriter.xError THEN
//iniWriter.Close();
iniWriter.xExecute := FALSE;
//iniWriter.Close();
JMP Error;
END_IF
IF iniWriter.xDone THEN
State := 0;
xDone := TRUE;
//iniWriter.Close();
iniWriter.xExecute := FALSE;
//iniWriter.Close();
ND_IF
END_IF
State := 0;
END_CASE


Die Funktion iniWriter.Close() erzeugt folgende Fehlermeldung:

Mitteilung vom Gerät:
"runtime received SIGABRT - system may be in an inconsistent state

**** We recommend a reboot of the controller now! ****"

Dabei ist es egal, an welcher Stelle im Programm (vor oder nach iniWriter.xExecute := FALSE) die Close-Funktion ausgeführt wird.

Wenn ich nun meine Speicher-Funktion so wie oben (ohne Close) ausführe, funktioniert das ganze genau einmal. Wenn ich die Funktion ein weiteres Mal ausführe, wird keine Datei mehr erstellt. Erst nach einem Reset der Steuerung funktioniert das ganze wieder genau einmal. Auch wenn beim Ausführen keine ini-Datei erstellt wird, ist iniWriter.xError = False und iniWriter.xDone = True. Ich vermute, dass es daran liegt, dass die CLose-Funktion nicht ausgeführt wird.

Vielleicht hat irgendjemand noch eine Idee, was ich noch ausprobieren könnte?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kenne das Ding nicht und finde auf die Schnelle auch keine Doku dazu, könnte mir aber vorstellen dass nach Beendigung des Schreibens erst das Execute auf False gesetzt werden muss, die Instanz dann nochmals aufgerufen werden muss bevor das Close ausgeführt werden kann.

Also so:
Code:
CASE State OF

//0...7:

8:
    GVL.INIEntry.sSection := 'Ertrag';
    GVL.INIEntry.sKey := 'PreviousYear.W_PV';
    GVL.INIEntry.sValue := REAL_TO_STRING(GVL_Retain.Ertrag.PreviousYear.W_PV);
    GVL.iniEntryManager.DeleteEntry (strIniFileEntry := GVL.INIEntry);
    IF GVL.iniEntryManager.AddEntry (strIniFileEntry := GVL.INIEntry) <> INI_UTIL.ERROR.NO_ERROR THEN
        JMP Error;
    END_IF;
    State := 9;
9:
    fbDelete(xExecute := TRUE, sFileName := GVL.iniFileName);
    IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = FILE.ERROR.NOT_EXIST) THEN
        fbDelete(xExecute:=FALSE);
        iniWriter.sFileName := GVL.iniFileName;
        iniWriter.paIniFileEntry := ADR (GVL.aIniFileEntry);
        iniWriter.uiSizeIniFileEntry := GVL.iniMaxEntries;
        iniWriter.psBuffer := ADR (GVL.iniBuffer);
        iniWriter.udiBufferSize := GVL.iniBufferSize;
        iniWriter.xExecute := TRUE;
        State := 10;
    END_IF
10:
    iniWriter();
    IF NOT iniWriter.xBusy THEN
        IF iniWriter.xError THEN
            iniWriter.xExecute := FALSE;
            iniWriter();
            iniWriter.Close();
            JMP Error;
        END_IF
        IF iniWriter.xDone THEN
            State := 0;
            xDone := TRUE;
            iniWriter.xExecute := FALSE;
            iniWriter();
            iniWriter.Close();
        END_IF
    END_IF
    State := 0;
END_CASE
 
Nur mal so ein Schuss ins Blaue:
Die Zugriffsrechte auf den Datei-Pfad und die Datei selbst stimmen?
Hallo Blockmove,
das weiß ich leider nicht. Ich bin davon ausgegangen, dass das soweit passen müsste, weil die Datei-Funktionen FILE.Delete oder FILE.Copy ja auch problemlos funktionieren.

Ich kenne das Ding nicht und finde auf die Schnelle auch keine Doku dazu, könnte mir aber vorstellen dass nach Beendigung des Schreibens erst das Execute auf False gesetzt werden muss, die Instanz dann nochmals aufgerufen werden muss bevor das Close ausgeführt werden kann.
Hallo Oberchefe,
ich habs soeben ausprobiert, leider kommt auch hier mit der Close-Funktion wieder diese komische Fehlermeldung. Aber so wie es ausschaut hast du trotzdem Recht, die iniWriter-Funktion muss nach dem xExcecute := False nochmal ausgeführt werden. Dann funktioniert alles so wie es soll. Und die Close-Funktion braucht man scheinbar nicht bzw. macht die Funktion wahrscheinlich automatisch (mit dem xExcecute := False).

Vielen, vielen Dank für euere Hilfe!!!
 
Ich glaube dann haben wir ein anderes Problem. Du setzt (in deiner oben geposteten Version) in Schritt 10 zwar das Execute auf False, rufst den FB aber danach nicht mehr auf. Wenn Du dann beim nächsten Schreiben das Execute in Schritt 9 wieder auf True setzt, dann in den Schritt 10 wechselst und die Instanz aufrufst, dann hat die Instanz keine Flanke vom Execute gesehen weshalb beim zweiten Mal nichts mehr passiert. Hier würde es auch helfen, in Schritt 9 das Execute erst auf False zu setzen, danach die Instanz einmal aufzurufen und anschließend das Execute auf True zu setzen.
Code:
CASE State OF

//0...7:

8:
    GVL.INIEntry.sSection := 'Ertrag';
    GVL.INIEntry.sKey := 'PreviousYear.W_PV';
    GVL.INIEntry.sValue := REAL_TO_STRING(GVL_Retain.Ertrag.PreviousYear.W_PV);
    GVL.iniEntryManager.DeleteEntry (strIniFileEntry := GVL.INIEntry);
    IF GVL.iniEntryManager.AddEntry (strIniFileEntry := GVL.INIEntry) <> INI_UTIL.ERROR.NO_ERROR THEN
        JMP Error;
    END_IF;
    State := 9;
9:
    fbDelete(xExecute := TRUE, sFileName := GVL.iniFileName);
    IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = FILE.ERROR.NOT_EXIST) THEN
        fbDelete(xExecute:=FALSE);
        iniWriter.sFileName := GVL.iniFileName;
        iniWriter.paIniFileEntry := ADR (GVL.aIniFileEntry);
        iniWriter.uiSizeIniFileEntry := GVL.iniMaxEntries;
        iniWriter.psBuffer := ADR (GVL.iniBuffer);
        iniWriter.udiBufferSize := GVL.iniBufferSize;
        iniWriter.xExecute := FALSE;
        iniWriter();
        iniWriter.xExecute := TRUE;
        State := 10;
    END_IF
10:
    iniWriter();
    IF NOT iniWriter.xBusy THEN
        IF iniWriter.xError THEN
            JMP Error;
        END_IF
        IF iniWriter.xDone THEN
            State := 0;
            xDone := TRUE;
        END_IF
    END_IF
    State := 0;
END_CASE
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also meine momentane Lösung, die funktioniert, schaut folgendermaßen aus:
Code:
CASE    State    OF    
9:
        fbDelete(xExecute := TRUE, sFileName := GVL.iniFileName);
           IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = FILE.ERROR.NOT_EXIST) THEN
              fbDelete(xExecute:=FALSE);
            iniWriter.sFileName             := GVL.iniFileName;
            iniWriter.paIniFileEntry         := ADR (GVL.aIniFileEntry);
            iniWriter.uiSizeIniFileEntry     := GVL.iniMaxEntries;
            iniWriter.psBuffer                 := ADR (GVL.iniBuffer);
            iniWriter.udiBufferSize         := GVL.iniBufferSize;
            iniWriter.xExecute                :=    TRUE;
            State := 10;
           END_IF
    10:   
        iniWriter();
        IF NOT iniWriter.xBusy THEN
        IF iniWriter.xError THEN
            //iniWriter.Close();
            iniWriter.xExecute := FALSE;
            iniWriter();
            //iniWriter.Close();
            JMP Error;
        END_IF
        IF iniWriter.xDone THEN
            State := 0;
            xDone := TRUE;
            //iniWriter.Close();
            iniWriter.xExecute := FALSE;
            iniWriter();
            //iniWriter.Close();
        END_IF
        END_IF
        State := 0;
END_CASE

Dein Vorschlag mit:
Code:
        iniWriter.xExecute := FALSE;
        iniWriter();
        iniWriter.xExecute := TRUE;
        State := 10;
    END_IF
10:
    iniWriter();
gefällt mir sehr gut, da hier der iniWriter auf jedem Fall von Anfang an jede Änderung vom xExecute mitbekommt. Das werde ich deshalb so übernehmen. Nochmal vielen Dank, du hast mir sehr geholfen!
 
Zurück
Oben