Daten zwischenspeichern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Moin,

wie kann ich schnell, einfach und effizient Daten zwischen speichern. Ich haben versucht mit f = open('bla.txt', w) usw. aber wenn schnell geschrieben und gelesen werden muss, entstehen bei mir Fehler, zum Beispiel wird mal gar nichts überschrieben und der alte Wert bleibt. Also es soll nur kurz eine Zeile gespeichert werden, quasi ein Zustand, ob eine Variable Abhilfe schafft, die sache ist nur die, es wäre schön wenn der Zustand behalten werden könnte, falls das Programm abstürzt ... es wäre schön, wenn mir jemand auch Tipps über oder allgemein etwas zu Pythonstatemaschinen schreiben möge, falls die Zeit dafür ist... Danke im Voraus und ich hoffe ich verwechsel nicht zu viel, bin Anfänger^^

VG
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Soulpilot: Die Beschreibung klingt komisch. Was heisst wenn schnell geschrieben wird, wird manchmal gar nichts überschrieben? Hast Du da irgendwie Nebenläufigkeit im System? Schaust Du von ”aussen“ auf Dateien die Du im Programm nicht sauber schliesst?

Was sind „Pythonstatemaschinen“? Willst Du Zustandsautomaten in Code umsetzen? Das ist in Python generell nicht anders als in anderen Programmiersprachen. Falls das mit der ersten Frage nach dem Speichern in eine Datei zu tun hat, würde man wahrscheinlich einen Aufzählungstyp mit `enum.Enum` erstellen, damit man pro Zustand einen Wert hat, den man speichern kann. Ansonsten kann man auch Objekte verwenden um Zustände zu repräsentieren, die auch gleich das Verhalten für diesem Zustand beschreiben. OOP halt. Wobei man in einfachen Fällen auch direkt Funktionen oder Methoden verwenden kann um den Zustand zu repräsentieren, weil das in Python ja auch Objekte sind.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Gegen welche Abstürze möchtest Du Dich denn Absichern? Dass ein Meteorit den Rechner trifft? Dass der Strom ausfällt? Dass jemand das Programm hart abbricht, oder dass es eine Exception gibt?
Je nach Fall muß man unerschiedliche Maßnahmen zur Absicherung treffen.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Im Kontext der bisherigen Fragen vermute ich das übliche: Datenaustausch zwischen zwei Programmen durch einfache Dateioperationen. Die dafür halt nicht gemacht sind. Dafür benutzt man die IPC Mechanismen des Systems, wie zb Domain sockets oder Netzwerk sockets. Die Frage nach Persistenz ist dazu orthogonal und schwerer zu beantworten. Da sind gute Kandidaten zb SQLite, das ziemlich robuste Schreiblogik hat.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

__deets__ hat geschrieben: Sonntag 26. Juni 2022, 08:53 Im Kontext der bisherigen Fragen vermute ich das übliche: Datenaustausch zwischen zwei Programmen durch einfache Dateioperationen. Die dafür halt nicht gemacht sind. Dafür benutzt man die IPC Mechanismen des Systems, wie zb Domain sockets oder Netzwerk sockets. Die Frage nach Persistenz ist dazu orthogonal und schwerer zu beantworten. Da sind gute Kandidaten zb SQLite, das ziemlich robuste Schreiblogik hat.
Richtig erkannt!

Ist ein Websocket von hier: viewtopic.php?p=405330#p405330

Es geht dabei darum, dass wenn die SPS gesteuert wird, dass die HW Adressen gespeichert sind und von einem anderen Computer aus die Zustände der Hardwareadressen einfach abgefragt / ausgelesen werden können.

Jetzt ist es allerdings so, dass manche Zustände, also Schalter1 an oder aus, noch Nebenzustände besitzen können, wie Taster gedrückt und zeitliches Intervall schaltet periodisch ein und aus, aber da der Schalter aktiv ist, wird das auf der Webseite als "LED" quasi ausgegeben.
Schwer für einen nicht Profi das richtig zu beschreiben... Jedenfalls suche ich jetzt noch eine Möglichkeit, diese Zustände zu speichern. In einer Variable funktioniert das nur, dass ein Client das Programm nutzen kann, gehe ich mit einem zweiten PC drauf, bekomme ich nur die HW Adressen nach der Abfrage(Client Seitig) ausgegeben.

Der Code von damals wurde bereits erweitert, sollte aber das Funktionsprinzip von meiner WEBAPI erklären, im Großen und Ganzen.

Das mit dem schnell Schreiben ist so, ich habe versucht, die Informationen zu den Nebenzuständen in eine TXT Datei zu speichern, aber da die Funktion "lese alle Register aus" auf dem JS Client periodisch ausgeführt wird, kommt es da zu Fehlern, also so interpretiere ich das zumindest, also es wird nicht immer das geschrieben, was tatsächlich passiert, und ich glaube, es liegt unter anderem auch an den unterschiedlichen lese/schreib Zugriffsberichtigungen r / w. Es soll aber immer mit w geschrieben werden, damit der letzte Zustand überschrieben wird.

Eine Datenbank wäre möglich, aber dieses Szenario müsste die Voraussetzung haben, dass ich mich um die eigentliche DB nicht mehr kümmern muss und diese leicht zu bedienen ist.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Sonntag 26. Juni 2022, 08:51 Gegen welche Abstürze möchtest Du Dich denn Absichern? Dass ein Meteorit den Rechner trifft? Dass der Strom ausfällt? Dass jemand das Programm hart abbricht, oder dass es eine Exception gibt?
Je nach Fall muß man unerschiedliche Maßnahmen zur Absicherung treffen.
Absturz in dem Sinne, dass die WebSocket Verbindung abbricht, dass kommt hin und wieder mal vor, macht aber nichts, weil ich die Seite neu laden kann und alles im Hintergrund bisher seine Aufgabe erfüllt.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

