Jump to content

[GELÖST] HTML5 Worker implementieren geht nicht .. geht doch


Recommended Posts

Ich bin dabei eine auf JS basierende Anwendung zu erstellen und bin dabei auf ein Problem gestoßen. JS ist derzeit wegen der "Leichtigkeit" in der Verwendung, nicht weil es möglicherweise die für das Problem beste Sprache ist.

 

Es gibt seit HTML5 das Prinzip der Worker, die eine Art Nebenläufigkeit ermöglichen. Nun dachte ich, es wäre vielleicht die ideale Lösung, um >6 Servo´s "gleichzeitig" (fast) anzusteuern, weil es mit rein serial geschriebenem Code etwas versetzt abläuft. Je schneller die Servos arbeiten, desto mehr kommt man in das Problem, dass das erste Servo schon an der neuen Position ist, aber das letzte noch nicht gestartet ist. Über verschiedene Wege kann mann das immer enger zusammenbringen.

 

Ein noch besserer Weg wären möglicherweise die neuen Worker, aber das JS-Binding kann da nicht eingesetzt werden, weil die Worker kein document/window/..-Bezug erlauben, welcher aber im Binding enthalten ist. Vielleicht kann man darauf verzichten, wo das Binding, ja keinen Bezug zum Dom aufbaut. Eventuell baut man auch ein separates Binding mit reduziertem Umfang speziell für Worker?!

 

Ist nur eine Anregung, weil performante HTML5 wie Pilze aus dem Boden schießen.

Link zu diesem Kommentar
Share on other sites

Oh, sehr interessant. Besten Dank, mchott. Webworkers http://www.w3schools.com/html/html5_webworkers.asp kannte ich noch nicht. Aber im Prinzip besser als die ständige Anbindung zum GUI, und wenn ich es richtig verstanden habe, durchaus geeignet im Falle der asynch. Brick-Callbacks z.B. mit

w.onmessage = function(event){
    document.getElementById("result").innerHTML = event.data;
}; 

Link zu diesem Kommentar
Share on other sites

Das habe ich jetzt noch nicht ganz verstanden..:-)

 

Es wäre (in meinem Fall ja so):

 

INIT:

var i = 0; 
var Worker = new Array(); 
while(i<7) { 
  var Worker[i] = new Worker('SimpleServoWorker');
  Worker[i].addEventListener('message', function (e) { ..was getan werden soll, wenn der Worker etwas ausgibt.. }, false);
}

 

POSITIONIERUNG (kann ständig aufgerufen werden und teilt dem Worker nur schnell mit, was er machen soll)

Worker[i].postMessage({'Position':'0','ServoId':'5','TimeToRun':'5' ..und was der Worker sonst noch wissen muss..});

(TimeToRun .. wie lange er sich zeitlassen soll um die Position zu erreichen)

 

DER SimpleServoWorker

self.addEventListener('message', function(e) { 
  importScripts('Tinkerforge.js'); 
  var Act = ..per Tf eine Verbindung zu diesem Servo aufbauen..; 
  var Request = e.data; 
  var CurPos = ..per Tf ermitteln..; 
  var PosDiff = CurPos - Request.Position; 
  var Velocity = PosDiff / Request.TimeToRun; 
  Act.setVelocity(0, Velocity); 
  Act.setPosition(0, Request.Position); 
  self.postMessage({'Infos an den Auslöser':'geben, die für den Callback gebraucht werden'});
});

 

So in der Art. Das hat den Vorteil, dass man im "Vordergrund" nur die neue Position mitteilt und im Hintergrund eine stehende Verbindung zum Brick besteht. Zudem könnte man damit dann "aufwendigere" Berechnungen durchführen, wie die von mir schon gepostete "Deceleration", die über das Frontend einfach zu langsam läuft. Ideal auch, weil die Ansteuerung vieler Servos nur noch durch die Zeit für die Mitteilung der neuen Position verzögert wird und nicht mehr durch die Ausrechnung und Ansteuerung je Servo nacheinander.

 

Ich habe das exemplarisch schon aufgebaut und wollte die Bindings auch händisch anpassen, aber dafür kenne ich den Aufbau des Bindings dann doch zu wenig und bin selbst zu wenig Entwickler, um das performant umzusetzen.

Link zu diesem Kommentar
Share on other sites

Soweit mein Verständnis derzeit reicht, sieht es so aus - bin da aber kein Experte - dass man ein separates Binding erstellen muss, was dann für WebWorker läuft.

 

Grund der Annahme: Man kann wohl keine komplexen Objekte übergeben. Man kann nur Skripte verwenden, die keinen dom Bezug haben.

 

Auswirkung: Würde man die Standard-Bindings verwenden, dann würde deren Verwendung ausserhalb vom Worker nicht mehr so komfortabel sein..wie ich es bis jetzt verstanden habe werden deswegen diese "global.window.Tinkerforge" Aufrufe verwendet.

Link zu diesem Kommentar
Share on other sites

Da hab ich noch etwas dazu gelesen: http://html5rocks.appspot.com/de/tutorials/workers/basics/

 

Aus dieser Quelle:

Für Worker verfügbare Funktionen

 

