Eingänge von entfernten Raspberry Pi "intelligent" Abfragen

Hallo Leute,

wie der eine oder andere schon mitbekommen hat, bin ich gerade dabei ein Modul zur Steuerung und Abfrage lokaler oder entfernter Raspberry Pi zu erstellen.
Vielen Herausforderungen sind schon - hier noch einmal des besonderen Dank an Nall Chan, Fonzo und Paresy - gemeistert.
Die Steuerung der GPIO, also als Ausgang, funktioniert schon super, lediglich wenn ich die Eingänge - möglichst ressourcenschonend - abfragen will, bereit mir noch Kopfzerbrechen…

Tririviallösung: den auf Eingang konfigurierten GPIO alle x Millisekunden aus dem Modul abfragen - also polll, poll und noch mal poll…das sollte zum einen IPS belasten, zum anderen den Netzwerkverkehr

Anderer Lösungsansatz: ein python Skript bekommt diese Aufgabe, was und wo abgefragt werden soll, bekommt das Python-Skript als Parameter, IPS bekommt nur eine Information, wenn sich eine der benannten GPIO ändert…

Andere ggf. vorhandene Möglichkeit: PIGPIO bekommt irgendwie - aus der „Ferne“ mitgeteilt etwas zu machen, wenn sich eine der benannten GPIO ändert und übermittelt das an IPS…

PIGPIO bietet dazu ggf. Möglichkeiten, die ich bisher übersehen habe (Watchdog, Notification, Scrips…)?

Wichtig: die Umsetzung muss aus dem Modul selbst erfolgen und auch auf entfernte Raspberry Pi anwendbar sein.

Wäre schön, wenn mich hier jemand ggf. mit tieferer PIGPIO-Erfahrung einen Tipp geben könnte…

Joachim

Bei mir läuft es in Python mit Interrupts. Bietet Dir das PIGPIO nicht an?

…um es im Modul zu verwenden - ohne das manuell noch etwas auf einem entfernten Raspbery Pi installiert werden muss - muss es auf dem Raspberry Pi laufen, auf dem auch IPS läuft. Ich würde daher gerne auf Python-Skripte verzichten, damit das Modul auch auf einem Windows-IPS-Server lauffähig zu bekommen.

Zur Steuerung verwende ich das PIGPIO-Socket-Interface, das läuft so weit echt performant.
Von daher würde ich einen Weg bevorzugen, der diesen Weg nutzt, IPS oder das Netzwerk jedoch nicht übermäßig belastet…

Joachim

…fantasiere ich noch mal ein bißchen weiter…

Wie könnte ich die zyklische Abfrage vom IPS aus mit einer Zeit <1 Sekunde „legal“ realisieren?

  • Eine While-Schleide würde nach 30 Sekunden ins time out laufen…
  • Mit den zyklischen Ereignissen könnte das Skript im Minimum nur alle Sekunde einmal laufen - zu lang wenn der Druck eines Tasters erfasst werden sollte…

Hat jemandschon mal so etwas realisiert?

Joachim

Hallo Joachim,

mit ‚tieferen‘ PIGPIO-Erfahrungen kann ich zwar nicht dienen, aber schau Dir mal folgende PIGPIO-Socket-Befehle an:

NB (Notify Open) - cmd: 19
NOIB - cmd: 99

Ein Aufruf von IPS-Seite könnte so aussehen:

PIGPIO_SetMode($InstanceID, 15, 0); // 15 --> GPIO, 0 --> Eingang
PIGPIO_NotifyOpen($InstanceID, 01, 0x8000); // 01 --> Handle, 0x8000 --> Bitmaske der GPIO-Eingänge
PIGPIO_NOIB($InstanceID);

Hallo Joachim,

zu kompliziert gedacht - PIGPIOD macht die ganze Arbeit!

Mit der obengenannten Befehlsfolge schickt das Socket-Interface von PIGPIO bei jeder Zustandsänderung eines Eingangs einen Datensatz. Zusätzlich wird alle 60 Sekunden der aktuelle Zustand der Bank1 (GPIO 0 … 31) geschickt.

…das ist ja eine ganze heiße Spur!:slight_smile:

Hast Du das im IPS ausprobiert?

Wie hast Du das gemacht? Wie hast Du die Bitmaske generiert?

Joachim