So wirklich klarer geworden, was du da wie genau miteinander reden laesst, ist das Ganze mir zumindest nicht.

SQLite ist eine Datenbank, aber sie ist Datei-basiert, und kommt mit Python auch schon mit. Da musst du dich also um nix kuemmern. Da wird auch nichts "bedient". Das speichert strukturiert und robust Daten.

Ob dir das aber ueberhaupt hilft, ist mir - siehe oben - unklar. Denn speichern hat ja erstmal nix mit "zweiten PC" zu tun, das klingt eher danach, als ob dein Programm Zustand im Browser vorhaelt, den es aber eigentlich im Server lagern sollte. Damit verschiedene Clients (Browser) den abfragen koennen. Ob der aber persistent ist oder nicht ist fuer das Problem nachrangig.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast also einen Webserver, der Daten auslief, dazu ist, wie __deets__ schon schrieb, eine Datenbank sinnvoll.
Wenn der Client periodisch Daten abfragt, dann benutzt Du websockets falsch, denn da ist ja gerade der Server derjenige, der sich bei Änderungen beim Client meldet.

Aber ohne den Code zu sehen und eine verständliche Beschreibung, was das System alles können soll, kann man da nicht konkret weiterhelfen.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Sonntag 26. Juni 2022, 13:57 Du hast also einen Webserver, der Daten auslief, dazu ist, wie __deets__ schon schrieb, eine Datenbank sinnvoll.
Wenn der Client periodisch Daten abfragt, dann benutzt Du websockets falsch, denn da ist ja gerade der Server derjenige, der sich bei Änderungen beim Client meldet.

Aber ohne den Code zu sehen und eine verständliche Beschreibung, was das System alles können soll, kann man da nicht konkret weiterhelfen.
Der Server ist so gemacht, dass er nur auf Client Anfragen reagiert, ich weiß nicht wie man das anders macht, in JS kann ich das über ein Intervall machen, aber in Python dachte ich, läuft das Programm mittels while true permanent. Und es ändert sich auch nur etwas, wenn ich einen Button drücke?

Wo finde ich Informationen oder Tutorials, wie ein Websocket normalerweise gebaut wird, wo das auch richtig erklärt wird, gegoogelt habe ich bereits, leider nur mit mäßigem Erfolg, wie man sieht.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

__deets__ hat geschrieben: Sonntag 26. Juni 2022, 13:35 So wirklich klarer geworden, was du da wie genau miteinander reden laesst, ist das Ganze mir zumindest nicht.

SQLite ist eine Datenbank, aber sie ist Datei-basiert, und kommt mit Python auch schon mit. Da musst du dich also um nix kuemmern. Da wird auch nichts "bedient". Das speichert strukturiert und robust Daten.

Ob dir das aber ueberhaupt hilft, ist mir - siehe oben - unklar. Denn speichern hat ja erstmal nix mit "zweiten PC" zu tun, das klingt eher danach, als ob dein Programm Zustand im Browser vorhaelt, den es aber eigentlich im Server lagern sollte. Damit verschiedene Clients (Browser) den abfragen koennen. Ob der aber persistent ist oder nicht ist fuer das Problem nachrangig.
Danke für den Tipp!

Leider habe ich nicht 10 Jahre Python Erfahrung, man wird hier als doof hingestellt, nur, weil man nicht im Elitepython Jargon spricht oder sich wie ein Senior Developer auszudrücken vermag. Ich bin wirklich dankbar für jeden Tipp, es fällt mir nicht leicht, das Problem exakter zu beschreiben.

Ich sprach von Zuständen, was ein Zustand ist, sollte jeder Informatikstudent im ersten Semester lernen (habe ich mal gehört als ein Bekannter von Zustandsautomaten sprach) und der Zustand soll abgespeichert, verändert und ausgelesen werden können, ich verstehe nicht, warum das jetzt so ein Problem ist ... also für Profis wie Euch ... für mich als Beginner leider schon.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe dich nicht als doof dargestellt, ich habe lediglich dargelegt, dass deine Ausfuehrungen unklar sind. Code zeigst du natuerlich auch nicht, wo kaeme man denn dahin, da koennte ja jemand was verstehen. Und dir die Moeglichkeit genommen werden, schoen pampig zu werden :roll:

Glaub mir, ich weiss schon was ein Zustand ist. Und wie man Webservices baut, und IO ansteuert, und Daten persistiert. Was ich auch weiss, ist, dass man Leute, die sich mit ihrem ueberhoerten Kneipengelaber meinen, sie haetten Ahnung und wuerden darum ihr Problem mit irgendwelchen unverstandenen Phrasen garniert klar darlegen, ihren Mist alleine machen laesst. Lass dir deine Probleme von deinem Bekannten loesen...
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Du wirst hier nicht als "doof" hingestellt, sondern wir drücken nur aus, dass die Informationen, die Du lieferst nicht ausreichend sind, um Dir zu helfen. Ein beliebter Fehler ist, dass man mitten drin anfängt und nicht bedenkt, dass das Gegenüber noch gar nichts weiß.

Was ich bisher zusammengereimt habe ist folgendes:
Es gibt einen zentralen Server. An den sind mehrere Raspberries angeschlossen, die irgendeine Art "Zustand" an den Server melden.
Und es gibt Clienten, die gerne über Zustandsänderungen unterrichtet werden wollen.
Also ein typischer Message-Broadcaster.
Oder um es einfacher auszudrücken: ein Chatserver.
Und mit diesen Stichworten sollte es genug Beispiele im Netz geben, wie man sowas umsetzt.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

