WebSerial mit SpiderBasic überhaupt möglich?

Hier könnt ihr alle Fragen zu SpiderBasic austauschen.
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Nachdem ich alles mit PureBasic mache, und auch für Web-Anwendung schon ein SpiderBasic-Programm erfolgreich hingekriegt habe
http://carpatrain.magnetmotor.ch/umrech ... chner.html
wollte ich nun mit der WebSerial API auf die serielle Schnittstelle zugreifen
Beschreibung MC.net:
https://www.mikrocontroller.net/topic/556536
Manual zu Chrome:
https://developer.chrome.com/docs/capab ... rial?hl=de
Aber schon der einfachste Versuch mit

Code: Alles auswählen

port = await navigator.serial.requestPort();
schlägt fehl, also genau lädt nicht mal die Seite.
Das Testprogramm:

Code: Alles auswählen

Procedure GadgetEvents()
  
  Select EventGadget()  ; To see which menu has been selected
      
    Case 2 ;Umrechnen
      EnableJS
      v_port = await navigator.serial.requestPort();
      ;await port.open({ baudRate: 9600 });
      DisableJS
      SetGadgetText(10, "Test")
      
    Default
      ;

  EndSelect

EndProcedure


;
; We just have to open a window and see when an event happen on the menu
;
If OpenWindow(0, 0, 0, 300, 220, "WebSerial Test", #PB_Window_TitleBar + #PB_Window_ScreenCentered)
  
  ButtonGadget(2, 30, 50, 240, 20, "Testen")

  TextGadget(9, 30,  170, 180, 20, "Ausgabe:")
  StringGadget(10, 220, 170, 50, 20, "0", #PB_String_ReadOnly)
  
  BindEvent(#PB_Event_Gadget, @GadgetEvents())
EndIf
Das Ganze in JS zu machen schreckt mich anhand der Kompliziertheit etwas ab. Deshalb die Frage: Ist das überhaupt möglich mit SB? Am Schluss möchte ich einfach mit ein paar Buttons verschiedene Strings schicken und die Antwort im StringGadget anzeigen. Das Programm darf explizit blockierend auf den Antwort-String warten (endet mit \n).

Danke und
Gruss Chregu
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Kiffi »

await darf nur in async - Funktionen aufgerufen werden:

Code: Alles auswählen

Procedure GadgetEvents()
  
  Protected Port
  
  Select EventGadget()
      
    Case 2 
      
      ! async function test() {
      !   v_port = await navigator.serial.requestPort();
      
      ; ....
      
      ! }
      
      ! test();
      
    Default
      
  EndSelect
  
EndProcedure


If OpenWindow(0, 0, 0, 300, 220, "WebSerial Test", #PB_Window_TitleBar + #PB_Window_ScreenCentered)
  ButtonGadget(2, 30, 50, 240, 20, "Testen")
  TextGadget(9, 30,  170, 180, 20, "Ausgabe:")
  StringGadget(10, 220, 170, 50, 20, "0", #PB_String_ReadOnly)
  BindEvent(#PB_Event_Gadget, @GadgetEvents())
EndIf
a²+b²=mc²
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Danke Kiffi!
Das funktioniert!
Gruss Chregu
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Jetzt kommt natürlich das nächste Problem:

Code: Alles auswählen

Case 3 ;Daten senden
      EnableJS
      async function senden() {
        const writer = v_port.writable.getWriter();
        const Data = new Uint8Array([104, 101, 108, 108, 111]); // hello
        await writer.write(Data);
        // Allow the serial port To be closed later.
        writer.releaseLock();
      }
      senden();
      DisableJS
Erscheint in der Browser-Konsole:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'getWriter')
Wenn ich das "v_" nach "const writer =" weglasse kommt keine Fehlermeldung, gesendet wird aber nichts. Ich vermute einerseits, dass Variablen von einem InlineJS zum Nächsten "vergessen" werden, andererseits warscheinlich der Typ nicht stimmt. Scheint ja ein Objekt zu sein.
Diesbezüglich hält sich die Anleitung zu SB sehr spartanisch.

Gruss Chregu
Gruss Chregu
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Kiffi »

In dem Fall solltest Du "Port" global deklarieren. Der Variablenpräfix ändert sich dann von "v_" zu "g_":

Code: Alles auswählen

Global Port

Procedure GadgetEvents()
  
  Select EventGadget()
      
    Case 2 
      
      ! async function oeffnen() {
      !   g_port = await navigator.serial.requestPort();
      !   // ...
      ! }
      
      ! oeffnen();
      
    Case 3
      
      ! async function senden() {
      !   const writer = g_port.writable.getWriter();
      !   // ...
      ! }
      
      ! senden();
      
    Default
      
  EndSelect
  
EndProcedure
(Das ist aber auch ein ganz normales Vorgehen in der Programmierung und hat nichts speziell mit SpiderBasic oder JavaScript zu tun)
a²+b²=mc²
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Danke, so geht's!
In dem Fall solltest Du "Port" global deklarieren. Der Variablenpräfix ändert sich dann von "v_" zu "g_":
Fast. Ich zitiere aus dem HTML Help:
Here are the naming rules to use when accessing SpiderBasic items: - JavaScript variable name is the same in lowercase with a 'v_' prefix. It's the same for local variable, global variable and function parameter.
Das ist aber auch ein ganz normales Vorgehen in der Programmierung und hat nichts speziell mit SpiderBasic oder JavaScript zu tun
Ich konnte mir nur noch nicht vorstellen, wie der Variablenaustausch zwischen den Beiden funktioniert.
Gruss Chregu
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Kiffi »

Chregu hat geschrieben: 21.12.2023 15:50Fast. Ich zitiere aus dem HTML Help:
Here are the naming rules to use when accessing SpiderBasic items: - JavaScript variable name is the same in lowercase with a 'v_' prefix. It's the same for local variable, global variable and function parameter.
Das war früher einmal so. Die Dokumentation bedarf hier einer Überarbeitung. Den Präfix von (globalen) Variablen kannst Du Dir ganz gut in der Developer-Konsole Deines Browser anschauen.
a²+b²=mc²
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Danke Kiffi!
Ich komme dann wahrscheinlich noch einmal wegen dem reader mit einer Frage, das ist ja noch ein bisschen komplizierter...
Gruss Chregu
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Also das

Code: Alles auswählen

      EnableJS
      async function verbinden() {
        g_port = await navigator.serial.requestPort();
        await g_port.open({ baudRate: 9600 });
      }
      verbinden();
      DisableJS
      SetGadgetText(10, "Serielle Schnittstelle geöffnet")
funktioniert schön. Aber ich wollte jetzt das Programm erweitern. Momentan wird sofort nach dem Klick auf "Verbinden" (das den Schnipsel aufruft) "Serielle Schnittstelle geöffnet" angezeigt, was ja manchmal nicht stimmt. Also das Problem ist, dass der Funktionsaufruf nicht auf das Ende wartet (was ja auch normal zu sein scheint) und ich keine Rückgabewerte bekommen kann. Also weder:

Code: Alles auswählen

      EnableJS
      async function verbinden() {
        try {
          g_port = await navigator.serial.requestPort();
          await g_port.open({ baudRate: 9600 });
          // Erfolgreiche Verbindung, also return null oder eine Erfolgsmeldung
          g_fehler = 0;
        } catch (err) {
          if (err.name === 'AbortError') {
            g_fehler =  42;
          } else if (err.name === 'NotAllowedError') {
            g_fehler =  43;
          } else if (err.name === 'SecurityError') {
            g_fehler =  44;
          } else {
            g_fehler =  45;
          }
        }
      }
      async function starten() {
        await verbinden();
      }
      //verbinden();
      starten();
      DisableJS
      MessageRequester("Rückgabewert: "+Str(fehler), #PB_MessageRequester_Ok)
      SetGadgetText(10, "Serielle Schnittstelle geöffnet")
noch das Gleiche mit return geht nicht. Der Requester für die Schnittstelle erscheint dann gar nicht (bzw. scheint gar nicht zu erscheinen) stattdessen bekomme ich sofort 0 zurück, und beim nächsten Mal 45.
Diese .html Datei mit rein JS funktioniert:

Code: Alles auswählen

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Serial Port Verbindung</title>
</head>
<body>
  <button id="connectButton">Verbindung herstellen</button>
  <script>
    let g_fehler = 0;

    async function verbinden() {
      try {
        const port = await navigator.serial.requestPort(); // Warten auf Benutzerinteraktion
        if (!port) {
          console.error("Kein Port ausgewählt");
          return;
        }
        
        await port.open({ baudRate: 9600 });
        g_fehler = 0; // Erfolgreiche Verbindung
        console.log("Verbindung erfolgreich mit Port:", port);
      } catch (err) {
        // Fehlerbehandlung
        if (err.name === 'AbortError') {
          g_fehler = 42;
        } else if (err.name === 'NotAllowedError') {
          g_fehler = 43;
        } else if (err.name === 'SecurityError') {
          g_fehler = 44;
        } else {
          g_fehler = 45;
        }
        console.error("Fehler bei der Verbindung:", err);
      }
    }

    // Benutzerinteraktion auslösen
    document.getElementById('connectButton').addEventListener('click', async () => {
      await verbinden();
      console.log("Fehlercode:", g_fehler);
    });
  </script>
</body>
</html>
Ich weiss nicht mehr weiter. Ich möchte nur, dass ich weiss, ob die Schnittstelle zur Verfügung steht, und dies beim Drücken anderer Buttons zum Senden verschiedener Strings berücksichtigt wird (Userfreundlichkeit). Momentan funktionierts so:
https://chregu73.github.io/carparameter.html

Gruss Chregu
Gruss Chregu
Chregu
Beiträge: 22
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Re: WebSerial mit SpiderBasic überhaupt möglich?

Beitrag von Chregu »

Der Requester für die Schnittstelle erscheint dann gar nicht (bzw. scheint gar nicht zu erscheinen)
Habe jetzt herausgefunden, dass wirklich nicht zu Erscheinen scheint. Wenn man die Ausgabe in die Konsole oder in ein Text-Gadget macht, geht es.

Aber der Unterschied ist, dass der in HTML eingebettete Code funktioniert, mit warten, aber in SpiderBasic nicht. Irgendwie funktioniert das mit dem async / await nicht richtig!

Gruss Chregu
Gruss Chregu
Antworten