mchott Geschrieben July 3, 2015 at 06:21 Geschrieben July 3, 2015 at 06:21 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. Zitieren
Nic Geschrieben July 3, 2015 at 07:45 Geschrieben July 3, 2015 at 07:45 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; }; Zitieren
mchott Geschrieben July 3, 2015 at 08:36 Autor Geschrieben July 3, 2015 at 08:36 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. Zitieren
Nic Geschrieben July 3, 2015 at 10:14 Geschrieben July 3, 2015 at 10:14 Sorry ich meinte das nur ganz generell, eine mögliche Erweiterung/Anpassung in den JS-Bindings für Webworkers. Zitieren
mchott Geschrieben July 3, 2015 at 10:51 Autor Geschrieben July 3, 2015 at 10:51 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. Zitieren
mchott Geschrieben July 3, 2015 at 10:52 Autor Geschrieben July 3, 2015 at 10:52 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 Zitieren
photron Geschrieben July 6, 2015 at 16:16 Geschrieben July 6, 2015 at 16:16 "global.window.Tinkerforge" ist redundant, es reicht auch "global.Tinkerforge" für das gleiche Ergebnis. Damit funktionieren die Bindings hier auch in einem einfachem WebWorker Test. Tinkerforge.js Zitieren
mchott Geschrieben July 7, 2015 at 06:34 Autor Geschrieben July 7, 2015 at 06:34 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? Zitieren
photron Geschrieben July 7, 2015 at 09:10 Geschrieben July 7, 2015 at 09:10 Wird das Binding in Zukunft entsprechend angepasst? Habe es gerade so abgeändert im git. Die nächste Version wird diese Änderung beinhalten. Zitieren
Nic Geschrieben July 7, 2015 at 09:20 Geschrieben July 7, 2015 at 09:20 Diese WebWorker kenne ich so noch nicht, klingt aber sehr interessant. Lässt sich das Prinzip der WebWorker auch für eine serverseitige node.js Anwendung einsetzen, oder muss ich da was beachten ? Zitieren
raphael_vogel Geschrieben July 7, 2015 at 10:56 Geschrieben July 7, 2015 at 10:56 Im NPM gibt es dazu ein(ige) Module, z.B. https://www.npmjs.com/package/webworker-threads Zitieren
Nic Geschrieben July 7, 2015 at 11:00 Geschrieben July 7, 2015 at 11:00 Aha danke, Raphael. Und die Tinkerforge Bindings lassen sich dann auch innerhalb dieser WebWorkers serverseitig verwenden ? Zitieren
mchott Geschrieben July 7, 2015 at 11:04 Autor Geschrieben July 7, 2015 at 11:04 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. Zitieren
Nic Geschrieben July 7, 2015 at 12:33 Geschrieben July 7, 2015 at 12:33 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. Zitieren
mchott Geschrieben July 7, 2015 at 13:27 Autor Geschrieben July 7, 2015 at 13:27 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. Zitieren
photron Geschrieben July 7, 2015 at 14:48 Geschrieben July 7, 2015 at 14:48 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. Zitieren
mchott Geschrieben July 7, 2015 at 20:26 Autor Geschrieben July 7, 2015 at 20:26 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. Zitieren
photron Geschrieben July 8, 2015 at 13:01 Geschrieben July 8, 2015 at 13:01 Die Zeilen stammen auf dem letzten Release der JavaScript Bindings. Das ist nicht die korrigierte Datei aus meinem Post. Teste mal die angehängte Version, bei der jetzt auch die Crypto Verwendung korrigiert ist.Tinkerforge_window_fixes.js Zitieren
mchott Geschrieben July 9, 2015 at 21:54 Autor Geschrieben July 9, 2015 at 21:54 Jap..das Binding funktioniert tadellos samt der Verwendung eines Schlüssels. Kompliment für die schnelle Reaktion. Zitieren
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.