__deets__ hat geschrieben: Sonntag 26. Juni 2022, 14:56 Ich habe dich nicht als doof dargestellt, ich habe lediglich dargelegt, dass deine Ausfuehrungen unklar sind. Code zeigst du natuerlich auch nicht, wo kaeme man denn dahin, da koennte ja jemand was verstehen. Und dir die Moeglichkeit genommen werden, schoen pampig zu werden :roll:

Glaub mir, ich weiss schon was ein Zustand ist. Und wie man Webservices baut, und IO ansteuert, und Daten persistiert. Was ich auch weiss, ist, dass man Leute, die sich mit ihrem ueberhoerten Kneipengelaber meinen, sie haetten Ahnung und wuerden darum ihr Problem mit irgendwelchen unverstandenen Phrasen garniert klar darlegen, ihren Mist alleine machen laesst. Lass dir deine Probleme von deinem Bekannten loesen...
Ok du hast recht, es tut mir leid, falls ich dir auf die Füße getreten bin. In die Kneipe gehe ich nicht und dass ich Ahnung habe, habe ich auch nicht behauptet. Und zu meinem Bekannten habe ich Gottseidank auch keinen Kontakt mehr...
Zuletzt geändert von Soulpilot am Sonntag 26. Juni 2022, 15:28, insgesamt 1-mal geändert.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Sonntag 26. Juni 2022, 15:02 Du wirst hier nicht als "doof" hingestellt, sondern wir drücken nur aus, dass die Informationen, die Du lieferst nicht ausreichend sind, um Dir zu helfen. Ein beliebter Fehler ist, dass man mitten drin anfängt und nicht bedenkt, dass das Gegenüber noch gar nichts weiß.

Was ich bisher zusammengereimt habe ist folgendes:
Es gibt einen zentralen Server. An den sind mehrere Raspberries angeschlossen, die irgendeine Art "Zustand" an den Server melden.
Und es gibt Clienten, die gerne über Zustandsänderungen unterrichtet werden wollen.
Also ein typischer Message-Broadcaster.
Oder um es einfacher auszudrücken: ein Chatserver.
Und mit diesen Stichworten sollte es genug Beispiele im Netz geben, wie man sowas umsetzt.
So in der Art, Du hast mir doch vor einigen Monaten geholfen, den Link habe ich doch gesetzt. Mein Code ist mir peinlich, also das, was ich dann noch hinzugefügt habe, deswegen würde ich das per PN bevorzugen, also falls Du Zeit und Lust hast? Würde dir auch was bezahlen ;-) Hatte ich dir eh schon mal angeboten, da wurde meine Intention vermutlich missverstanden.

Es ist eine Steuerung von einer SPS bzw. Feldbusskopler... ich habe viele Beispiele mit Raspis gesehen, da ist auch viel unbrauchbares mit dabei, ich mache keine GPIO, sondern Pymodbus.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Joah, ohne Code kann dir hier halt niemand helfen.
Und wenn dir dein Code peinlich ist, wird er sich ja durch die Kritik hier nur verbessern. Kritik ausschließlich als negativ anzusehen ist leider nicht sehr zielführend.
Ansonsten hast du ja bereits den Hinweis bekommen, dass du nach einem Chatserver suchen solltest.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

JavaScript Websocket Client

Code: Alles auswählen

