Frage an die Modulentwickler (bzw. wo finde ich die geheime Doku)

Hallo Zusammen,

ich bin jetzt kein professioneller PHP Programmierer, habe es aber bisher immer hinbekommen, mit PHP Dokus im Internet fremde Programme nachzuvollziehen und dadurch Ideen und Lösungen für eigene Problemstellungen zu finden.

Leider stoße ich bei dem Thema Symcon Modulentwicklung hier sehr schnell an Grenzen, weil ich in der Dokumentation gerade zum Thema Datenfluss meine Fragen und Unklarheiten nicht beantwortet finde.

Wenn ich mir den Code von manchen PHP Modulen anschaue, frage ich mich oft, wie die Autoren auf diese Lösung gekommen sind. Wenn ich das Programm dann näher analysiere, komme ich immer zu dem Schluss, dass es eine geheime Dokumentation geben muss, die mir vorenthalten wird oder die ich einfach nicht finde. :confused:

Ein konkretes Beispiel. Ich habe ein ModBus Gerät, für dessen Anbindung ich ein Modul schreiben möchte.

Unter https://github.com/symcon/SymconBC/tree/master/EM24-DIN habe ich auch eine passende Vorlage gefunden, auf die ich aufbauen würde.

Mein erstes Problem stellt sich aber schon in der module.json


"parentRequirements": ["{E310B701-4AE7-458E-B618-EC13A1A6F6A8}"],
"childRequirements": [],
"implemented": ["{77B31ABB-18FA-4B91-BB63-E5B2AB5588F4}"],

Wie kann ich konkret diese beiden GUIDs ermitteln oder wo finde ich die Information für was sie stehen?

Ich brauche für das Auslesen von Modbus eine Modbus Gateway, welches in meinem Fall (Modbus TCP) mit einem Client Socket verbunden ist.
Mit IPS_GetInstance(ID ModBus Gateway) bekomme ich [ModuleID] => {A5F663AB-C400-4FE5-B207-4D67CC030564}

Die Zeile in der Create Section der module.php leuchtet mir dadurch ein.


$this->ConnectParent("{A5F663AB-C400-4FE5-B207-4D67CC030564}");

In der Funktion RequestRead() finde ich eine weitere Codezeile, wo ich keine Dokumentation finde:


$Volt = $this->SendDataToParent(json_encode(Array("DataID" => "{E310B701-4AE7-458E-B618-EC13A1A6F6A8}", "Function" => 3, "Address" => $Address , "Quantity" => 2, "Data" => "")));

Im Speziellen geht es mir hier um das JSON Datenobjekt.

„DataID“ => „{E310B701-4AE7-458E-B618-EC13A1A6F6A8}“
„Function“ => 3
„Address“ => $Address
„Quantity“ => 2
„Data“ => „“

Natürlich sehe ich aus dem Codezusammenhang, dass hier die ModBus Parameter an diese ominöse GUID {E310B701-4AE7-458E-B618-EC13A1A6F6A8} übergeben werden, wo sie dann beim ModBus Gateway landen.

aber wo kann ich konkret nachlesen oder mit welchen IPS Befehlen ermitteln, um welche Parameter es sich handelt?

Wie kann ich z.B. auch ermitteln, welches JSON Datenobjekt ich bei einem ModBus Schreibvorgang (Single Coil, Register, …) an den Parent übermittelt werden muss?

Kann mir jemand bei den rot markierten Fragen weiterhelfen und mir zeigen wo ich diese Informationen finden kann?
Wenn jemand dieses geheime Modulentwickler Handbuch hat, würde ich mich um eine Kopie sehr freuen. :wink:

schau mal hier : https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/tools/

und hier ist der Datenfluss beschrieben

https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/datenfluss/

Der Datenaustausch ist nicht für alle Module komplett dokumentiert.
Aber die GUIDs vom Datenaustausch kannst du mit IPS_GetModule — IP-Symcon :: Automatisierungssoftware ermitteln.
Michael
PS: ich habe das Thema in den passenden Bereich verschoben.

Hi,

ich kenne natürlich die Doku auf Symcon.de und habe auch die „IP-Symcon-Dokumentation-5.5.pdf“ heruntergeladen und vermutlich inzwischen auswendig gelernt.