Das hängt davon ab was auf Rasberry PI Seite installiert sein soll. Wenn nicht ständig Polling getrieben werden soll wäre eine Möglichkeit Websockets zu nutzten dann bekommst Du nur dann eine Antwort wenn sich was ändert.

Hier wurde z.B. Mal beschrieben wie das über Websockets gelöst wurde.
Raspberry PI mit Sensoren am I2C Bus

Da IPS leider noch kein Websocket unterstützt müsstest Du das selber bauen.

Mit Rachet gibt es eine PHP Library für Websockets. Vielleicht kannst Du auch die nutzen um Websockets mit IPS zu nutzen
Ratchet - PHP WebSockets

Auf IPS-Seite ein Client-Socket.

Testweise ‚handgestrickte‘ Befehlsfolgen per CSCK_SendText verschickt.

Die Grundidee kam beim Mitschneiden des TCP/IP-Protokolls 2er Raspis.
Auf dem einen lief ein Pythonprogramm,das den zweiten Raspi per PIGPIO steuert und dessen Eingänge per callback überwacht.

Bitmaske - heisses Thema. Da muss man mit Bitweise „AND“ arbeiten. Das Problem hierbei sind die 32 Bitwerte die der PIGPIOD schickt. PHP hat ein Problem mit der Darstellung / Verarbeitung von 32 Bit unsigned Integerwerten. Das Verhalten ist auch abhängig vom verwendeten Prozessor / Betriebssystem. Im Moment suche ich eine unkomplizierte Lösung hierfür.

@Joachim
Das war das was ich mit Events empfangen meinte.
Jetzt kommst du um den Datenaustausch mit dem ClientSocket doch nicht herum :wink:
@EHB
Was spricht dagegen anstatt mit uint Long mit 4x Byte zu arbeiten?
Die Reihenfolge der Bits ist ja auf dem Socken in IPS immer gleich, egal welches System.
Wenn du es also nicht in eine so große Zahl konvertierst, solltest du auch kein Problem bekommen.
Oder mit Bit Verschiebung arbeiten. So konvertiert ich immer meine RGB Werte von 24 Bit auf 3x Byte.
Michael

Hallo Ernst,

magst Du mir Deinen Skript zeigen?

Bekomme keine Notification…:confused:

Joachim

Ja, Michael, dass habe ich bei dem Weg auch schon „befürchtet“…:smiley:

Aber wenn mir dasgelingt, dann wäre das doch eine super Sache!

Joachim

Hallo Joachim,

nur Geduld…

Das komplette Script (Versuch eine IPS-Moduls) sieht (noch) zu Wüst aus, und läuft nur teilweise.

Hier die wichtigsten Teile:

Befehlsfolge in IPS:

PIGPIO_SetMode($InstanceID, 15, 0);
PIGPIO_NotifyOpen($InstanceID, 01, 0x8000);
PIGPIO_NOIB($InstanceID);

// **** PIGPIO_SetMode($id, $gpio, $mode); ****
		// gpio = 0 ... 31
		// OUTPUT = 0, INPUT = 1, ALT 1 = 5, ALT 2 = 6, ALT 3 = 7, ALT 4 = 3, ALT 5 = 2
		public function SetMode($gpio, $mode)
		{
			IPS_LogMessage("SetMode Parameter : ",$gpio." , ".$mode);				
			$cmd = 0;																					
			$this->SendData(array($cmd, $gpio, $mode, 0));
		}
// **** PIGPIO_NotifyOpen($id, $handle, $bits); ****	
		public function NotifyOpen($handle, $bits)
		{
			IPS_LogMessage("NotifyOpen gestartet : ",$handle." , ".$bits);				
			$cmd = 19;																					
			$this->SendData(array($cmd, $handle, $bits, 0));
		}
// **** PIGPIO_NOIB($id); ****
		public function NOIB()
		{		
			IPS_LogMessage("NOIB : ", "");				
			$cmd = 99;																					
			$this->SendData(array($cmd, 0, 0, 0));
		}