<!DOCTYPE html>
<head>
<link href="/favicon.png" rel="icon" type="image/png" />
</head>
<meta charset="utf-8"/>
<title>WebSocket</title>
<script language="javascript" type="text/javascript">

  // Client for Python SimpleWebsocketServer
  const portnum = 8001;
  var host, server, connected = false, relais1 = false, relais2 = false, relais3 = false, temp1 = false, temp2 = false, temperatur1 = 0, temperatur2 = 0, button_temp1 = false, button_temp2 = false, heating = false, feedpump = false;

  // Display the given text
  function display(s)
  {
    document.myform.text.value += s;
    document.myform.text.scrollTop = document.myform.text.scrollHeight;
  }

  // Initialisation
  function init()
  {
//    host = "192.168.0.24";
    host = "192.168.0.27";
//    host = location.host ? String(location.host) : "unknown";
//    host = host.replace("127.0.0.1", "localhost");
//    server = host.replace(/:\d*\b/, ":" + portnum);
//    server = "192.168.0.24:8001";
    server = "192.168.0.27:8001";
    document.myform.text.value = "Host " + host + "\n";
    window.setInterval(timer_tick, 2600);
    window.setInterval(timer_tick2, 1600);
    window.setInterval(timer_tick3, 10000);
    window.setInterval(timer_tick4, 7000);
  
    if (connected === false)
      connect();
      connected = true;

    //Timeout() initialisiert nur einmal im Gegensatz zu Intervall()
    setTimeout(() =>
    {
    if (connected === true)
    {

      image0()

      websock.send('abfrage_aller_register');
      websock.send('temp1off');
      websock.send('temp2off');

      button_temp1 = false;
      temp1 = false;

      button_temp2 = false;
      temp2 = false;

      heating = false;

    }
    }, 100);

  }

  // Open a Websocket connection
  function connect()
  {
    var url = "ws://" + server + "/";
    display("Opening websocket " + url + "\n");
    websock = new WebSocket(url);
    websock.onopen    = function(evt) {sock_open(evt)};
    websock.onclose   = function(evt) {sock_close(evt)};
    websock.onmessage = function(evt) {sock_message(evt)};
    websock.onerror   = function(evt) {sock_error(evt)};
    connected = true;
  }
  // Close a Websocket connection
  function disconnect()
  {
    connected = false;
    websock.close();   
  }

  // Timer tick handler
  function timer_tick()
  {
    if (connected)
//      websock.send('*');
//      websock.send('abfrage_aller_register');
      websock.send('temperatur1');
      websock.send('temperatur2');
      websock.send('heatread');
      websock.send('systemp');

  }

  function timer_tick2()
  {

    image0()
    image4()
    image5()

    if (connected)
//      websock.send('*');
//      if (temp1 == true)

        if ((button_temp1 == true && button_temp2 == false) && (temp1 === true && temp2 === false))
        {
          if (temperatur1 < 28)
          {
           //if (temp1 === false)
            {
              websock.send('temp1');
              image4()
            }
          }
          else
          {
            //if (temp1 === true)
            {
              websock.send('temp1off');
              image4()
            }
          }
        } 
        if ((button_temp2 === true && button_temp1 === false) && (temp2 === true && temp1 === false))
        {
          if (temperatur1 < 30)
          {
            //if (temp2 === false)
            {
              websock.send('temp2');
              image5()
            }
          }
          else
          {
            //if (temp2 === true)
            {
            websock.send('temp2off');
            image5()
            }
          }
        }
  }

  function timer_tick3()
  {
    if (connected)
//      websock.send('*');
      websock.send('abfrage_aller_register');
      websock.send('temp1state');
      websock.send('temp2state');
      websock.send('temp3state');
      websock.send('temp4state');
  }

  function timer_tick4()
  {
    if (connected)
    {
      if (feedpump === true)
      {
        setTimeout(() =>
        {
        // Code, der erst nach 0.1 Sekunden ausgeführt wird
        websock.send('relais3');
        }, 100);

        setTimeout(() =>
        {
        // Code, der erst nach 2 Sekunden ausgeführt wird
        websock.send('relais3off');
        }, 2000);
      }
    }
  }


  //Daten Empfangen bei Event
  function sock_message(evt)
  {
//    display(evt.data);

    //Temperatur von Heizmantel, Websocket übergabe von Websocketserver
    if (evt.data.includes(1020))
    {
      const myArray = evt.data.split(" ");
      let temper1 = myArray[1];
      display(temper1);
      temperatur1 = temper1;     
      output_temp1(temperatur1)
    }

    if (evt.data.includes(1024))
    {
      const myArray2 = evt.data.split(" ");
      let temper2 = myArray2[1];
      display(temper2);
      temperatur2 = temper2;
      output_temp2(temperatur2)
    }

    //Temperatur von Raspberry, Websocket übergabe von Websocketserver
    if (evt.data.includes(8888))
    {
      const myArray8 = evt.data.split(" ");
      let systemp = myArray8[1];
      display(systemp);
      temperatur8 = systemp;
      output_systemp(temperatur8)
    }


//    data = evt.data;
    if (evt.data === "528True")
    {
      relais1 = true;
      image1()
//      alert("528True");
    }
    if (evt.data === "528False") 
    {
      relais1 = false;
        image1()
//      alert("528False");
    }

    if (evt.data === "513True") 
    {
      relais2 = true;
      image2()
//      alert("513True");
    }
    if (evt.data === "513False")
    {
      relais2 = false;
      image2()
//      alert("513False");
    }

//    if (evt.data === "514True")
    if (evt.data === "514FeedpumpTrue")
    {
//      relais3 = true;
      feedpump = true;
      image3()
//      alert("514True");
    }
//    if (evt.data === "514False")
    if (evt.data === "514FeedpumpFalse")
    {
      feedpump = false;
//      relais3 = false;
      image3()
//      alert("514False");
    }

    if (evt.data === "1025True")
    {

      if (temp2 === false || button_temp2 === false)

        temp1 = true;
//        button_temp1 = true;

      image4()
//      alert("524True" + button_temp2 + button_temp1);
    }

    if (evt.data === "1026False")
    {

      temp1 = false;
//      button_temp1 = false;
      image4()
//      alert("524False");
    }

    if (evt.data === "1028True")
    {
      if (temp1 === false || button_temp1 === false)

        temp2 = true;
//        button_temp2 = true;

      image5()
//      alert("524True");
    }

    if (evt.data === "1029False")
    {

      temp2 = false;
//      button_temp2 = false;
      image5()
//      alert("524False");
    }

    if (evt.data === "1025True" || evt.data === "1028True")
    {
        heating = true;
        image6()
    }
    if (evt.data === "1026False" || evt.data === "1029False")
    {
        heating = false;
        image6()
    }

  }


   //functions to control the io
  function relais1_on()
  {
    relais1 = true;

      if (relais1 === true)
        websock.send('relais1');
//        alert("button pressd" + relais1);
  }

  function relais2_on()
  {
    relais2 = true;
    //alert("button pressd" + relais2);

      if (relais2 === true)
        websock.send('relais2');
//        alert("button pressd" + relais2);
  }

  function relais3_on()
  {
    relais3 = true;
    feedpump = true;

//    alert("button pressd" + relais2);

//      if (relais3 === true)
//        websock.send('relais3');
      if (feedpump === true)
        websock.send('feedpump');
//        alert("button pressd" + relais3);
  }

  function temp1_on()
  {
    temp1 = true;
    button_temp1 = true;

    temp2 = false;
    button_temp2 = false;

    websock.send('temp2off');
  }

  function temp2_on()
  {
    temp2 = true;
    button_temp2 = true;

    temp1 = false;
    button_temp1 = false;

    websock.send('temp1off');
  }



  function relais1_off()
  {
    relais1 = false;

      if (relais1 === false)
        websock.send('relais1off');
//        alert("button pressd" + relais1);
  }

  function relais2_off()
  {
    relais2 = false;

     if (relais2 === false)
       websock.send('relais2off');
//       alert("button pressd" + relais2);
  }

  function relais3_off()
  {
    relais3 = false;
    feedpump = false;

//      if (relais3 === false)
//        websock.send('relais3off');

      if (feedpump === false)
        websock.send('feedpumpoff');
//        alert("button pressd" + relais3);
  }