Ich kann aber trotzdem meine in rot markierten Fragen damit nicht beantworten.

Ich bin mal Deinem Hinweis direkt gefolgt:


print_r(IPS_GetModule("{E310B701-4AE7-458E-B618-EC13A1A6F6A8}"));

Warning: Modul mit der GUID {E310B701-4AE7-458E-B618-EC13A1A6F6A8} nicht gefunden

Mir fällt da aber gerade auf, dass Du ja in Deinem Modul für die B+G Tech Stromzähler die gleichen Befehle und GUIDs verwendest.
Kannst Du da bei mir Licht ins Dunkel bringen oder hast Du diese Code Teile einfach von Paresy’s Code übernommen?

Ich würde total gerne verstehen, wie das funktioniert. :mad:

Die Erklärung hat BestEx verlinkt (der zweite Link).
Das ist in der SDK Doku erklärt (erster Link), nicht in der normalen Dokumentation. Und somit wohl auch nicht in deinem Download.
Der Befehl kann so nicht funktionieren da die GUID {E310B701-4AE7-458E-B618-EC13A1A6F6A8} keine Modul-Guid ist, sondern eine vom Datenaustausch (probiere doch einmal {A5F663AB-C400-4FE5-B207-4D67CC030564} aus :slight_smile: ).
Die GUIDs im Datenaustausch benutzt Symcon um den Inhalt des json korrekt zuordnen zu können, also was dort im json als Nutzdaten enthalten ist bzw sein muss.

Und ja, dem Datenaustausch von Modbus habe ich einfach beim Symcon Modul angeschaut.
Warum selber die GUIDs ermitteln, wenn es eine Vorlage gibt :slight_smile:
Michael

Also den zweiten Link von BestEx finde ich 1:1 auch im PDF. Wie gesagt, die Informationen darin beantwortet nicht meine Fragen aus dem ersten Post.
Der Hinweis RTFM bringt mich leider nicht weiter da ich es gelesen habe.

Aber erst mal zur GUID: Du erwähntest: {A5F663AB-C400-4FE5-B207-4D67CC030564}


print_r(IPS_GetModule("{A5F663AB-C400-4FE5-B207-4D67CC030564}"));


Array
(
    [ParentRequirements] => Array
        (
            [0] => {79827379-F36E-4ADA-8A95-5F8D1DC92FA9}
        )

    [ChildRequirements] => Array
        (
            [0] => {77B31ABB-18FA-4B91-BB63-E5B2AB5588F4}
        )

    [Implemented] => Array
        (
            [0] => {018EF6B5-AB94-40C6-AA53-46943E824ACF}
            [1] => {E310B701-4AE7-458E-B618-EC13A1A6F6A8}
        )

    [Vendor] => ModBus
    [Aliases] => Array
        (
        )

     => https://www.symcon.de/service/dokumentation/modulreferenz/modbus-rtu-tcp/
    [LibraryID] => {0945206A-47AA-4FDD-9093-99051E410E82}
    [ModuleID] => {A5F663AB-C400-4FE5-B207-4D67CC030564}
    [ModuleName] => ModBus Gateway
    [ModuleType] => 2
)

Da haben wir doch schon mal:

[ModuleName] => ModBus Gateway
[ChildRequirements] => Array
(
[0] => {77B31ABB-18FA-4B91-BB63-E5B2AB5588F4}
)

[Implemented] => Array
(
[0] => {018EF6B5-AB94-40C6-AA53-46943E824ACF}
[1] => {E310B701-4AE7-458E-B618-EC13A1A6F6A8}
)

Das sind die beiden GUIDs aus der module.json. Also ist ja schon mal meine erste Frage beantwortet.

Ok, wenn man diesen Zusammenhang kennt, findet man durch Suche nach dem Wort „ParentRequirements“ auch den Befehl IPS_GetModule in der Doku.
Es wäre aber schön, wenn dieser Zusammenhang in dem Kapitel „Datenfluss“ näher beleuchtet sein würde.
[Implemented] ist beim ModBus Gateway ein Array mit zwei IDs. Jetzt stellt sich für mich natürlich die Frage welche der zwei IDs ich in der module.json verwendet werden muss und was der Unterschied dieser zwei IDs ist.

