Diese Anleitung beschreibt das “Schritt f�r Schritt”-Vorgehen, um eine per RFC 1006 empfangene XML-Datei nach dem Empfang in eine Datenbank zu schreiben.
Als Datenquelle wird hierbei beispielhaft der RFC 1006 Device Plugin und als Datenziel eine lokale MySQLo Datenbank verwendet.
Durch das einheitliche Interface, das CoDaBix f�r den Zugriff auf angebundene Ger�te und Datenbanken bietet, ist dieses Vorgehen jedoch auf jede Art von Daten,
die in CoDaBix definiert sind, anwendbar.
F�r die Ausf�hrung der folgenden Schritte ben�tigen Sie einen Rechner (mit Windows oder Linux Betriebssystem),
auf dem Sie die erforderlichen Rechte besitzen, um Anwendungen installieren zu k�nnen.
Desweiteren ist eine Internetverbindung notwendig, um CoDaBix und die bereitgestellte Standardkonfiguration zu laden.
Die genauen Systemanforderungen an Hardware und Betriebssystemversion finden Sie hier:
Folgende CoDaBix Plugins sind erforderlich
In diesem Schritt installieren Sie CoDaBix auf Ihrem System.
F�r diese Anleitung stellen wir Ihnen eine Grundkonfiguration f�r die Prozessdatenerfassung bereit.
auf dem Sie CoDaBix verwenden wollen.
4) Restore Backup
Enter
-Taste
Im “Nodes” Verzeichnis wird eine Folder-Node XML
erstellt.
Dort erstellen wir folgende Nodestruktur:
TriggerNode
Steuerung
Ort
tagid
Inhalte
Info
Client Channel anlegen
Unter System
→ Devices
→ RFC-1006 Device
legen Sie einen neuen Channel mit dem Namen Channel1
und folgenden Einstellungen an.
Hier verwenden wir die localhost IP-Adresse 127.0.0.1, da ein weiterer Channel angelegt wird, welcher als Testserver dient.
Dann k�nnen Sie wie folgt vorgehen, um aus dem Rfc1006-Channel1 ein XML-Telegramm zu empfangen und dieses in die Nodes zu schreiben, welche dann wiederrum in eine Datenbank geschrieben werden k�nnen:
Stellen Sie bitte im Rfc1006-Channel im Ordner “Nodes” den Value Type der “ReceiveBuffer”-Node von Blob auf “String” um
Testserver Channel anlegen
Nun legen wir noch den Channel f�r den Testserver mit dem Namen TestServer
an.
Hier werden die LocalTSAP und RemoteTSAP vertauscht um mit dem Client kommunizieren zu k�nnen.
Stellen Sie bitte im Rfc1006-Channel im Ordner “Nodes” den Value Type der “TransmitBuffer”-Node von Blob auf “String” um
RFC1006 Deserialisation
Bitte beachten Sie, dass das Script als Beispiel noch nicht alle String-Werte korrekt dekodiert (z.b. wenn mit “&” kodierte Zeichen vorkommen). Wir arbeiten jedoch aktuell an der Implementierung eines separaten XML-Plugins f�r CoDaBix, dass das Parsen von XML-Dateien �bernimmt, sodass alle Stringwerte korrekt ausgelesen werden k�nnen.
runtime.handleAsync(async function () { const rfc1006ChannelReceiveBufferPath = "/System/Devices/RFC-1006 Device/Channels/Channel1/Nodes/ReceiveBuffer"; const rfc1006ChannelReceiveBufferNode = codabix.findNode(rfc1006ChannelReceiveBufferPath); if (!rfc1006ChannelReceiveBufferNode) throw new Error(`Could not find node '${rfc1006ChannelReceiveBufferPath}'.`); const tagBaseNodePath = "/Nodes/XML"; const triggerNodePath = tagBaseNodePath + "/TriggerNode"; const triggerNode = codabix.findNode(triggerNodePath); if (!triggerNode) throw new Error(`Could not find node '${triggerNodePath}'.`); const tagNames = ["Steuerung", "Ort", "tagid", "Inhalte", "Info"]; // Find the nodes for each tag name. const tagNodes = new Map<string, codabix.Node>(); for (let tagName of tagNames) { const nodePath = tagBaseNodePath + "/" + tagName; const node = codabix.findNode(nodePath); if (!node) throw new Error(`Could not find node '${nodePath}'.`); tagNodes.set(tagName, node); } // Reset the trigger node. void codabix.writeNodeValueAsync(triggerNode, 0); // Add a value changed event listener to the Receive Buffer. rfc1006ChannelReceiveBufferNode.addValueChangedEventListener(e => { if (typeof e.newValue.value != "string") { logger.logError(`Value Type of node '${rfc1006ChannelReceiveBufferPath}' is not 'String'!`); } else { let stringValue = e.newValue.value; // Log the received XML. logger.log("Received: " + stringValue); // Find the tags. let tags = extractTagsFromXmlString(stringValue); // Now write the tags into their corresponding nodes. codabix.scheduleCallback(() => { let valuesToWrite: { node: codabix.Node, value: string | number }[] = []; tags.forEach((value, key) => valuesToWrite.push({ node: tagNodes.get(key)!, value })); // Also, write 1 to the Trigger Node. valuesToWrite.push({ node: triggerNode, value: 1 }); // Write the values. codabix.writeNodeValuesAsync(valuesToWrite); // After writing the values, switch the trigger node back to 0. codabix.writeNodeValueAsync(triggerNode, 0); }); } }); function extractTagsFromXmlString(xmlString: string): Map<string, string> { let map = new Map<string, string>(); for (let tagName of tagNames) { // Search for the start tag. let startTag = `<${tagName}>`; let endTag = `</${tagName}>`; let startTagIndex = xmlString.indexOf(startTag); if (startTagIndex >= 0) { // OK, we found the start tag. Now search for the end tag. let endTagIndex = xmlString.indexOf(endTag, startTagIndex + startTag.length); if (endTagIndex >= 0) { // OK, we now have the value. // TODO: To get the correct string value, we would need to XML-decode the string. let content = xmlString.substring(startTagIndex + startTag.length, endTagIndex); logger.log(`Found Tag '${tagName}' with value '${content}'.`); map.set(tagName, content); } else { logger.logWarning(`Could not find start tag '${startTag}'.`); } } else { logger.logWarning(`Could not find start tag '${startTag}'.`); } } return map; } }());
(Falls ein Fehler geloggt wird, dass eine Node nicht gefunden wurde, m�ssen Sie ggf. den Pfad zur Node im Script-Code anpassen.)
Nun sollten auch die Werte in den zuvor erstellen Nodes stehen:
Um nun jedes Mal wenn neue Werte geschrieben wurden, die Tags in eine Datenbank zu schreiben, k�nnen Sie z.B. unser Database-Plugin verwenden. Dazu k�nnen Sie folgende Konfiguration in der XML-Konfigurationsdatei (CoDaBix.DatabasePlugin.Settings.xml) angeben:
<?xml version="1.0" encoding="utf-8" ?> <PluginSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Channels> <Channel id="ch1" active="true"> <DbConnections> <DbConnection id="con1" type="MySQL" hostname="localhost" port="3306" username="root" password="xxxxx" database="mydatabase" table="mytable" /> </DbConnections> <Triggers> <Trigger id="t1" type="edge" node="/Nodes/XML/TriggerNode" edgeValue="1" /> </Triggers> <DataSets> <DataSet id="ds1" writeDelay="1000" writeBufSize="10"> <DbConnection id="con1" /> <Trigger id="t1" /> <Nodes root="/Nodes/XML/"> <Node path="Steuerung" column="Steuerung" /> <Node path="Ort" column="Ort" /> <Node path="tagid" column="tagid" /> <Node path="Inhalte" column="Inhalte" /> <Node path="Info" column="Info" /> </Nodes> </DataSet> </DataSets> </Channel> </Channels> </PluginSettings>
Dadurch w�rde nun immer wenn ein neues XML-Telegramm eintrifft, dieses in die Datenbank geschrieben werden.