//Temp1 Heizen off
  function temp1_off()
  {
    temp1 = false;
    button_temp1 = false;

      if (temp1 === false)
        websock.send('temp1off');

//      if (button_temp1 === false)
//        websock.send('button_temp1off');
  }

//Temp1 Heizen off
  function temp2_off()
  {
    temp2 = false;
    button_temp2 = false;

      if (temp2 === false)
        websock.send('temp2off');

//      if (button_temp2 === false)
//        websock.send('button_temp2off');
  }



  // Display incoming data
//  function sock_message(evt)
  {
//    display(evt.data);
//    alert("relais1True");
//    return evt.data;
  }

  // Handlers for other Websocket events
  function sock_open(evt)
  {
    display("Connected\n");
  }
  function sock_close(evt)
  {
    display("\nDisconnected\n");
  }
  function sock_error(evt)
  {
    display("Socket error\n");
    websock.close();
  }

  // Do initialisation when page is loaded
  window.addEventListener("load", init, false);

//  function state()
//  {
//  if (relais1 === true)
//  {
//    document.getElementById('on').src="on.png";
//  }else
//  {
//    document.getElementById('off').src="off.png";
//  }
//  }

</script>
<form name="myform">
  </div>
  <img id="BEE"  src="BEE.png" width="40" height="40" align="left">
  <h2>&nbsp Websocket</h2>
  </div>
  <p>
  <textarea name="text" rows="10" cols="60">
  </textarea>
  </p>
  <p>
  <p>
  <input type="button" value="Connect" onClick="connect();">
  <input type="button" value="Disconnect" onClick="disconnect();">

  </p>
  <img id="myImage0" src="RI.png" align="middle" alt="Plant Image" style="position:absolute; top:5%; left:30%; height=”150”; border:double;"  />
  <p>
  <script>
  function image0()
  {

//Relais1 = Cooling
//Relais2 = Gas
//Relais3 = Feed

    var image = document.getElementById("myImage0");

//    if ((button_temp1 === true || button_temp2 === true) && (relais1 === true && relais2 === true))
//    {
//      image.src = "RI_hot5_cool_gas.png";
//    }

    if ((button_temp1 == true || button_temp2 == true) && (relais1 === false && relais2 === false && feedpump === false))
    {
      image.src = "RI_hot3.png";
    }
    else if ((relais2 === true && relais1 === true) && feedpump == false && (button_temp1 == false && button_temp2 == false))
    {
      image.src = "RI_cool_gas.png";
    }
    else if ((relais2 === true && relais1 === false) && feedpump == true && (button_temp1 == false && button_temp2 == false))
    {
      image.src = "RI_feed_gas.png";
    }
    else if ((relais2 === false && relais1 === true) && feedpump == true && (button_temp1 == false && button_temp2 == false))
    {
      image.src = "RI_cool_feed.png";
    }
    else if ((relais2 === true && relais1 === true) && feedpump == true && (button_temp1 == false && button_temp2 == false))
    {
      image.src = "RI_cool_feed_gas.png";
    }
    else if ((button_temp1 == true || button_temp2 == true) && (relais1 === true && relais2 === true && feedpump === false))
    {
      image.src = "RI_hot5_cool_gas.png";
    }
    else if ((button_temp1 == true || button_temp2 == true) && (relais1 === true && relais2 === true && feedpump === true))
    {
      image.src = "RI_hot5_feed_cool_gas.png";
    }
    else if ((button_temp1 === true || button_temp2 === true) && (relais1 === true && feedpump === true) && relais2 === false)
    {
      image.src = "RI_hot5_feed_cool.png";
    }
    else if ((button_temp1 === true || button_temp2 === true) && (relais1 === false && feedpump === true) && relais2 === true)
    {
      image.src = "RI_hot5_feed_gas.png";
    }
    else if ((button_temp1 === true || button_temp2 === true) && relais1 === true)
    {
      image.src = "RI_hot5_cool.png";
    }
    else if ((button_temp1 === true || button_temp2 === true) && relais2 === true)
    {
      image.src = "RI_hot5_gas.png";
    }
    else if ((button_temp1 === true || button_temp2 === true) && feedpump === true)
    {
      image.src = "RI_hot5_feed.png";
    }
    else if (relais1 === true)
    {
      image.src = "RI_cool.png";
    }
    else if (relais2 === true)
    {
      image.src = "RI_gas.png";
    }
    else if (feedpump === true)
    {
      image.src = "RI_feed.png";
    }
    else
    {
      image.src = "RI.png";
    }


  }

  </script>
  


  <input type="button" value="Cooling System on" onClick="relais1_on();">
  <img id="myImage1"  src="off.png" width="20" height="20"> 
  <script>
  function image1()
  {
    var image = document.getElementById("myImage1");

    if (relais1 === true) 
    {
      image.src = "on.png";
    }else 
    {
      image.src = "off.png";
    }   
  }
  </script>

  </p>
  <input type="button" value="Cooling System off" onClick="relais1_off();">
  </p>

  <input type="button" value="Gas Valve on" onClick="relais2_on();">
  <img id="myImage2"  src="off.png" width="20" height="20">
  <script>
  function image2()
  {
    var image = document.getElementById("myImage2");

    if (relais2 === true)
    {
      image.src = "on.png";
    }else
    {
      image.src = "off.png";
    }
  }
  </script>

  </p>
  <input type="button" value="Gas Valve off" onClick="relais2_off();">
  </p>

  <input type="button" value="Feed Pump on" onClick="relais3_on();">
  <img id="myImage3"  src="off.png" width="20" height="20">
  <script>
  function image3()
  {
    var image = document.getElementById("myImage3");

    if (feedpump === true)
    {
      image.src = "on.png";
    }else
    {
      image.src = "off.png";
    }
  }
  </script>

  </p>
  <input type="button" value="Feed Pump off" onClick="relais3_off();">
  </p>



  </p>
  <p>Heating Status</p>
  
  <img id="myImage6"  src="red-off.png" width="20" height="20">
  <script>
  function image6()
  {
    var image = document.getElementById("myImage6");

    if (button_temp2 === true || button_temp1 === true)
//    if (temp1 === true || temp2 === true)
    {
      image.src = "red-on.png";
    }else
    {
      image.src = "red-off.png";
    }
  }
  </script>


  </p>
  <p>Heat 350 °C</p>
  <input type="button" value="temp1_on" onClick="temp1_on();">

  <img id="myImage4"  src="off.png" width="20" height="20">
  <script>
  function image4()
  {
    var image = document.getElementById("myImage4");

    if (temp1 === true)
//    if (button_temp1 === true && temp1 === true)
//    if (button_temp1 === true)
    {
      image.src = "on.png";
    }else
    {
      image.src = "off.png";
    }
  }
  </script>

  </p>
  <input type="button" value="temp1_off" onClick="temp1_off();">
  </p>
 

  </p>
  <p>Heat 400 °C</p>
  <input type="button" value="temp2_on" onClick="temp2_on();">

  <img id="myImage5"  src="off.png" width="20" height="20">
  <script>
  function image5()
  {
    var image = document.getElementById("myImage5");

    if (temp2 === true)
//    if (button_temp2 === true && temp2 === true)
//    if (button_temp2 === true)
    {
      image.src = "on.png";
    }else
    {
      image.src = "off.png";
    }
  }
  </script>

  </p>
  <input type="button" value="temp2_off" onClick="temp2_off();">
  </p>


  </p>
  </p>

  <script>
  function output_temp1(temperatur1)
  {
//    var temperatur1;
    document.getElementById('temper1').innerHTML = temperatur1;
//    display(temperatur1);
  }
  </script>
  <p> Temperatur Reaktor: <span id="temper1"></span>.</p> 

  </p>

  </p>
  </p>

  <script>
  function output_temp2(temperatur2)
  {
//    var temperatur1;
    document.getElementById('temper2').innerHTML = temperatur2;
//    display(temperatur1);
  }
  </script>
  <p> Temperatur Water: <span id="temper2"></span>.</p>

  </p>


  
  <script>
  function output_systemp(temperatur8)
  {

    document.getElementById('systemp').innerHTML = temperatur8;

  }
  </script>
  <p> Temperatur System: <span id="systemp"></span>.</p>

  </p>



  </p>

