Zusammenfassung

In diesem Beitrag geht es um die Verarbeitung von Maschinendaten in NodeRed. Die Daten werden von der WebAPI FORCAM bereitgestellt und kommen zunächst als String in NodeRed an. Nach der Konvertierung in ein JSONObjekt wird anschaulich erklärt, wie Spaltennamen des Objekts, sowie Datums und Zeitformate angepasst werden. Hierbei werden Funktionsbausteine mit der Programmiersprache JavaScript eingesetzt.
Dieser Kurzbeitrag ist im Rahmen des Kurses Advanced Manufacturing an der Hochschule für angewandte Wissenschaften WürzburgSchweinfurt (FHWS) entstanden.

1 Einführung und Problemstellung

Bereits in einem vorherigen Beitrag wurde auf das lokale Abspeichern von Maschinendaten aus FORCAM mit der Webversion von NodeRed eingegangen (Kristhofen, Weber und Wollert 2022). Bei einer ersten Sichtung dieser Daten aus FORCAM wurde festgestellt, dass die Datums und Zeitangaben im USamerikanischen Format ausgegeben werden. Zudem sollen die Spaltennamen, die in Abbildung 1 in doppelten Anführungszeichen angegeben sind, auf Deutsch übersetzt werden.
Das Formatieren von Daten, insbesondere von Zeitformaten, in Reportingtools, wie z.B. PowerBI oder Tableau, ist mit Schwierigkeiten verbunden.
Tableau beispielsweise erkennt zwar das Datenformat „Datum und Uhrzeit“, obwohl die USamerikanische Schreibweise übergeben wird, korrekt und kann diese auch bei Bedarf in ein europäisches Format umwandeln. Jedoch kann in dem Programm die Uhrzeit nicht vom Datum getrennt werden. Au-
ßerdem erkennt es die übergebene Zeitdauer nur als Textwert (String). Sobald hier der Typ des Feldes auf Integer (Ganzzahl) oder Float (Fließkommazahl) geändert wird, wird in den Feldern „null“ ausgegeben (Fehler/Leeres Feld).

In PowerBI hingegen hat der Benutzer die Möglichkeit zwischen weiteren Datenformaten zu wählen, so kann aus einem Datenformat Datum/Uhrzeit nur das Datum oder nur die Uhrzeit angezeigt werden.
Jedoch wandelt das Programm das Datum von der amerikanischen Schreibweise in die europäische Schreibweise um, ohne das Format zu ändern. So wird aus 06. Januar (06.01.2022) der 01. Juni (01.06.2022). Zeitdauern (02:00 min) wandelt das System, im Gegensatz zu Tableau, automatisch in
eine Dauer um. Das Umwandeln von z.B. Sekunden in Minuten als Dezimalzahl funktioniert jedoch nicht. Für das System ist eine Dauer von einem Tag gleich einer Eins. Dementsprechend ist eine Minute 1/1440 (1/ (24*60) = 0,000694). Es ist jedoch möglich, über Umwege auf ein gewünschtes Ergebnis zu kommen, bspw. die Angabe „01:30 min“ als 1,5 min darzustellen.

Um diese Schritte zu vermeiden, wird die Datentransformation in das gewünschte Format gleich an der erstmöglichen Stelle, und zwar im NodeRed, vorgenommen. Außerdem erleichtert diese Vorgehensweise die Lesbarkeit bei der späteren Ausgabe der Daten in einem Reportingtool, wie z.B. PowerBI oder Tableau.

Abbildung 1: Ausgabe der Maschinendaten in FORCAM (eigene Darstellung)

2 Vorgehen

Abbildung 2: Übersicht des gesamten NodeRed-Flows (eigene Darstellung)

Zunächst lohnt sich ein Blick auf die vorhandenen Daten und deren Format. Wie im vorigen Beitrag bereits erläutert, kommen die Daten aus FORCAM in NodeRed als JSONString an. Dieser muss dann in ein JSONObjekt umgewandelt werden, damit die Daten bearbeitet werden können (Abb. 2 Nr. 1).

Ein JSONObjekt hat im Vergleich zu einem JSONString den Vorteil, dass die Daten hierarchisch strukturiert sind und auf diese zugegriffen werden kann.

Abbildung 3 stellt beide Ausgabearten gegenüber.
Im Anschluss werden durch einen ChangeBlock die unnötigen Bestandteile der Abfrage gelöscht, da diese keine Maschinendaten enthalten. Dies sind die Objekte „msg.payload.pagination“ und „msg.payload._links“ (Abb. 2 Nr. 2).

