Moin Leute, um einen kleinen Verstärker neben dem Drehencoder und TFT an der Frontplatte auch über WEB steuern zu können, habe ich (widerwillig) die Arduino-IDE installiert und übertrage die Slider- und anderen Werte von der Webseite mittels websocket an einen nachgerüsteten ESP8266, der wiederum über die serielle Schnittstelle 'Variable=Wert'-Paare ausgibt. Der STM32-Prozessor auf dem Verstärker könnte entfallen und die Sache allein mit dem ESP8266 geregelt werden, das ist klar. Andrerseits war die Chronologie der Entstehung des Verstärkers anders und die Idee mit dem Webfrontend entstand erst vor kurzem. Der STM32 soll auch aus anderen Gründen drinbleiben. Gelöst ist es so: Ein Javascript liest die Werte von den Slidern und anderen Steuerelementen und überträgt sie als payload an einen websocket, der wiederum die etwas vorgefilterte payload über die serielle Schnittstelle des ESP (.onmessage) ausgibt. Der STM32 empfängt diese und steuert das TFT, den Klangregler und Anderes. Das funktioniert auch soweit und ist prinzipiell dann doch auch nicer Schice für leidenschaftliche HTML-, Javascript- und Arduinohasser wie mich. Es ist also möglich, Daten vom Webfrontend an den STM32 zu senden. Was aber noch fehlt, ist der Rückkanal. Der STM32 speichert die Einstellungen im Backup-Ram. Wenn der Websocket nun geöffnet wird (weil die Webseite zur Steuerung aufgerufen wird, siehe angehängtes Bild), bekommt der STM32 eine Mitteilung (.onopen) und sollte diese Daten eigentlich an die Slider des Frontends schicken. Im günstigsten Fall kann man dann auch die Slider der Webseite über den Drehencoder, der an der Frontplatte sitzt, synchron bewegen - das wäre der feuchteste Traum meiner Hoffnungen. Das Problem ist, daß ich diesen Rückkanal vom STM32 (bzw. ESP) zum Webfrontend nicht kenne, und beim Googeln auch nicht recht weiterkomme. Websockets sind Vollduplex, soviel habe ich inzwischen verstanden. '.send' funktioniert auch, aber das entsprechende Wissen über ein '.receive' fehlt mir beim socket. Das Einzige, was ich gefunden habe, ist ein Console.log(), aber das wird es wohl nicht sein. Ich stochere da etwas im Nebel. Habt ihr vielleicht ein Stichwort, wie man diesen mysteriösen Rückkanal nennt oder seine Funktionsweise ausfindig machen kann? Den Rest mache ich dann selba :-)
Ich weiss nicht ob ich das Problem wirklich verstehe. Du hast eigentlich alle Dinge schon genannt die du brauchst.
1 | var socket = new WebSocket("ws://...."); |
2 | |
3 | // zum zurücksenden an den "server" |
4 | socket.send("your message"); |
5 | |
6 | // zum empfangen vom server |
7 | socket.onmessage = function (event) { |
8 | console.log(event.data); |
9 | } |
:
Bearbeitet durch User
Ok, dann stoeber ich mal weiter an dem console.log-Dingsbums rum. Ist ja schon ein Hinweis, daß man da weitersuchen kann :-) Den Pfad zu finden, wie ich von der seriellen Schnittstelle des STM32 bis zum Slider komme, das ist die Herausforderung. Andersherum geht es schon. Breaking News: Wie durch ein Wunder kann ich schon einen Slider verschieben, wenn ich ihm im Javascript einen Wert zuweise (dachte, das geht nur andersherum). Wenn das jetzt noch vom STM32 aus geht, bin ich glücklich g.
console.log ist nicht die Lösung, das gibt in diesem Beispiel einfach nur die ankommende Zeichenkette in der Konsole vom Browser aus. Das benutzt man zum debuggen. Die meisten Browser öffnen so eine Art developer Tool mit F12 und da gibt es einen reiter "Konsole", dort sieht man die Ausgabe. Die Empfangene Nachricht liegt in "event.data" (im onmessage event wie oben in meinem Beispiel), damit musst du dann weiterarbeiten.
:
Bearbeitet durch User
Danke Paul, das Problem liegt/lag - glaube ich - daran, daß der Weg von dem seriellen Port bis zum "event" im Javascript noch nicht klar war. Prinzipiell sollen Frontplatte mit TFT und Drehencoder mit dem Webfrontend synchronisiert sein (also jeweils die gleichen Werte für Volume, Bass etc. haben und anzeigen). Es bleibt spannend, aber es ist Licht am Ende des Tunnels zu sehen g Dieses Video wird des Lötsels endgültige Räsung bringen, hoffe ich https://www.youtube.com/watch?v=cxbXyTwOl-M Da werden die Daten der Sensoren vom ESP über websocket zur Anzeige gebracht, und genau da hakt es bei mir. Das bastel ich nach, und lerne nebenbei noch was über die Vorteile der JSON-Sache. Vermutlich werde ich dabei wieder auf die event-Methode stoßen, und dann ist der Kreis geschlossen. Das macht inzwischen schon Laune mit dem ESP/Arduino-Zeugs. Wenn mal im Ansatz klar ist, wie JSON, Javascript und die Funktionen auf der html-Seite zusammenspielen, ist schon was gewonnen. Weiß nicht, ob es anderen auch so geht, aber die Verknotungen im Hirn beim Nachvollziehen, wer bei diesem Server/Client-Zeug was wann wie warum und wohin sendet, sind bei diesem Webgedöns nicht ganz ohne.
Das ist völlig normal, wenn man sich mit einer neuen Materie beschäftigt. Man hat nur irgendwann mehr Erfahrung wie man sich schneller solche Dinge aneignet. Mit websocket und JSON hast du auf jeden Fall schon genau die Dinge gefunden die du brauchst. Beispiel JSON: Zahlen können ohne Anführungsstriche geschrieben werden, Text immer mit. Ein einfacher JSON-String mit Key, Value pärchen sieht so aus: {"Volume": 22, "Treble": 8, "Bass": 8} Im onmessage event musst du den Json string als erstes in ein Objekt parsen: JSONobj = JSON.parse(event.data); dann kannst du auf die Werte einfach zugreifen z.b. var volume = JSONobj.Volume; Als Anfänger ist es etwas tricky wie man nun auf die HTML Elemente zugreift, weil es je nach Typ unterschiedlich ist. Wichtig ist, dass im HTML all deine Elemente eine eindeutige id haben. Um einen Slider zu aktualisieren zum Beispiel so: document.getElementById("volumeslider").value = volume; bei einer checkbox oder radio button document.getElementById("chkbox1").checked = true; bei einfachem Text in einem HTML Element document.getElementById("divxyz").innerHTML = "was auch immer";
:
Bearbeitet durch User
Ah gut, das mit dem JSON.parse werde ich auch noch ausprobieren. Die Wertepaare hatte ich noch selbst gebaut, aber jetzt ist klar, daß JSON und die entsprechenden Werkzeuge einem genau diese Dinge abnehmen. Der Zugriff auf HTML über die IDs ist für die ".send" Richtung (also die Sliderstellung zum STM32 übermitteln) genauso gemacht. Da gab es einige gute Lern-Beispiele von randomnerdtutorials, tttapa und anderen. Inzwischen ist der Knackpunkt auch gefunden: Der "socket.broadcastTXT(x)" ist das, wonach ich gesucht habe. Der versendet ein vorbereitetes JSON-Paket x, das aus den Daten der seriellen Schnittstelle zusammengestellt wird. Diese Funktion/Methode kannte ich nicht. Soweit die Theorie. In den nächsten Tagen werde ich's testen :-). Danke nochmal für die Unterstützung.
Jou, das geht so. Checkboxen, Slider, alles läßt sich jetzt von beiden Seiten (Webseite und Frontplatte) steuern. Das "JSON.parse" hat die Sache sehr vereinfacht. Ich habe auf Variablen im Javascript verzichtet. So ungefähr sieht das Script jetzt aus [c] var power; var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']); // ------------------------- // functions // ------------------------- connection.onopen = function () { connection.send('socket=true'); connection.send('Date=' + new Date()); // Wed Nov 24 2021 13:59:14 GMT+0100 (Mitteleuropäische Normalzeit) connection.send('Unix=' + new Date().getTime()); // unixtime mit ms (durch 1000 teilen) }; connection.onerror = function (error) { console.log('WebSocket Error ', error); }; connection.onmessage = function (event) { console.log('Server: ', event.data); JSONobj = JSON.parse(event.data); document.getElementById('vol').value = JSONobj.Vol; document.getElementById("voltxt").innerHTML = JSONobj.Vol; document.getElementById('treb').value = JSONobj.Treb; document.getElementById("trebtxt").innerHTML = JSONobj.Treb; document.getElementById('bass').value = JSONobj.Bass; document.getElementById("basstxt").innerHTML = JSONobj.Bass; //[.....] document.getElementById('loud').checked = JSONobj.Loud; document.getElementById('mute').checked = JSONobj.Mute; document.getElementById('inp'+JSONobj.Input).checked = 1; document.getElementById('gain'+JSONobj.Gain).checked = 1; power = JSONobj.Power; document.getElementById('power').value = power; }; connection.onclose = function(){ connection.send('socket=false'); console.log('WebSocket connection closed'); }; // ------------------------- // functions // ------------------------- function VolSli() { v_vol = document.getElementById('vol').value; connection.send('Vol=' + v_vol); document.getElementById("voltxt").innerHTML = v_vol; } //[.....] [/code] Der broadcastTXT(), der das .onmessage-event auslöst, läuft in der websocket.loop() in der sketch loop(). So funktioniert das also :-) Was Lustiges: Der broadcastTXT ballert zurück, was man bei der power-Variable merkt: Man drückt den Powerknopf auf der Webseite, das wird zum STM32 gesendet, und weil der alternierend schaltet, wird der Powerknopf einmal negiert, wenn das Zeug rausgeht, andrerseits merkt der STM32, daß sich was geändert hat, und sendet alle Variablen zurück, wobei der Knopf dann nochmal negiert wird. Äh, tja. Damit läßt sich das Ding also erstmal nicht abschalten gg. Aber das ist ja der übliche Mistkram, evtl. geht es auch mit sendTXT(client,str) anstatt broadcastTXT(str) oder man nimmt halt einfach eine checkbox anstatt einem alternierenden Schalter. Was allerdings zu erwarten war: Wenn der Drehencoder nicht langsam genug gedreht wird, aktualisieren sich die Daten auf der Webseite nicht und man sieht in der Konsole, daß nur ein Teil des JSON-Strings ankommt. Da muß man diesen Riesenstring, der ja alle Variablen beinhaltet, nochmal irgendwie stückeln. Es wird ja auch am Drehencoder immer nur eine Variable geändert, das ist also sinnloser Overhead jedesmal. Das kommt dann später mal dran. Grüße Sauer
Shit, Formatierung versaut. v_vol ist außerdem unsichtbar viel weiter oben definiert, aber noch experimentell und kann direkt durch 'document.getElementById('vol').value' ersetzt werden. Die "document.getElementById("voltxt").innerHTML = JSONobj.Vol"-Elemente beziehen sich auf Labels auf der Webseite, die über die id adressiert werden und die Werte der Sliderstellung anzeigen. Die Zahlen sieht man sonst nicht.
Inzwischen habe ich nach JSON.Parse mit if-Abfragen auf JSONObj.hasOwnProperty erreicht, daß auch Teilstrings akzeptiert werden. An der Geschwindigkeit in dieser Richtung hat sich aber nichts geändert. Wenn man eine Variable am Drehencoder ändert, vergehen ca. 500ms, bis der Slider auf der Webseite nachzieht. Obwohl nur ein JSON-String mit einer payload von 8 chars übertragen wird ("vol":xx). Andere Erfahrungsberichte jammern schon über nur 150ms. Mal checken, ob das Synchronisieren verbessert werden kann, indem die Daten, die vom STM32 zur Webseite gehen, quittiert werden. Wenn der Encoder gedreht wird, müssen dann vom Javascript mit connection.send() die Werte zurückgesendet werden - und wenn da nichts zum STM32 zurückkommt, sendet dieser halt mit geeignetem delay solange, bis die Werte im Javascript und im STM32-Speicher übereinstimmen. Vermutlich wird sich an der Geschwindigkeit selbst nicht viel ändern lassen. Die umgekehrte Richtung, also vom Bewegen eines Sliders bis zur Umsetzung im STM32 geht dagegen mit einer gefühlten Verzögerung von max. 50ms in Ordnung. Bisher war ich auf einem anderen System mit NO_SYS=1-lwip immer mit 'GET' unterwegs, da mußte man alle Änderungen noch mit einem submit-Button übertragen. Bei den Beispielen für den ESP mit AJAX und asynchronem Webserver muß zur Werteübernahme der Slider immer losgelassen werden. Da ist diese socket-Geschichte schon besser. Da schiebt man den Slider und die Änderung passiert ohne Absetzen fast gleichzeitig, ist ein viel besseres 'look-and-feel'.
Moin, also der Websocket ist für solche Sachen eigentlich recht schnell. Vielleicht bremst bei dir schon die serielle Übertragung zwischen STM und ESP? Hier muss man ggf. dafür sorgen das bei häufigen Änderungen nicht alle übertragen werden. Sascha
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.