</form>
</html> 

Python Socket Server & Pymodbus Client

Code: Alles auswählen

import os
import shutil
import logging
import time
from functools import partial
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer
logger = logging.getLogger(__name__)

# Adressen
UNIT = 0x1
HOST = '192.168.2.50'
PORT = 502
# Coil Output Base Address
COILBASE = 512
# Portnummer listen
PORTNUM = 8001

# Websocket class to echo received data
class Echo(WebSocket):

    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.modbus = client

    def handleMessage(self):
        try:
            print("Echoing '%s'" % self.data)
            self.sendMessage(self.data)

            command = self.data
            address, value = {
                "relais1": (COILBASE + 16, True),
                "relais1off": (COILBASE + 16, False),
                "relais2": (COILBASE + 1, True),
                "relais2off": (COILBASE + 1, False),
                "relais3": (COILBASE + 2, True),
                "relais3off": (COILBASE + 2, False),
                "feedpump": (COILBASE + 201, True),
                "feedpumpoff": (COILBASE + 202, False),
                "*": (COILBASE + 999, False),
                "temperatur1": (1020, False),
                "temperatur2": (1023, False),
                "temp1": (1025, True),
                "temp2": (1028, True),
                "temp1off": (1026, False),
                "temp2off": (1029, False),
                "heatread": (1027, False),
                "systemp": (8888, False),
                "temp1state": (9991, False),
                "temp2state": (9992, False),
                "temp3state": (9993, False),
                "temp4state": (9994, False),
                "abfrage_aller_register": (COILBASE + 500, False),

            }[command]
            # Eingabe String Vergleich
            if address < 999:
                # Relaisregister schreiben
                rq = self.modbus.write_coil(address, value, unit= UNIT)
                # print(rq)
                print(str(rq))
                # self.sendMessage(self.data)
                time.sleep(0.1)
                # Relaisregister lesen
                rp = self.modbus.read_coils(address, unit= UNIT)
                # self.sendMessage(str(rp))
                time.sleep(0.1)
                self.sendMessage(str(address) + str(rp.bits[0]))
                print(rp.bits[0])

                if address == 713:
#                    datei  = open('register.txt','w')
#                    datei.write("\r\nFeedpumpTrue")
#                    datei.close()
#                    datei  = open('register.txt','r')
                    l = 'FeedpumpTrue'
                    self.sendMessage(str(514) + str(l))