Diese Datenobjekte werden beim Exportieren automatisch durch die FORCAM API erzeugt. Dabei beinhalten die Objekte „msg.payload.pagination“ lediglich allgemeine Informationen wie z.B. Gesamtanzahl der Datensätze. Außerdem werden die ausgewerteten Einträge in Paketen von maximal 100 Einträgen unterteilt. Diese Unterteilung hat für den Endanwender keinen Mehrwert.


Das Objekt „msg.payload._links“ beinhaltet nur den Link, der zur Abfrage der API verwendet wurde.
Die Entfernung der Daten wird vorgenommen, um den Benutzer bei der Analyse der Daten nicht zu verwirren und die Auswertung schlank zu halten.

Anschließend erfolgt die Beschreibung eines JSONObjekts und in einem Funktionsbausteinen die Umbenennung der Spaltennamen auf Deutsch (Abb. 2 Nr. 3).

Abbildung 3: Debug-Ausgabe der Maschinendaten in Node-Red: als JSON-String links und konvertiert in ein JSON-Objekt rechts (eigene Darstellung)

2.1 Aufbau eines JSON-Objektes

Im Folgenden wird auf den allgemeinen Aufbau eines JSONObjekts eingegangen. Das Gesamtobjekt, sowie weitere Unterobjekte sind mit geschweiften Klammern umschlossen. Spaltenbezeichnungen, sowie die darin enthaltenen Werte werden, wenn es sich um Strings handelt, in doppelten Anführungszeichen geschrieben. Einzelne Spalten sind untereinander mit Kommas getrennt. Die Inhalte eines Lis-
tenobjekts werden, wie in anderen Programmiersprachen, in eckigen Klammern dargestellt.

JSONObjekte können aus mehreren Ebenen bestehen. Um zwischen diesen zu wechseln, muss der Name der nächstniedrigeren Ebene gefunden werden. Dies kann in NodeRed durch einen debugBaustein gemacht werden.

Die übergeordnete Ebene in NodeRed stellt die Message „msg“ da. Die nächste Ebene, in der schon Daten gespeichert werden können, ist der „payload“. Eine Gliederstufe tiefer ist u.a. „_embedded[„AVODetailsRuestenWSAPLTT“]“ enthalten. Dieses Objekt enthält die von FORCAM kommenden Rüstdaten. Hierunter sind weitere Informationen enthalten.


Um sich durch die Stufen zu navigieren, werden zwischen den Objektbezeichnungen Punkte platziert, wie nachfolgend abgebildet ist:

msg.payload._embedded[„AVODetailsRuesten-WSAPL-TT“]

2.2 Umbenennung der Spaltennamen auf Deutsch

Begonnen wird mit dem Anlegen einer Zählvariable i für die ForSchleife. Zudem wird die Anzahl der Datensätze des übermittelten JSONObjekts, also dessen Länge, ermittelt. Dies geschieht mit der in JavaScript vorhandenen Funktion „length“. Es wird die Anzahl von „[„AVODetailsRuestenWSAPLTT“]“ des Objekts „msg.payload._embedded“ ermittelt.

Innerhalb dieses Teilobjekts befinden sich alle durchnummerierten Messwerte (in Abb. 4 die Werte 0 bis 72), die zum Zeitpunkt der Abfrage bereits aufgenommen waren. Die Einstellung des auszuwertenden Zeitraums wird in FORCAM vorgenommen und ist im vorherigen Beitrag erklärt (Kristhofen, Weber und Wollert 2022, Kapitel 2).

Die ForSchleife zählt nun von i=0 bis i=n und erhöht i bei jedem Durchlauf um 1. In jedem Durchgang, also für jeden Datensatz, werden die Werte aller Spaltennamen übersetzt. Hierzu muss wieder hierarchisch auf das richtige Teilobjekt zugegriffen werden. Die Datensätze befinden sich
in „msg.payload._embedded[„AVODetailsRuestenWSAPLTT“][i].properties“. Die englische Bezeichnung wird durch eine deutsche ersetzt und der Wert in den neuen Datensatz mit deutschem Namen geschrieben.

Dies ist im folgenden Code am Beispiel der Bestellnummer zu sehen: rot hervorgehoben sind die Spaltennamen, die Zählvariable i ist blau gekennzeichnet:

msg.payload._embedded[„AVODetailsRuesten-WSAPL-TT“][i].properties.BestellNr = msg.payload._embedded[„AVODetailsRuesten-WSAPL-TT“][i].properties.orderId;

Anschließend wird der englische Spaltenname mit der Funktion „delete“ gelöscht:

delete msg.payload._embedded[„AVODetailsRuesten-WSAPL-TT“][i].properties.orderId;

Abbildung 4: Hierachischer Aufbau des Payloads mit mehreren Ebenen (eigene Darstellung)

2.3 Änderung des Datums- und Zeitformates

Nachdem die Spaltennamen angepasst wurden, soll nun das Datums und Zeitformat geändert werden. Es gibt vier Spalten, die Datums und Zeitinformationen enthalten. Aufgrund der Übersichtlichkeit und um Programmierfehler zu vermeiden, wurde für jede Konvertierung ein eigener Funktionsbaustein in das Programm eingefügt (siehe Abb. 2, Nr. 4 7).
Zunächst wird auch hier eine Zählvariable i und eine weitere Variable n angelegt. Letztere enthält, wie im vorherigen Kapitel, die Anzahl der Datensätze von „msg.payload._embedded[„AVODetailsRuestenWSAPLTT“]“. Die ForSchleife läuft ebenfalls wieder von i=0 bis i=n mit der Schrittlänge 1.

Innerhalb der ForSchleife wird zunächst der jeweilige Datums und Zeitstempel in die Variable „zeit“ gespeichert. Der Vorgang wird hier am Beispiel der Spalte „Statuszeit“ erläutert:

var zeit = msg.payload._embedded[„AVODetailsRuesten-WSAPL-TT“][i].properties.Statuszeit;

Wie in Abbildung 1 zu sehen, baut sich jede Datums- und Zeitangabe folgendermaßen auf:

11/1/21, 7:57 AM

Zur Teilung des Strings wurde die Funktion „split“ verwendet. Das Zeichen, an dem getrennt werden soll wird in einfache Anführungszeichen in das Argument der Funktion geschrieben.
Um aus dem String Zeit und Datum zu extrahieren, wird zunächst am Komma getrennt. Gespeichert wird in das Feld „trennung“, welches nun zwei Werte besitzt. Diese sind das Datum und die Zeit.

var trennung = zeit.split(‚,‘);

Um auf den ersten Wert des Felds „trennung“, in dem das Datum gespeichert ist, zugreifen zu können, muss dieses mit dem Index 0 aufgerufen werden. Nun wird, wie oben, mit der Funktion split getrennt. Das Argument ist diesmal aber der Schrägstrich „/“. Gleiches passiert mit dem hinteren Teil des Felds „trennung“, das den Index 1 hat. Stunde und Minute sind durch einen Doppelpunkt getrennt, der das Argument einer weiteren SplitFunktion ist.

var datum = trennung[0].split(´/´);
var uhrzeit = trennung[1].split(´:´);

Nun wird die Variable „tageszeit“ initialisiert, die durch Trennung des zweiten Datenwerts des Felds „uhrzeit“ am Leerzeichen entsteht.

var tageszeit = uhrzeit[1].split(´ ´);

Zuletzt wird die Minute entnommen aus dem vorderen Teil des Felds „tageszeit“ (Index = 0) und eine Variable „std“ für die Stunde angelegt.

var min = tageszeit[0];

var std;

Da im US-amerikanischen Format die Stunden nur von eins bis zwölf gezählt werden und mit dem Zusatz AM für Zeiten vormittags und PM für nachmittags versehen werden, ist die Konvertierung hier komplizierter. Folgende Abbildung 5 gibt einen Überblick:

Abbildung 5: US-amerikanisches Zeitformat (Bikos und Kher 2021)

Der Wert AM bzw. PM steht im hinteren Teil des Felds „tageszeit“. Da es bei der Umrechnung entscheidend ist, ob „AM oder „PM“ vorliegt, wird mit einer if-else-Abfrage gearbeitet, die in Abbildung 6 dargestellt ist.