Das sind aber nur Kleinigkeiten und ich bin schon mal wesentlich weiter als vorher. Danke dafür!

Jetzt ist immer noch die Frage nach dem JSON Format offen, welches in $this->SendDataToParent(json_encode(Array(„DataID“ =>…) verwendet wird.

Ich habe gerade gelernt, dass die GUID {E310B701-4AE7-458E-B618-EC13A1A6F6A8} zum ModBus Gateway gehört. Also müssten ja die weiteren Parameter im JSON was mit dem ModBus Gateway zu tun haben.

https://www.symcon.de/service/dokumentation/modulreferenz/modbus-rtu-tcp/

Leider steht dort nichts über die Parameter für den Datenaustausch.

Gibt es ein IPS Befehl, mit dem ich zumindest die Namen der möglichen Parameter
also:

„Function“ => 3
„Address“ => $Address
„Quantity“ => 2
„Data“ => „“

aus der anzusprechenden ModBus Gateway Instanz ermitteln kann?

Hallo,
mir ist leider nicht bekannt, welche Parameter die Splitter genau erwarten. Hier wäre es aber tatsächlich eine coole Idee, man würde das verbindlich für alle Splitter irgendwie anfordern, dass z.B. mit IPS_GetDatenfluss(„GUID“) eine brauchbare Rückmeldung für Modulentwickler rauskommt.

Noch eine Bitte an das Symcon-Team bzgl. Modulgenerator: Wäre es möglich entsprechend Kommentare insbesondere in die module.json einzubauen? Sodass hier z.B. bei „implements“ direkt steht „RX ID des Client Socket“ und in der module.php bei „ConnectParent“ (GUID des Client Socket) o.ä.? Das macht es wenigstens etwas einfacher.
Mir ist bewusst, dass JSON ohne weiteres keine Kommentare zulässt. Vielleicht könnte man einfach zwei Dateien anbieten wie module.json (lauffähig) und module.json.txt (mit Erklärungen).

Wir dokumentieren den Datenfluss bewusst aus mehreren Gründe nicht:
a) Der Aufwand ist immens, da es ne ganze Menge zu Dokumentieren gibt. (Ausnahme: MQTT ist im Forum dokumentiert)
b) Bisher gibt es nur eine Hand voll Entwickler, welche sich an offizielle Splitter hängen
c) Wir wollen uns vorbehalten ab und zu Änderungen vorzunehmen.
d) Manche Felder erhalten Informationen welche wir nur gegen NDA erhalten haben und somit nicht dokumentieren dürfen :wink:

Falls du also ganz spezielle Details brauchst ist dein bester Anlaufpunkt dafür hier im Forum. Wir geben dann unser besten dir Infos zu geben. Und wir Benachrichtigen wir genau diese Entwickler, welchen wir dann hier auch geholfen haben für diese eher sehr speziellen Fälle bei Änderungen im Datenfluss :slight_smile:

paresy

Welche Frage?
Weil wie die GUIDs ermittelt werden ist ja beantwortet.

Die GUID vom Modul hattest du ja selber schon im ersten Post rausgefunden.

Warum es zwei sind, ergibt sich bei einem Blick in die Doku.
Jedes Modul welches sowohl einen Parent als auch einen Child hat, muss einen GUID als Endpunkt haben wo es Daten empfängt.
Siehe Bild im Anhang.

Darüber gibt es keine detaillierte Dokumentation.
Nur das was in der SDK Doku zu Datenaustausch steht.
Ist aber wohl beabsichtigt, da sich z.b. bei Zwave oder HM einfach etwas ändern kann.
Michael

Edit: Oh, zu langsam :smiley:

Hallo Uwe,

um zu sehen wie die Kommunikation funktioniert, habe ich mir bei einem meiner ModBus-Projekte einen „Fake-Splitter“ erstellt. Dann siehst Du was da von den „echten“ Instanzen ankommt:
GitHub - Joey-1970/IPS2Broetje: Anbindung einer Brötje-Heizung über ModBus an IPS

Joachim

Erstmal ein frohes neues Jahr,

@paresy Ich glaube Du hast mein Anliegen nicht verstanden. :confused:

Modbus ist ja jetzt keine Raketenwissenschaft wofür es ein NDA geben könnte? :smiley:

Ich habe in der offiziellen Dokumentation keinen Hinweis gefunden, wie bei den Modulen die Anbindung an das ModBus Gateway funktioniert.
Ein paar Hinweise in der offiziellen Doku über den Datenfluss des ModBus Gateway analog wie für (Client Socket, HID, HTTP Client, …) ist ja jetzt keine große Sache.
Eine Referenz auf einen Beispielcode mit ein paar zusätzlichen Hinweisen im Code hätten mir auch gereicht.

Mein Ergebnis aus „Jugend forscht“ sieht wie folgt aus. Vielleicht kann das jemand anderes gebrauchen.
Falls ich falsche Rückschlüsse gezogen habe bitte berichtigen.


	class MODBUS extends IPSModule {

		public function Create()
		{
			//Never delete this line!
			parent::Create();

			// verbinde ein ModBus Gateway 
			$this->ConnectParent("{A5F663AB-C400-4FE5-B207-4D67CC030564}");

		}

		public function Destroy()
		{
			//Never delete this line!
			parent::Destroy();
		}

		public function ApplyChanges()
		{
			//Never delete this line!
			parent::ApplyChanges();
		}

		public function ModBusRequest()
		{
			// $DataID ist die [Implemented] GUID des ModBus Gateway. 
			// Lässt sich mit folgendem Befehl ermitteln:  IPS_GetModule("{A5F663AB-C400-4FE5-B207-4D67CC030564}")
			$DataID = "{E310B701-4AE7-458E-B618-EC13A1A6F6A8}"; 
			
			// ModBus Adresse des Gerätes. Die ModBus Geräte ID wird direkt im Modbus Gateway konfiguriert. 
			$Address = 0x0000;

			// ModBus FunctionCode zur Abfrage bzw. Senden von Parameter. (Siehe https://de.wikipedia.org/wiki/Modbus)
			$Function = 4;

			// Anzahl der Datenregister
			$Quantity = 2;

			// Datenbyte String, zum Schreiben an ModBus (Bei FunctionCodes 5,15,6,16) 
			$Data = "";

						
			$response = $this->SendDataToParent(json_encode(Array("DataID" => $DataID, "Function" => $Function, "Address" => $Address , "Quantity" => $Quantity, "Data" => $Data)));
			// $response[0] => gesendeter Function Code
			// $response[1] => Anzahl der folgenden Werte Bytes (angefordert mit $Quantity)
			// $response[2] bis  
			// $response[x] => Werte Bytes. Die Reihenfolge ist unabhängig von der Einstellung von "Swap LSW/MSW" im Modbus Gateway !! 

			$this->SendDebug("ModBus Response", $response, 1);
			
		
		}


	}

Ich klinke mich hier mal ein. Ich bin auch grade dabei ein Modul zu schreiben für eine EOS Saunasteuerung die über ModBus angebunden ist.
Leider bekomme ich es nicht hin, die Parent Instanz in der Create Funktion einzubinden. Wenn ich den Code wie ich hier erfahren habe verwende:

class EOSModBus extends IPSModule
		public function Create()
		{
			//Never delete this line!
			parent::Create();
			$this->ConnectParent('{A5F663AB-C400-4FE5-B207-4D67CC030564}');			
			
			$this->CreateVariableProfiles();

			$this->RegisterPropertyInteger("Vaporizer", 1);
			$this->RegisterPropertyInteger('Interval', 0);
			$this->RegisterTimer('UpdateTimer', 0, 'EOS_RequestRead($_IPS["TARGET"]);');
		}

bekomme ich die Meldung:

Warning:  Datenfluss ist inkompatibel in C:\ProgramData\Symcon\modules\EOSModBus\EOSModBus\module.php</b> on line 34
 (Code: -32603)
Edit:

Ich hab es grade selbst gefunden, man muss die Datei modul.json entsprechend anpassen, dann läuft es zumindest schon mal durch.

1 „Gefällt mir“