#                    datei.close()
                if address == 714:
#                    datei  = open('register.txt','w')
#                    datei.write("\r\nFeedpumpFalse")
#                    datei.close()
#                    datei  = open('register.txt','r')
                    l = 'FeedpumpFalse'
                    self.sendMessage(str(514) + str(l))
#                    datei.close()

            # Abfrage aller IO's
            if address == 1012:
                for r in range(0, 30):
#                    time.sleep(0.01)
                    rp = self.modbus.read_coils(COILBASE + r, unit= UNIT)
                    time.sleep(0.01)
                    address_new = COILBASE + r
                    self.sendMessage(str(address_new) + str(rp.bits[0]))
                    time.sleep(0.01)
#                    shutil.move('register.txt', 'registerlog.txt')
#                    datei  = open('registerlog.txt','r')
#                    with open('register.txt', 'r') as datei:
#                    self.sendMessage(str(514) + str(print(datei.read())))
#                    datei.close()

#                    self.sendMessage(str(1025) + str(state1025))
#                    self.sendMessage(str(1026) + str(state1026))
#                    self.sendMessage(str(1028) + str(state1028))
#                    self.sendMessage(str(1029) + str(state1029))

            # Temperatur Abfrage
            if address == 1020:
                response = self.modbus.read_holding_registers(0x00,4,unit=1)
                time.sleep(0.05)
                t = response.registers[0]
                self.sendMessage(str(address) + " " + str(t/10))
                time.sleep(0.05)
#                response = self.modbus.read_holding_registers(0x00,4,unit=1)
                time.sleep(0.05)
                z = response.registers[3]
                self.sendMessage(str(address + 4) + " " + str(z/10))

            # Heizen an | Modul an dem der Heizdraht geschaltet wird
            if address == 1025:
                rq = self.modbus.write_coil(524, True, unit= UNIT)
                time.sleep(0.01)
                rq = self.modbus.write_coil(525, True, unit= UNIT)
                time.sleep(0.1)
                rp = self.modbus.read_coils(525, unit= UNIT)
                time.sleep(0.1)
                self.sendMessage(str(1025) + str(rp.bits[0]))

            if address == 9991:
                rp = self.modbus.read_coils(525, unit= UNIT)
                time.sleep(0.1)
                self.sendMessage(str(1025) + str(rp.bits[0]))

            # Heizen an | Modul an dem der Heizdraht geschaltet wird
            if address == 1028:
                rq = self.modbus.write_coil(524, True, unit= UNIT)
                time.sleep(0.01)
                rq = self.modbus.write_coil(526, True, unit= UNIT)
                time.sleep(0.1)
                rp = self.modbus.read_coils(526, unit= UNIT)
                time.sleep(0.1)
                self.sendMessage(str(1028) + str(rp.bits[0]))

            if address == 9992:
                rp = self.modbus.read_coils(526, unit= UNIT)
                time.sleep(0.1)
                self.sendMessage(str(1028) + str(rp.bits[0]))

            # Heizen aus | Modul an dem der Heizdraht geschaltet wird
            if address == 1026:
                rq = self.modbus.write_coil(524, False, unit= UNIT)
                time.sleep(0.01)
                rq = self.modbus.write_coil(525, False, unit= UNIT)
                time.sleep(0.05)
                rp = self.modbus.read_coils(525, unit= UNIT)
                time.sleep(0.05)
                self.sendMessage(str(1026) + str(rp.bits[0]))

            if address == 9993:
                rp = self.modbus.read_coils(525, unit= UNIT)
                time.sleep(0.05)
                self.sendMessage(str(1026) + str(rp.bits[0]))

            # Heizen aus | Modul an dem der Heizdraht geschaltet wird
            if address == 1029:
                rq = self.modbus.write_coil(524, False, unit= UNIT)
                time.sleep(0.01)
                rq = self.modbus.write_coil(526, False, unit= UNIT)
                time.sleep(0.05)
                rp = self.modbus.read_coils(526, unit= UNIT)
                time.sleep(0.05)
                self.sendMessage(str(1029) + str(rp.bits[0]))

            if address == 9994:
                rp = self.modbus.read_coils(526, unit= UNIT)
                time.sleep(0.01)
                self.sendMessage(str(1029) + str(rp.bits[0]))

            # Digitalausgang der Heizung auslesen | Modul an dem der Heizdraht geschaltet wird
            if address == 1027:
                rp = self.modbus.read_coils(524, unit= UNIT)
                time.sleep(0.05)
                self.sendMessage(str(524) + str(rp.bits[0]))

            # Systemtemperatur von Raspberry
            if address == 8888:
#                os.system('echo 1 > vcgencmd measure_temp')
#                systemtemp = str(os.system('vcgencmd measure_temp'))
#                print(systemtemp)
#                self.sendMessage(str(8888) + " " + str(os.system('vcgencmd measure_temp')))
                res = os.popen("vcgencmd measure_temp").readline()
                temp = (res.replace("temp=","").replace("'C\n",""))
                self.sendMessage(str(8888) + " " + str(temp))



        except Exception as exception:
            logger.exception("handle message")
            raise

    def handleConnected(self):
        print("Connected")

    def handleClose(self):
        print("Disconnected")

def main():
    logging.basicConfig()
    with ModbusClient(host=HOST, port=PORT) as client:
        client.connect()

        print("Websocket server on port %s" % PORTNUM)
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        try:
            server.serveforever()
        finally:
            server.close()


if __name__ == "__main__":
    main()

Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