// **** PIGPIO_SendData($id, $Parameter); ****
		public function SendData($cmd, $p1, $p2, $p3)
		{
			// --> ToDo = Prüfen ob Socketverbindung aufgebaut und frei --> wenn ja Lock setzen
			
			// Datensatz zusammensetzen / formatieren
			$SendText = pack("IIII", $cmd, $p1, $p2, $p3);									
			// an Cliensocket zum Senden weiterleiten
			$res = $this->SendDataToParent(json_encode(Array("DataID" => "{79827379-F36E-4ADA-8A95-5F8D1DC92FA9}", "Buffer" => utf8_encode($SendText)))); 
			IPS_Sleep(30);																	// 30 msec warten
			
			// --> ToDo = Socket wieder freigeben -> Wartezeit einfügen ohne IPS_Sleep !!!
		}

Debug des IPS-Client Sockets:
Screenshot.jpg

Noch viel Spaß beim Testen!

Hallo Ernst,

nur noch mal zu meinem Verständnis:
Müsste es nicht so zum Start sein
Cmd 18 NO - Rückgabe ist ein freier Handle
Cmd 19 NB - Start der Notifikation mit 19, Handle (aus der ersten Kommunikation) und der Bits (der Wert -1 soll die Notifikation für alle einrichten?)
Cmd 99 NOIB - ist mir unklar was der macht

Joachim

Guter Einwand!

Die Befehlsreihen sollte sein:

NOIB (cmd 99) schicken --> Antwort von PiGPIO : Handle in den letzten 4 Byte
NB (cmd 19) Parameter : handle, Bitmask schicken

Ab diesem Zeitpunkt wird der entsprechende GPIO Eingang überwacht

Schau Dir mal die Datei pigpio.py (Quelltext von Joan2937) an:

ab Zeile 877 class _callback_thread(…

Zeile 879 : def init(…

Zeile 891 : self.handle = _pigpio_command(self.sl, _PI_CMD_NOIB, 0, 0)

Zeile 901 : def append(…

Zeile 905 : _pigpio_command(self.control, _PI_CMD_NB, self.handle, self.monitor)

…aus der Dokumentation ist das m.E. So nicht erkennbar (der Handle steht als Rückgabewert nur bei cmd 18) aber sei es drum - wenn es so bei Dir funktioniert, werde ich es auch so machen![emoji2]

Hast Du das mal mit -1 als Bitmask probiert?

(Bin im Urlaub und bekomme ganz doll auf den Deckel wenn ich da rumspiele - externer Zugriff ist aber für alle Fälle schon eingerichtet…[emoji12])

Joachim

Bei Bitmask -1 wird „FF FF FF FF“ rausgeschickt und von PIGPIOD bestätigt --> GPIO 0 … 31 überwachen ?

(Ich krieg zwar keine auf’n Deckel, aber mach jetzt für heute Schluß. Muss morgen früh raus.)

Schönen Urlaub noch - und lass Dich nicht erwichen! :wink:

…so, bekomme jetzt mit der Bitmaske -1 jede Sekunde Daten - auch wenn ich noch nicht so genau weiß wie ich diese jetzt auswerrte - muss mir das mit der Bitmaske noch mal genauer anschauen.:confused:

Erst einmal vielen Dank - das ist der richtige Schritt gewesen!:slight_smile:

Joachim

…ich habe aktuell an den GPIO 4, 24, 25 Taster. Daraushabe ich eine Bitmaske von 3000010 errechnet…

Jetzt kommen regelmäßig alle Minute folgende Daten (ohne dasTaster betätigt werden):
00 00 40 00 B5 FC 1A 9F 4F C1 01 00
01 00 40 00 4F 84 AE A2 4F C1 01 00
02 00 40 00 D7 0E 42 A6 4F C1 01 00
03 00 40 00 F4 95 D5 A9 4F C1 01 00

Das erste scheint so etwas wie ein Zähler zu sein, die letzten Daten bleiben unverändert. Was beschreibendieDaten dazwischen?:confused:

Joachim

Anhand Deiner Meldung:
03 00 40 00 F4 95 D5 A9 4F C1 01 00

00 03 --> Laufende Nummer / Satznummer
00 40 --> ? ? ? ?
A9 D5 95 F4 --> „tick“ (Zeitstempel)
00 01 C1 4F --> Bitmaske --> zu diesem Zeitpunkt sind GPIO 0, 1, 2, 3, 6, 8, 14, 15, 17 Aktiv (HIGH)

Die Bytefolge der Daten im PIGPIO-Socketprotokoll sind gemäß „Little-Endian“ angeordnet.