Im ifTeil wird der Fall „PM“ behandelt. Zunächst wird in einer weiteren ifelseAbfrage geprüft, ob die Stundenanzahl kleiner als 12 ist. In diesem Fall wird der Stundenwert vor der Konvertierung zuerst mit der parseIntFunktion von einem String in ein Integer, also eine Zahl, umgewandelt. Dies ist nötig, damit zur Umrechnung 12 Stunden dazu addiert werden können. Im zweiten Fall, wenn die Stundenzahl gleich 12 ist, ist sie auch im neuen Format 12.
Auch der elseTeil der übergeordneten Abfrage ist wiederum in eine ifelseAbfrage unterteilt. Er behandelt den Fall „tageszeit[1] == „AM““. Auch die untergeordnete ifSchleife gilt wieder für Stundenzahlen kleiner 12. Wenn dies zutrifft, sind die Stundenanzahlen vorher und nachher gleich und können übernommen werden. Wenn die Stundenzahl gleich 12 ist, ist sie nach der Umrechnung 0.

Abbildung 6: If-Else-Abfrage zur Konvertierung der Stundenzahl (eigene Darstellung)

Im letzten Teil des Funktionsbausteins werden aus dem Feld „Datum“ Tag, Monat und Jahr extrahiert, indem wieder der entsprechende Feldwert genommen wird:

var tag = datum[1];
var monat = datum[0];
var jahr = datum[2];

Um Datum und Zeit im neuen Format in den Datensatz zu übertragen, müssen die erstellten Variablen nun in der richtigen Reihenfolge mit den passenden Trennungszeichen übergeben werden. Diese sind hierzu in doppelte Anführungszeichen zusetzen und alle Elemente sind mit dem Plussymbol zu verbinden.

msg.payload._embedded[„AVODetailsRuesten-WSAPL-TT“][i].properties.Statuszeit = tag+„.“+monat+„.20“+jahr+„, „+std+„:“+min;

Fazit

Die hier dargestellten Möglichkeiten der Umwandlung von Daten eines JSON-Objekts mit Node-Red sind eine sichere Methode zur Bearbeitung großer Datenmengen. Sie sind, auch bei geringen Kenntnissen der Sprache JavaScript, leicht zu implementieren und Erleichtern die Auswertung und spätere Darstellung der Daten in Reportingprogrammen, wie PowerBI.

Quellen

Kristhofen, Dennis; Weber, Aleksej; Wollert, Alexander (2022): Lokales Speichern von Daten über Node Red. FHWS. Online verfügbar unter http://kabasumo.de/wordpress/iotstarter/?p=6474, zuletzt geprüft am 13.01.2022.

Bikos, Konstantin; Kher, Aparna (2021): AM und PM – Bedeutung. Online verfügbar unter https://www.timeanddate.de/uhrzeit/am-pm-bedeutung, zuletzt geprüft am 08.01.2022.

Anhang

Im Anhang befindet sich der für diesen Beitrag notwendige Node-Red Flow:

