Cover Image

Websocket in Python

Kommunikation ist alles

Juni 14, 2022 - Lesezeit: 10 Minuten

Wenn man mit dem Symolo Server kommunizieren will, ist nicht einfacher als mit einem Websocket darauf zuzugreifen. Das Protokoll ist einfach und lässt sich schnell umsetzten. Keine kompizierten XML Querys oder umfangreiche Anmeldung ist erforderlich. Lediglich ein Autentifizierungstoken muss vorliegen und kann im Vorfeld angefragt werden. Oder, wenn es komplizierter sein soll, kann man auch eine Sitzung anfordern und ist da sogar mit einer Benutzerkennung unterwegs. Mithilfe dieses Verfahrens lassen sich kleinere Anforderungen schnell umsetzten und der Websocket ist inzwischen in den meisten höheren Programmiersprachen Out-of-the-Box verfügbar. Zumindest in den Programmiersprachen in denen Symolo am meisten unterwegs ist. Inzwischen gehört auch Python dazu, da getreu dem Motto, "the right tool for the job", Python bestimmte Aufgaben deutlich eleganter oder effektiver erledigen kann als eine andere höhere Programmiersprache.

Um nun mit dem Symoloserver in Kontakt zu treten ist lediglich das websocket-client paket erforderlich.

from websocket import create_connection # pip install websocket-client

Um die Kommunikation zu vereinfachen können wir noch die JSON Bibliothek importieren, die unser Nachrichtenerstellen nochmal vereinfacht.

import json

Nun ist es uns zum Beispiel möglich ein einfaches Dateihochladen zu realisieren:

ws = create_connection("<myWebsocketEndpoint>")
ws.send(json.dumps({
    "sid": "<mySecretCode>",
    "cmd": "dsf.cmd.verwaltung.FileManager.WriteFileBase64",
    "par": [
        '<myFilename>',
        '<myBase64Data>'
    ]
}))
ws.close()

Damit kann nun eine Datei im Server hinterlegt werden. Wir verzichten hier auf die Auswertung der Antwort, weil diese hier nicht relevant ist. Wenn das schief geht, kann das im Serverlog eingesehen werden.

Natürlich kann man den Server auch nach Informationen fragen und bekommt sogar Antwort. Auch hier ist das Protokoll einfach gehalten:

ws = create_connection("<myWebsocketEndpoint>")

ws.send(json.dumps({
    "sid": "<mySecretCode>",
    "cmd": "dsf.server.Info.GetInstanceName",
    "par": []
}))

result = ws.recv()

print(result)

ws.close()

Hier ist die Interpretation der Antwort von der Frage abhängig, der Server versucht immer den einfachsten Datentypen zu senden. Kompliziertere Strukturen werden in JSON abgebildet. Das lässt sich in Python aber auch wieder einfach laden:

data = json.loads(result)

Mithilfe dieser Werkzeuge wird die Kommunikation mit dem Symoloserver einfach möglich und sämtliche Funktionen des Servers können nun verwendet werden. Hierzu zählen z.B. dynamicszugriff via SQL, erstellen und drucken von PDFs unter Windows wie Linux, Zugriff auf verschiedenste objektrelationale Datenbanken, Dateiverwaltung oder Nachrichtenverteilsystem. Darüber sollte ich mal was schreiben.

Nachdem das jetzt geklärt ist, bin ich mal gespannt, was in Python damit alles angestellt wird.


Cover Image

Typeisch C#

Lovely ArrayList

März 17, 2022 - Lesezeit: ~1 Minute

Arraylist ist der tollste Datentyp überhaupt. Ich mag normale Arrays. Wie machen wir da jetzt ein draus. Ganz einfach:

ArrayList newList = new ArrayList();
newList.Add("1");
newList.Add("2");
string[] ParamNameListArray = (string[])newList.ToArray(typeof(string));
object[] ParamDataListArray = (object[])newList.ToArray(typeof(object));
Console.WriteLine(ParamNameListArray);
Console.WriteLine(ParamDataListArray);

C# und die Typen. Wenn man fast nur noch in JavaScript unterwegs ist, ist das schon fast eine Tortur.


Cover Image

Fun with HTML5

making some noise

November 2, 2021 - Lesezeit: 25 Minuten

Jetzt gibt es soviele verschiedene Betriebssysteme und so viele unterschiedliche Musikplayerprogramme von VLC über mplayer oder der im Windows integrierte Grooveplayer. Nur sind die meisten Programme entweder nicht direkt installiert oder umständlich einzurichten, wollen ins Internet um irgendwas runterzuladen oder erstmal die ganze Festplatte durchsuchen. Ich will doch einfach nur ein paar mp3 Dateien anhören. Aber es gibt ja glücklicherweise den Browser, der das Abspielen von Musikdateien im HTML5 Standard ja bereits unterstützt. Super, also schnell die mp3 Datei gesucht und via Drag und Drop in den Browser ziehen und schon wird sie abgespielt. Nach 5 Minuten dann die nächste Datei draufziehen. Und dann nach 5 Min.? Genau: nächste Datei draufziehen. Nach 20 Min. war mir das dann zu doof und zu zeitaufwändig. Aber bis ich jetzt im Grooove mir was zusammengezogen habe und das Ganze dann noch für mein Linux und mein Androiden zusammengstellt habe, kam mir die Idee, warum nicht alles einmal fertig machen und auf jeder Plattform genießen. Also hab ich das Ganze mal in eine Website gepackt:

<audio id="audio" preload="auto" tabindex="0" controls="" type="audio/mpeg">
<source type="audio/mp3" src="./Voodoo Suite - Little Grass Shack.mp3">
Sorry, your browser does not support HTML5 audio.
</audio>

Ok, das war easy. Jetzt kann ich eine Datei abspielen. Die Datei muss im selben Ordner liegen und das Ganze kann, in zusammenarbeit mit einem einfachen Webserver, sogar schon gestreamt werden. Ist aber nur eine Datei, brauchen wir noch eine Playlist:

<ul id="playlist">
<li><a class='active'href="./Voodoo Suite - Little Grass Shack.mp3">Voodoo Suite - Little Grass Shack.mp3 (Local)</a></li>
<li><a href="https://files.freemusicarchive.org/storage-freemusicarchive-org/music/WFMU/Voodoo_Suite/blissbloodcom/Voodoo_Suite_-_03_-_Little_Grass_Shack.mp3">Voodoo_Suite_-_03_-_Little_Grass_Shack.mp3</a></li>
</ul>

Ok, jetzt haben wir eine Playlist. Wenn ich die aber anklicke, dann navigiert der Browser und ich bin soweit wie vorher. Dann packen wir doch einfach noch ein bisschen oldskool Javascript dazu:

<script>
  var audio;
  var playlist;
  var tracks;
  function init() {
    audio = document.querySelector('#audio');
    playlist = document.querySelector('#playlist');
    tracks = playlist.querySelector('li a');
    let links = playlist.querySelectorAll('a');
    links.forEach(e => {
      e.onclick = (evt) => {
        evt.preventDefault();
        playlink(e);
      }
    });
    audio.addEventListener('ended', function (e) {
      var current = playlist.querySelector('li a.active');
      var next = current.parentNode.nextElementSibling;
      if (next) {
        let e = next.querySelector('a');
        playlink(e);
      }
      else {
        let links = playlist.querySelectorAll('a');
        playlink(links[0]);
      }
    });
  }
  function playlink(link) {
    let e = link;
    playlist.querySelectorAll('a').forEach(l => { l.classList.remove("active") });
    e.classList.add("active");
    audio.src = e.getAttribute('href');
    audio.load();
    audio.play();
  }
  init();
</script>

So, jetzt kann ich mir in der Playlist aussuchen was ich will und die ganze Liste läuft solange ich nicht stoppe. Ich kann ich der Playlist entweder lokale Einträge verwenden oder Quellen aus dem Internet. Das Ganze lässt sich mithilfe eines Webservers bequem bedienen und funktioniert sogar mit der Xbox. Was will man mehr. Kein generve vom VLC für Updates oder das Verhalten des mplayers unter windows. Man muss nur seinen Browser aktuell halten und das war's schon.

Das Javascript in diesem Beispiel kann zweifelsohne noch deutlich verbessert werden. Ist aber für den vorliegenden Fall vollkommen ausreichend. Denn sonst hätt ich ja auch einen Player installieren können.


Cover Image

Mit Node.js gegen den Rest der Welt

Heute: easy SFTP Upload

Juli 27, 2021 - Lesezeit: 14 Minuten

Immer mal wieder hat man die Anforderung schnell mal ein paar Dateien von einem Rechner auf einen anderen zu laden. Besonders wenn dann noch das Internet beteiligt ist, ist man bestrebt das Ganze auch noch sicher ablaufen zu lassen. Damit entfällt die alte aber zuverlässige Methode des FTP. Aber dafür hat man ja SFTP. Nodejs macht es einem dann sogar recht einfach, da es bereits ein paar tolle Pakete dafür gibt. Eins davon hab ich dann heute mal eingesetzt und wieder lässt sich ein Anforderung in wenigen Zeilen elegant lösen. 

Installation

npm i sftp-upload

Danach eigentlich nur noch passend konfigurieren und fertig:

const SftpUpload = require('sftp-upload');

async function uploadFiles() {
  return new Promise((resolve=> {
    process.stdout.write('\r');
    new SftpUpload({
      host: '<HOST HERE>',
      username: '<USER HERE>',
      password: "<PASS HERE>",
      path: './',
      remoteDir: '/<DIR HERE>',
      excludedFolders: ['node_modules'],
      exclude: ['package-lock.json''package.json'],
      dryRun: false
    })
      .on('error', (err=>  {throw err;} )
      .on('uploading',  (progress=>  process.stdout.write('\r' + progress.percent + '% completed'))
      .on('completed', () => {
        process.stdout.write('\r');
        resolve();
      })
      .upload();
  });
}

(async () => {
  await uploadFiles();
  console.log("DONE");
})();

Lässt sich super für Kontinuierliche Integration einsetzen und man könnte das ganze jetzt mit dem Komprimieren passend kombinieren. Jetzt muss das Ganze nur noch zyklisch ausgeführt werden...