Aufgrund ihres Multithread-Verhaltens können Web Worker nur auf einen Teil der Funktionen von JavaScript zugreifen:

 

    Das navigator-Objekt

    Das location-Objekt (schreibgeschützt)

    XMLHttpRequest

    setTimeout()/clearTimeout() und setInterval()/clearInterval()

    Den Anwendungscache

    Import externer Skripts mithilfe der importScripts()-Methode

    Erzeugen weiterer Web Worker

 

Worker haben KEINEN Zugriff auf:

 

    Das DOM (nicht threadsicher)

    Das window-Objekt

    Das document-Objekt

    Das parent-Objekt

 

Link zu diesem Kommentar
Share on other sites

Danke..das hatte ich am Sonntag Abend noch herausgefunden und bisher noch keine Zeit es hier zu posten.

 

Damit funktioniert es wunderbar, lediglich das Handling der WebWorker braucht etwas mehr Aufmerksamkeit, weil diese neue Parallelisierung auch noch "gelernt" werden möchte.

 

Wird das Binding in Zukunft entsprechend angepasst?

Link zu diesem Kommentar
Share on other sites

Gute Frage..es ist in meinen Quellen immer von JavaScript die Rede, aber immer mit dem Fokus auf clientseitig. Aber ich denke, dass node.js das auch implementiert hat. Leider beherrsche ich kein node.js (bin da ausgestiegen, weil mir einiges zu kompliziert erschien und ich nur Kleinkram brauche).

 

Hier wird beschrieben, dass es das wohl geht:

http://webkrauts.de/artikel/2011/serverseitiges-javascript-mit-nodejs

 

Ausprobieren und vielleicht hier kurz eine Rückmeldung über den Erfolg. Die WebWorker sind ja recht leicht implementiert und getestet. Ich muss derzeit nur meine Anwendung umbauen, weil die WebWorker ja doch im Ablauf einiges verändern.

Link zu diesem Kommentar
Share on other sites

Die JS-Bindings von Tinkerforge verwende ich serverseitig in einer node.js Anwendung ohne Probleme, allerdings erstmal nur sehr banal. Callback-Werte des AnalogIn wird direkt an ein Display http://www.yoctopuce.com/EN/products/usb-displays/yocto-minidisplay von yoctopuce ausgegeben.

 

Wofür sich die WebWorker innerhalb einer TF-Projektes ideal verwenden erschließt sich im Moment zwar nicht ganz, aber für langweilige Statusausgaben könnte ich mir vorstellen das zu verwenden.

Link zu diesem Kommentar
Share on other sites

Das Binding hat in der Zeile 12810 ein ".window" zu viel und ohne dem lässt sich das Binding dann auch im WebWorker verwenden.

 

Ich brauche die WebWorker - und dafür sind sie grundsätzlich gedacht - um Aufgaben parallel sowie von der Bedienung entkoppelt ablaufen zu lassen. Wenn eine Aktion in Summe 1s dauert und dabei >6 Servos möglichst simultan angesteuert werden sollen. Dann aber die Bewegung berechnet werden muss, weil in der nächsten 1s die sich ändert, dann schaffe ich das nicht im SingleThread Ablauf. So übergebe ich jedem WebWorker eine Steuerungsaufgabe je Servo und teile dem WebWorker´n nur noch die neue Aufgabe mit.

 

Derzeit macht es bei mir den Eindruck, dass es genau mein Leistungsproblem löst.

 

Früher habe ich z.B. aufwendigere Operationen ausgelagert, wie beispielsweise Daten abrufen und "aufhübschen" oder Grafiken berechnen und dergleichen. Ein simples Auslesen von Zuständen und diese dann anzeigen, wäre meiner Meinung nach auch so zu lösen, wobei ein permanentes (fast Echtzeit) Anzeigen ist vielleicht schon ganz sinnig, wenn man das im Browser machen möchte und gleichzeitig die GUI aber stabil stehen soll.

Link zu diesem Kommentar
Share on other sites

Das Binding hat in der Zeile 12810 ein ".window" zu viel und ohne dem lässt sich das Binding dann auch im WebWorker verwenden.

 

In meiner Zeile 12810 steht ein langer Kommentar. Kannst du mal deine Zeile 12810 mit 5 Zeilen davor und danach posten, damit ich sehe was du meinst.

 

Die letzte Verwendung von window bei mir ist in der getRandomUInt32() Funktion um an die Crypto Funktionen zu kommen. Das muss ich gleich noch ändern.

Link zu diesem Kommentar
Share on other sites

Also bei mir steht folgendes:

 

	this.BrickletTilt = require('./BrickletTilt');
this.BrickletVoltage = require('./BrickletVoltage');
this.BrickletVoltageCurrent = require('./BrickletVoltageCurrent');
}

global[b][color=red].window[/color][/b].Tinkerforge = new Tinkerforge();}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./BrickDC":1,"./BrickIMU":2,"./BrickMaster":3,"./BrickRED":4,"./BrickServo":5,"./BrickStepper":6,"./BrickletAmbientLight":7,"./BrickletAnalogIn":8,"./BrickletAnalogOut":9,"./BrickletBarometer":10,"./

 

Was ich aber mittlerweile feststelle ist, dass nicht alles geht, wenn man das Binding verwendet. Für das Handling mit dem Secret wird ebenfalls das window verwendet und damit gehen nur Verbindungen ohne vergebenes Secret.

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...