[code][{"id":"cab746e5.b59a1","type":"tab","label":"AMAN WordPress","disabled":false,"info":""},{"id":"d80e9523.b27788","type":"http request","z":"cab746e5.b59a1","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://fcfhws.forcam.university/ffauth/oauth2.0/accessToken?client_id=GRUPPE4&client_secret=2g4Wt9UP6B&grant_type=client_credentials&scope=read%20write","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":250,"y":180,"wires":[["3cd4cd6d.34cf0a"]]},{"id":"3cd4cd6d.34cf0a","type":"json","z":"cab746e5.b59a1","name":"","property":"payload","action":"","pretty":false,"x":410,"y":180,"wires":[["218434c3.fbf414"]]},{"id":"218434c3.fbf414","type":"function","z":"cab746e5.b59a1","name":"Add HTTP headers","func":"var custom = \"Bearer \";\n\n//var custom =\"\";\ncustom += msg.payload.access_token; \n\nmsg.payload ={};\nmsg.responseUrl={};\nmsg.responseCookies={};\nmsg.redirectList={};\n\nmsg.url = \"https://fcfhws.forcam.university/ffwebservices/customized/v3/AVODetailsRuesten-WS/APL-TT/?limit=5&formatted=true&timeZoneId=UTC&workplace=D2AD6CBF195446EFA953F0E87B805BCF&workplace=8551B1F1B46341CD84E77A7F04D6F809&workplace=01CAE6E397AA43CFA748114FA5EADEE3&workplace=E7ACBD4DA89142CFA6805C0C5D5DD2C3&workplace=EF666F56C10445DF995C7E2049FC898A&workplace=660A4FB9F437405AAC60CB0B0708B1C5&workplace=C0ED65DE2440417183B7D48A10164B56&workplace=9C345AE8F5DD4ADD82F0CE663DC88AE1&workplace=6A01D036A1A146FC823D0A9E87F34AB6&workplace=713F79422AC94118A96D1B9B86779659&workplace=D360B5F4437540F9B29AE6B0D27216AB&workplace=FE2C1B6646544F9CAAF5F5E02CE48FE0&workplace=AE3AC90398E34C0C873D91B3F0325EFB&workplace=9EBC639CDF8246AEA98EA06AD9742B40&workplace=37F924E9C7044B0EA1C321D5C7BAB9A4&workplace=C98188E1EC0F4D3F80899B977C226697&workplace=149938E479CA471387B44C9DF2D79EDB&workplace=A2BC410483F14B08835A79EBB4556F60&workplace=6D108A3FD51942329C76D58B34BBC594&workplace=FD424E39100F421AA0E3804461058853&workplace=082E0B19C68641EBA23EB9EFE9D8563A&workplace=00A85F6E57534844AF80C2FA2BB2D4D0&workplace=03D6F3295F194AC492C3338D2EB68D85&workplace=CD48DBFF05D9415A8E904688102C2797&workplace=B7B27DE428084E4E867B4BB52AA027D9&workplace=33A1250AA9CE46AF9EB6594D1F15B6AA&workplace=81B97C6A6250466EAF1AA5697E503C9B&workplace=2B3F0EDC00644BA4BE2AFF18691B4EDB&timeType=DAY&startDate=2021-12-01T00:00:00&endDate=2022-01-07T00:00:00&operationPhase=2\";//\"https://fcfhws.forcam.university/ffwebservices/customized/v3/AVODetailsRuesten-WS/APL-TT/?limit=100&formatted=true&timeZoneId=UTC&workplace=6D108A3FD51942329C76D58B34BBC594&timeType=DAY&startDate=2021-11-01T00:00:00&endDate=2021-11-16T00:00:00&operationPhase=2\";\nmsg.headers = {\n \"Authorization\" : custom,\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":180,"wires":[["b8bbdc43.f1bac8"]]},{"id":"b8bbdc43.f1bac8","type":"http request","z":"cab746e5.b59a1","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":770,"y":180,"wires":[["cfeaeb3c.7d4a28","7fb5599ccaa58617"]]},{"id":"e2b574c4.dc72a","type":"inject","z":"cab746e5.b59a1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{}","payloadType":"json","x":110,"y":180,"wires":[["d80e9523.b27788"]]},{"id":"98d8de8f.675168","type":"change","z":"cab746e5.b59a1","name":"Löschen unwichtiger Daten","rules":[{"t":"delete","p":"payload.pagination","pt":"msg"},{"t":"delete","p":"payload._links","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":300,"wires":[["8a44c4d9181e6df2"]]},{"id":"cfeaeb3c.7d4a28","type":"json","z":"cab746e5.b59a1","name":"","property":"payload","action":"","pretty":true,"x":130,"y":300,"wires":[["98d8de8f.675168"]]},{"id":"64be11d901350cd1","type":"comment","z":"cab746e5.b59a1","name":"Aufruf mit https://nr.vlab.fm.fhws.de/dennis.kristhofen/rest/user1/Auswertung.json","info":"","x":320,"y":60,"wires":[]},{"id":"8a44c4d9181e6df2","type":"function","z":"cab746e5.b59a1","name":"Spaltennamen auf Deutsch","func":"var i;\n\nvar n = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"].length;\n\nfor (i = 0; i < n; i++)\n{\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.BestellNr = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.orderId;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.orderId;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.VorgangsNr = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.operationId;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.operationId;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Materialbezeichnung = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.materialId;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.materialId;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.PhasenText = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.phaseText;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.phaseText;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Statustext = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.statusText;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.statusText;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Statuszeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.statusTime;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.statusTime;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Arbeitsplatzgruppe = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.workplaceGroup;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.workplaceGroup;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.ArbeitsplatzNr = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.workplaceId;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.workplaceId;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Anzahl_Stuecke = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.targetQuantity;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.targetQuantity;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Einheit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.unit;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.unit;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Startdatum_der_Produktion = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.targetStartDate;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.targetStartDate;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitanfang = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupStartTs;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupStartTs;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitende = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupEndTs;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupEndTs;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Ist_Rüstzeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupDuration;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupDuration;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Echtzeit_pro_Takt_Sek = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.realTimePerStrokeSec;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.realTimePerStrokeSec;\n\n//msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Rüstzeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.targetSetupTime;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.targetSetupTime;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Rüstzeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.tbSetupDuration;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.tbSetupDuration;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Ist_Abweichung = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupTimeDeviationAbs;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupTimeDeviationAbs;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Ist_Abweichung_Prozent = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupTimeDeviationRel;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupTimeDeviationRel;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitrate = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupRate;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.setupRate;\n\nmsg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Dauer = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.persDuration;\ndelete msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.persDuration;\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":300,"wires":[["9bfd6320f694d945"]]},{"id":"7fb5599ccaa58617","type":"debug","z":"cab746e5.b59a1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":990,"y":180,"wires":[]},{"id":"eabee32d2d005267","type":"http response","z":"cab746e5.b59a1","name":"","statusCode":"","headers":{},"x":710,"y":600,"wires":[]},{"id":"52366d967ac65269","type":"file in","z":"cab746e5.b59a1","name":"","filename":"Auswertung.json","format":"","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":550,"y":600,"wires":[["eabee32d2d005267","e19449d9af9346da"]]},{"id":"90b2a0cb6477e743","type":"http in","z":"cab746e5.b59a1","name":"","url":"/rest/user1/Auswertung.json","method":"get","upload":false,"swaggerDoc":"","x":230,"y":600,"wires":[["52366d967ac65269"]]},{"id":"e19449d9af9346da","type":"debug","z":"cab746e5.b59a1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":560,"wires":[]},{"id":"e21f13f1.30d438","type":"file","z":"cab746e5.b59a1","name":"","filename":"Auswertung.json","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":1510,"y":400,"wires":[[]]},{"id":"9bfd6320f694d945","type":"function","z":"cab746e5.b59a1","name":"Konvertierung Zeitformat 1","func":"var i;\nvar n = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"].length;\n\nfor (i = 0; i < n; i++)\n{\n\n var zeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Statuszeit;\n\n var trennung = zeit.split(',');\n \n var datum = trennung[0].split('/');\n \n var uhrzeit = trennung[1].split(':');\n\n var tageszeit = uhrzeit[1].split(' ');\n\n var min = tageszeit[0];\n \n var std;\n\n if(tageszeit[1] == \"PM\")\n {\n if(uhrzeit[0] < 12)\n { \n std = parseInt(uhrzeit[0], 10) + 12;\n }\n \n else\n {\n std = 12;\n }\n }\n else\n {\n if(uhrzeit[0] < 12)\n { \n std = uhrzeit[0];\n }\n \n else\n {\n std = 0;\n }\n \n }\n\n var tag = datum[1];\n var monat = datum[0];\n var jahr = datum[2];\n\n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Statuszeit = tag+\".\"+monat+\".20\"+jahr+\", \"+std+\":\"+min;\n}\n \n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":180,"y":400,"wires":[["512986d5412fb93e"]]},{"id":"512986d5412fb93e","type":"function","z":"cab746e5.b59a1","name":"Konvertierung Zeitformat 2","func":"var i;\nvar n = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"].length;\n\nfor (i = 0; i < n; i++)\n{\n\n var zeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Startdatum_der_Produktion;\n\n var trennung = zeit.split(',');\n\n var datum = trennung[0].split('/');\n\n var uhrzeit = trennung[1].split(':');\n\n var tageszeit = uhrzeit[1].split(' ');\n\n var min = tageszeit[0];\n \n var std;\n\n if(tageszeit[1] == \"PM\")\n {\n if(uhrzeit[0] < 12)\n { \n std = parseInt(uhrzeit[0], 10) + 12;\n }\n \n else\n {\n std = 12;\n }\n }\n else\n {\n if(uhrzeit[0] < 12)\n { \n std = uhrzeit[0];\n }\n \n else\n {\n std = 0;\n }\n \n }\n\n var tag = datum[1];\n var monat = datum[0];\n var jahr = datum[2];\n\n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Startdatum_der_Produktion = tag+\".\"+monat+\".20\"+jahr+\", \"+std+\":\"+min;\n}\n \n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":400,"wires":[["21c5dbd9c3473c62"]]},{"id":"21c5dbd9c3473c62","type":"function","z":"cab746e5.b59a1","name":"Konvertierung Zeitformat 3","func":"var i;\nvar n = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"].length;\n\nfor (i = 0; i < n; i++)\n{\n\n var zeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitanfang;\n\n var trennung = zeit.split(',');\n\n var datum = trennung[0].split('/');\n\n var uhrzeit = trennung[1].split(':');\n\n var tageszeit = uhrzeit[1].split(' ');\n\n var min = tageszeit[0];\n \n var std;\n\n if(tageszeit[1] == \"PM\")\n {\n if(uhrzeit[0] < 12)\n { \n std = parseInt(uhrzeit[0], 10) + 12;\n }\n \n else\n {\n std = 12;\n }\n }\n else\n {\n if(uhrzeit[0] < 12)\n { \n std = uhrzeit[0];\n }\n \n else\n {\n std = 0;\n }\n \n }\n\n var tag = datum[1];\n var monat = datum[0];\n var jahr = datum[2];\n\n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitanfang = tag+\".\"+monat+\".20\"+jahr+\", \"+std+\":\"+min;\n}\n \n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":400,"wires":[["4ef38b7a6e90b685"]]},{"id":"4ef38b7a6e90b685","type":"function","z":"cab746e5.b59a1","name":"Konvertierung Zeitformat 4","func":"var i;\nvar n = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"].length;\n\nfor (i = 0; i < n; i++)\n{\n\n var zeit = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitende;\n\n var trennung = zeit.split(',');\n\n var datum = trennung[0].split('/');\n\n var uhrzeit = trennung[1].split(':');\n\n var tageszeit = uhrzeit[1].split(' ');\n\n var min = tageszeit[0];\n \n var std;\n\n if(tageszeit[1] == \"PM\")\n {\n if(uhrzeit[0] < 12)\n { \n std = parseInt(uhrzeit[0], 10) + 12;\n }\n \n else\n {\n std = 12;\n }\n }\n else\n {\n if(uhrzeit[0] < 12)\n { \n std = uhrzeit[0];\n }\n \n else\n {\n std = 0;\n }\n \n }\n\n var tag = datum[1];\n var monat = datum[0];\n var jahr = datum[2];\n\n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Rüstzeitende = tag+\".\"+monat+\".20\"+jahr+\", \"+std+\":\"+min;\n}\n \n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":960,"y":400,"wires":[["afef304e83011427"]]},{"id":"afef304e83011427","type":"function","z":"cab746e5.b59a1","name":"Umrechnung Rüstzeiten in Sekunden","func":"var i;\nvar n = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"].length;\n\nfor (i = 0; i < n; i++)\n{\n\n var ist = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Ist_Rüstzeit;\n var soll = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Rüstzeit;\n var abweichung = msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Ist_Abweichung;\n \n\n var trennung = ist.split(':');\n var trennung_soll = soll.split(':');\n var trennung_abw = abweichung.split(':');\n \n var neue_ist = parseInt(trennung[2], 10) + parseInt(trennung[1], 10)*60 + parseInt(trennung[0], 10)*3600;\n var neue_soll = parseInt(trennung_soll[2], 10) + parseInt(trennung_soll[1], 10)*60 + parseInt(trennung_soll[0], 10)*3600;\n var neue_abweichung = parseInt(trennung_abw[2], 10) + parseInt(trennung_abw[1], 10)*60 + parseInt(trennung_abw[0], 10)*3600;\n \n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Ist_Rüstzeit = neue_ist;\n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Rüstzeit = neue_soll;\n msg.payload._embedded[\"AVODetailsRuesten-WSAPL-TT\"][i].properties.Soll_Ist_Abweichung = neue_abweichung;\n \n}\n \n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1250,"y":400,"wires":[["e21f13f1.30d438","a6a6f6426f677910"]]},{"id":"a6a6f6426f677910","type":"debug","z":"cab746e5.b59a1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1490,"y":460,"wires":[]},{"id":"57913f7240177795","type":"ui_spacer","z":"cab746e5.b59a1","name":"spacer","group":"dfb4a60f.d788f8","order":1,"width":1,"height":1},{"id":"dfb4a60f.d788f8","type":"ui_group","name":"Herunterladen der Datei","tab":"48418b79.0f5834","order":1,"disp":true,"width":"12","collapse":false},{"id":"48418b79.0f5834","type":"ui_tab","name":"Dashboard","icon":"dashboard","order":1}][/code]

Dennis Kristhofen

Masterstudent Wirtschaftsingenieurwesen

Alexander Wollert

Masterstudent Wirtschaftsingenieurwesen