So ich bekomme meine Steuerung schon mal ausgelesen. Das geht mal super fix und mal dauert es ewig kein Ahnung warum. Ich bekomme aber fast immer am Ende der Schleife in der ich alle Daten hole einen Fehler „Zeitüberschreitung beim Warten auf Antwort“ aber die Daten werden meistens trotzdem gelesen und angezeigt. Und ab und zu auch die Meldung „ILLEGAL_DATA_ADDRESS“ was aber scheinbar nur passiert wenn ich versuche ein Register auszulesen, dass in meinem Fall zwar vorhanden ist, das aber keine Daten enthält. Dann hab ich noch den Fall, dass teilweise bei einem Lauf keine Daten geliefert werden.
Und dann kommt auch ab und an nur „UNKNOWN_ERROR“.

Das Verhalten ist irgendwie nicht vorher zu sehen.

Fragen:
Kann ich das Verhalten irgendwie analysieren?
Und wie kann ich die Meldung unterdrücken? Mit try / catch scheint es nicht zu gehen.

Am besten wäre es, wenn du mal im Debug (Der I/O Instanz oder im Splitter) schaust was für Daten gesendet werden.

Übrigens gibt es hier ein Modul, welches die ModBus Abfragen macht: SymconBC/module.php at master · symcon/SymconBC · GitHub

paresy

Das ist ein sehr schönes und anschauliches Beispiel vielen Dank dafür.

Ich hab das jetzt mal auf eine eigene Entwicklungsmaschine geschoben und auch nur noch die Steuerung am Modbus hängen und jetzt sieht es ganz gut aus. Allerdings bekomme ich immer bei der letzten Adresse die ich lese zwar den Wert aber danach den Fehler „ILLEGAL_DATA_ADDRESS“.

Jetzt befasse ich mich grade mit dem Schreiben von Werten. Das scheint auch noch nicht so einfach zu sein. Ich würde das gerne so machen, dass durch die Änderung der Variablen das Schreiben ausgelöst wird. Das passiert in RequestAction richtig? Aber wie müssen die Daten aussehen die gesendet werden? Ein einfacher String scheint es nicht zu sein wenn ich da z.B. 80 Als Wert übergebe zeigt mir das System später 48 an. Ich gehe mal davon aus, dass da was umgewandelt werden muss da das wohl Hex Werte sein müssen?.

Das funktioniert nicht. Zumindest nie über die Änderung des Wertes der Variable.
Es gibt aber die Anforderung einen Wert zu setzen, welches durch die Visualisierungen bzw. im Script durch RequestAction ausgelöst wird.
Diese Anforderungen landet dann, wie schon korrekt erkannt, im Modul in der Methode RequestAction.
Das ist die sogenannte Standardaktion einer Variable, welche du aber erst mit EnableAction auf deine Variable aktivieren musst.
Wie die Werte beim Schreiben genau sind, kann ich dir nicht sagen. Auf jeden Fall ist String (Datentyp) der Inhalt dürfte aber binary sein.
Michael

Zum Thema schreiben: Ich wandle einen Integer Wert in einen String und den übergebe ich. Kann es sein, dass da ein anderes Datenformat benötigt wird? Ich bekomme dabei keinen Fehler aber schalten tut das Gerät auch nicht.

Kann ich irgendwo den Code für das ModBus Devide finden? Da wird das doch auch gemacht und funktioniert.

Was heißt wandeln?
Nur die Zahl als Datentyp String versenden oder die Zahl in ihre binären Entsprechung?
Zeig doch einmal dein Code.
Irgendwo hatten wir das Thema im Forum schon einmal. Bin aber gerade auf den Sprung und kann somit nicht suchen.
Michael

Ich glaube es hat sich erledigt. Natürlich muss ich pack verwenden um aus dem Int den richtigen String zu bauen. Sorry für die Verwirrung!

Was ich jetzt noch brauche ist die Info, wie ich diese Action aufrufe wenn ich den Wert im Webfront ändere. Sprich wie kann ich die Standardaktion setzen wie z.B. das eigene Profil?

Ach ja und drei Fragen hab ich noch,

  • wie kann ich mein Modul aus einem Skript heraus aufrufen?
  • wie macht man es am geschicktesten diese Funktion „Status emulieren“ mit einzubauen (auch im Form) und zu verwenden?
  • wie kann ich meine Switches anwenden? Genau wie alle anderen auch?

Der neue Wert landet mit dem Ident der Variable in der Methode RequestAction von deinem Modul.
Kennst du die Test/Demo Module?

Michael