sparrow hat geschrieben: Sonntag 26. Juni 2022, 17:26 Joah, ohne Code kann dir hier halt niemand helfen.
Und wenn dir dein Code peinlich ist, wird er sich ja durch die Kritik hier nur verbessern. Kritik ausschließlich als negativ anzusehen ist leider nicht sehr zielführend.
Ansonsten hast du ja bereits den Hinweis bekommen, dass du nach einem Chatserver suchen solltest.
Gut ich habe den gesamten Code mal mit angehängt, den Chatserver schaue ich mir an, wenn ich es richtig verstehe, ist das eine Art Analogon zu meiner Problemstellung?
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Über konstruktive Kritik und Verbesserungsvorschläge freue ich mich sehr, bitte seid gnädig mit mir, hatte bisher gar nichts mit OOP zu tun. (Sirius hatte mir damals wirklich gut geholfen)
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Der Code besteht aus 90% kopierten Zeilen. Dieses Hin- und Herschicken von kryptischen Nummern macht das Lesen doch sehr schwierig. Wie kommst Du auf die Idee, dass "514False" eine gute Rückmeldung wäre? Wie kommst Du darauf, dass 512 + 999 = 1012 gibt? Warum hat feedpump eine andere Addresse als feedpumpoff?
os.popen benutzt man nicht, sondern statt dessen subprocess.run.

Typischerweise schickt man über Websockets JSON-kodierte Wörterbücher. Da kann man auf strukturierte Weise alle möglichen Daten kodieren, z.B: {"relais1": "off", "temp1": "on"}

Code: Alles auswählen

class Echo(WebSocket):

    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.modbus = client
        self.functions = {
            "relais1": partial(self.simple_switch, COILBASE + 16),
            "relais2": partial(self.simple_switch, COILBASE + 1),
            "relais3": partial(self.simple_switch, COILBASE + 2),
            "temperatur1": partial(self.read_temperature, 0),
            "temperatur2": partial(self.read_temperature, 3),
            "heizen1": partial(self.heating, 525),
            "heizen2": partial(self.heating, 526),
            "heatread": partial(self.simple_read, 524),
            "systemp": self.systemp
        }

    def simple_switch(self, address, value):
        """ value can be one of "on", "off" or "get" """
        if value in ["on", "off"]:
            rq = self.modbus.write_coil(address, value == "on", unit=UNIT)
            time.sleep(0.1)
        elif value != 'get':
            raise ValueError(value)
        # Relaisregister lesen
        rp = self.modbus.read_coils(address, unit=UNIT)
        return "on" if rp.bits[0] else "off"

    def simple_read(self, address, value):
        if value != 'get':
            raise ValueError(value)
        # Relaisregister lesen
        rp = self.modbus.read_coils(address, unit=UNIT)
        return "on" if rp.bits[0] else "off"

    def read_temperature(self, address, value):
        if value != "get":
            raise ValueError(value)
        response = self.modbus.read_holding_registers(0x00, 4, unit=1)
        return response.registers[address]

    def heating(self, address, value):
        # Heizen an | Modul an dem der Heizdraht geschaltet wird
        if value in ["on", "off"]:
            rq = self.modbus.write_coil(524, value == "on", unit=UNIT)
            time.sleep(0.01)
            rq = self.modbus.write_coil(address, value == "on", unit=UNIT)
            time.sleep(0.1)
        elif value != 'get':
            raise ValueError(value)
        rp = self.modbus.read_coils(address, unit=UNIT)
        return "on" if rp.bits[0] else "off"

    def systemp(self, value):
        result = subprocess.run(["vcgencmd", "measure_temp"], stdout=subprocess.PIPE)
        temperature = result.stdout.partition("temp=")[-1].partition("'C\n")[0]
        return temperature

    def handleMessage(self):
        new_state = {}
        commands = json.loads(self.data)
        for key, value in commands.items():
            function = self.functions[key]
            new_state[key] = function(value)
        self.sendMessage(json.dumps(new_stat))
Entsprechend einfach ist es, den Code um weitere Schalter zu erweitern.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Sonntag 26. Juni 2022, 22:43 Der Code besteht aus 90% kopierten Zeilen. Dieses Hin- und Herschicken von kryptischen Nummern macht das Lesen doch sehr schwierig. Wie kommst Du auf die Idee, dass "514False" eine gute Rückmeldung wäre? Wie kommst Du darauf, dass 512 + 999 = 1012 gibt? Warum hat feedpump eine andere Addresse als feedpumpoff?
os.popen benutzt man nicht, sondern statt dessen subprocess.run.

Typischerweise schickt man über Websockets JSON-kodierte Wörterbücher. Da kann man auf strukturierte Weise alle möglichen Daten kodieren, z.B: {"relais1": "off", "temp1": "on"}

[...]

Entsprechend einfach ist es, den Code um weitere Schalter zu erweitern.
OMG Sirius, vielen herzlichen Dank! Ich würde den Code die Tage mal testen und mich wieder melden... Ach ja, das waren die pseudo Register für Zustände, die keine explizite Hardwareadresse haben, so zum Beispiel sollte Relais3 bzw. der Feed getaktet gesteuert werden, aber der Zustand, dass der Button gedrückt wurde, dabei erhalten bleiben, damit das auf der Webseite dann angezeigt wird, das der Zustand "Feed" aktiv ist ... vielleicht denke ich einfach auch völlig verkehrt... Jedenfalls Danke und ich melde mich wieder!

514False bedeutet, das die Hardwareadresse 514 an der SPS den Zustand False hat und damit deaktiviert ist. Für mich war das irgendwie logisch :roll: :lol:

LG
Antworten