DMX Steuerung Selbstbau? Teil 7 Vom Browser zum Licht

Jetzt gibt es schöne Fader. Nun muss der eingestellte Wert aber auch wirklich zum gewünschten Ergebnis führen. Bisher gibt es noch keine Funktion. HTML und PHP alleine können das nicht vernünftig lösen. Damit die Seite nicht bei jeder Änderung neu geladen werden muss, muss Java Script verwendet werden.

Der Fader sieht in HTML folgendermaßen aus:

<input type="range" name="rangeInput" min="0" max="255" onchange="WriteSingleDMXValue(this.value,0);"

Über den Namen muss man später noch einmal nachdenken. Aktuell Spielt er keine Rolle. Der Maximalwert liegt bei 2 hoch 8. Was einem 8 Bit Wert entspricht. Also 256 Abstufungen pro Kanal.

Wenn der Wert sich geändert hat, wird die Funktion WriteSingleDMXValue aufgerufen. Der erste Parameter ist der Wert des Faders. Also ein Wert zwischen 0 und 255. Der Zweite Wert ist die Kanalnummer des DMX Kanals. Der Parameter „onchange“ verhält sich bei verschiedenen Browsern unterschiedlich. Bei Firefox funktioniert es so wie es soll. Mit abgeschaltetem Java Script funktioniert es gar nicht.

Das aufgerufene Script sieht erst einmal sehr einfach aus, hat es aber doch in sich. Es wird ein unabhängiger Zugriff auf eine Adresse gestartet. Dabei gibt es einige Einschränkungen des Browser die man beachten muss. Prinzipiell wird ein Zugriff auf eine PHP Datei mit angehängten Parametern „simuliert“. Ein offener Punkt ist, ob man die Verbindung jedes mal mit einem Close schließen muss, oder ob man es so lassen kann.

<script>
  'use strict'
  function WriteSingleDMXValue(wert,kanal){
  var phpzugriff = new XMLHttpRequest();
  phpzugriff.open("GET","EinzelWert.php?wert=" + wert + "&kanal=" + kanal ,wert);
  phpzugriff.send();
  }

</script>

Die Aufgerufene PHP Datei ist wirklich simpel, und reicht die Werte einfach an eine C Funktion weiter. Der Aufruf erfolgt wie ein Konsolen Aufruf.

<?php

$wert = $_GET['wert'];
$kanal = $_GET['kanal'];

$Kommando = "./EinzelWert ";
$Kommando .=  $kanal;
$Kommando .= " ";
$Kommando .=  $wert;
$Kommando .= "\n";

$output = system($Kommando);

?>

In der C Funktion wird zuerst die Anzahl der Parameter überprüft:

      //***************************************************
      // Parameter Überprüfen
      //***************************************************
      if(iAnzahlParameter != 3)
      {
         printf("Anzahl der Argumente nicht korrekt.\n");
         printf("Befehl: EinzelWert [Kanalnummer] [Kanalwert]\n");
      }

Dann müssen die Werte in „vernünftige“ Zahlen konvertiert werden. Zum Schluss werden Hex-Werte benötigt. Die werden hier erzeugt:

         iKanalnummer=atoi(argv[1]);
         iKanalwert=atoi(argv[2]);
         if(iKanalnummer >= 512)
         {
            printf("DMX Kanalnummer zu groß! Wert ist:%d\n",iKanalnummer);
            return(0);
         }
         if(iKanalwert > 255)
         {
            printf("DMX Kanalwert zu groß! Wert ist:%d\n",iKanalwert);
            return(0);
         }

Zum Glück gibt es schon eine fertige Funktion (atoi) dafür. Selber konvertieren ist in C etwas lästig.

Jetzt kommt noch das altbekannte auslesen der Sende Datei. Dann muss ein einziger Wert geändert werden:

Buffer[DATEN_OFFSET + iKanalnummer]=iKanalwert;

Und zum Schluss wird wieder geschrieben.

Auch in dieser Funktion fehlt noch eine vernünftige Fehlerbehandlung beim Dateizugriff. Sollte duch Nebenläufigkeiten ein Zugriffsfehler auftreten, geht der Wert zum schreiben einfach verloren.

Zum Schluss noch die komplette C Datei zum schreiben eines einzelnen Wertes:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


#define ANZAHL_BYTES 518
#define DATEN_OFFSET 5

int main(int iAnzahlParameter, char *argv[])
{
  //***************************************************
  // Variablen
  //***************************************************
  char Buffer[ANZAHL_BYTES];     //Puffer für Daten
  int i;                         //Zählvariable für Schleife
  FILE *fDaten_Datei;            //Datei Handle für DMX Werte
  int iKanalnummer;
  int iKanalwert;

  //***************************************************
  // Code
  //***************************************************
      //***************************************************
      // Parameter Überprüfen
      //***************************************************
      if(iAnzahlParameter != 3)
      {
         printf("Anzahl der Argumente nicht korrekt.\n");
         printf("Befehl: EinzelWert [Kanalnummer] [Kanalwert]\n");
      }
      else
      {
         iKanalnummer=atoi(argv[1]);
         iKanalwert=atoi(argv[2]);
         if(iKanalnummer >= 512)
         {
            printf("DMX Kanalnummer zu groß! Wert ist:%d\n",iKanalnummer);
            return(0);
         }
         if(iKanalwert > 255)
         {
            printf("DMX Kanalwert zu groß! Wert ist:%d\n",iKanalwert);
            return(0);
         }


      }


      //***************************************************
      // Hole Daten vom Dateisystem
      //***************************************************
      fDaten_Datei = fopen("/var/www/html/Config/SendeDaten.dmx","r");
      if(fDaten_Datei == 0)
      {
         printf("SendeDaten.dmx fehlt! \n");
      }
      else
      {
        fread(Buffer,ANZAHL_BYTES,1,fDaten_Datei);
        //***************************************************
        // Schließe Datei
        //***************************************************
        fclose(fDaten_Datei);
      }


      //***************************************************
      // Ändern eines einzelnen Wertes
      //***************************************************
      Buffer[DATEN_OFFSET + iKanalnummer]=iKanalwert;

      //***************************************************
      // Öffne Datei zum Schreiben
      // Und schreibe zeilenweise konvertierte Daten
      //***************************************************
      fDaten_Datei = fopen("/var/www/html/Config/SendeDaten.dmx","w+");
      if(fDaten_Datei == 0)
      {
         printf("Kann SendeDaten.dmx nicht öffnen! \n");
      }
      else
      {
        fwrite(Buffer,ANZAHL_BYTES,1,fDaten_Datei);
        fclose(fDaten_Datei);
      }


  return(1);
}