Eingänge von entfernten Raspberry Pi "intelligent" Abfragen

Hi Joachim,

meines Erachtens bedarf es für Taster und dergleichen Events im Millisekundenbereich.

Ich habe hierfür diverse PIs im Betrieb und übertrage die Daten untereinander ebenfalls über JSON. Ein Tastendruck an einem PI löst an einem anderen PI das Schalten des Relais aus. Eine Verzögerung ist nicht feststellbar (Hardware: PI2).

Etwas vereinfacht habe ich dies hier dargestellt: IP-Symcon auf Raspberry mit Nutzung der GPIOs

Ciao

Herbertf

Aber genau das ganze installieren von diversen Tools oder eines Scriptes wollte Joachim ja nicht haben.
Sondern nur PIGPIO installieren und fertig.

Hat sich ja auch erledigt mit der zyklischen Abfrage, Weil der Dienst von sich aus Event versenden kann.
Michael

Hallo Ernst,

mir ist immer noch unklar wie Du das vorzugebene Bitmuster errechnest. Nach der Anleitung

bits: 32 bit number
A mask used to select GPIO to be operated on. If bit n is set then GPIO n is selected. A convenient way of setting bit n is to bit or in the value (1<<n).

To select GPIO 1, 7, 23

bits = (1<<1) | (1<<7) | (1<<23) 

habe ich folgendes Skript geschrieben:

$a = 0;
$b = 4;
$c = 24;
$d = 25;

$z = (1<<$b)|(1<<$c)|(1<<$d);

echo ($z);

und komme dezimal auf
50331664
Das habe ich in

$this->ClientSocket(pack("LLLL", 19, $response[4], 50331664, 0));

eingesetzt.

Ist der Ansatz falsch?

Joachim

Hallo Joachim,

passt wenn:
$this->ClientSocket(… --> Deine SendeFunktion ist
$response[4] --> Der zugehörige Handle ist

Hab Deine Werte bei mir testweise eingesetzt - sieht gut aus.

Hallo Ernst,

wie entpackst Du denn die Daten?
PHP unpack? Aber welcher Format String?

Joachim

Hier die aktuelle Variante --> läuft Dank Michaels Tip :slight_smile:

"Normaler " 16 Byte Datensatz :
$Array = unpack(„v2cmd/v2p1/v2p2/v2p3“, $Data);

  • 2 * 2 Byte --> cmd
  • 2 * 2 Byte --> p1
  • 2 * 2 Byte --> p2
  • 2 * 2 Byte --> p3

…die „normalen“ Antworten klappen mit

$response = unpack("L*", $Message);

Bei den regelmäßigen Sendungen (Notification) kommen da auch teilweise negative Werte…:confused:

Joachim

Negative Werte ?
Bist Du sicher ?

Wie oben bereits erwähnt hat PHP und unpack Probleme mit 32Bit-Zahlen!
Ich hab deshalb die 32Bitwerte in jeweils 2 16Bitwerte aufgetrennt.

Hallo Ernst,

vielleicht ist diese regelmäßige Sendung doch etwas anderes als wir vermuten…

Die Dokumentation dazu ist ja eher dürftig - ich habe jedenfalls nichts aussagekräftiges dazu gefunden…

Wenn das der aktuelle Status der GPIO sein sollte, dann sollte es sich

  • in den letzten Stellen nicht unterschienen vom BankRead (das Ergebnis ist einfach nachvollziehbar)
  • eine der GPIO Änderung sichtbar sein

Beides konnte ich nicht feststellen!

Leider konnte ich jetzt nicht prüfen was passiert, wenn jemand auf die Taster drückt…

Joachim

Hallo Ernst,

habe jetzt doch noch das hier gefunden:

The notification sends state changes for each GPIO whose corresponding bit in bits is set.

Each notification occupies 12 bytes in the fifo and has the following structure.

typedef struct
{
uint16_t seqno;
uint16_t flags;
uint32_t tick;
uint32_t level;
} gpioReport_t;

seqno: starts at 0 each time the handle is opened and then increments by one for each report.

flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE. If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags indicate a GPIO which has had a watchdog timeout; if bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive signal on the pipe/socket and is sent once a minute in the absence of other notification activity.

tick: the number of microseconds since system boot. It wraps around after 1h12m.

level: indicates the level of each GPIO. If bit 1<<x is set then GPIO x is high.

Das sollte weiterhelfen…

Habe jetzt aber mein IPS wohl so weit „abgeschossen“, das ich es aus der Ferne nicht wieder in Gange bekomme…:mad:

Joachim

Nachtrag: Ich werde es, wenn mein IPS wieder läuft, mal so für die Statusmeldungen probieren:
$response = unpack(„SSL*“, $Message);
Ich entpacke es an andere Stelle auch mit „L“, wenn Little Endian stimmt (wo hast Du die Information her?) wäre es:
$response = unpack(„vvV*“, $Message);

Meine Datentelegramme Richtung PIGPIO packe ich mit
pack(„LLLL“, $Message); (läuft!)
die Antworten darauf entpacke ich mit
$response = unpack(„L*“, $Message); (läuft!)

Hallo Joachim,

die Info betreffs dem Datenfeld „flags“ finde ich sehr interessant!
Wo hast Du das gefunden?

Für die pack-Funktion verwende ich die gleichen Format-Parameter.

Bei der unpack-Funktion verwende ich „v“ um in 16-Bitwerte zu wandeln.

Woher die Info betreffs „Little-Endian“ stammt, kann ich im Moment nicht sagen.
Schau Dir mal die Datensätze vom pigpiod an --> speziell den Bitwert. Hier kann man sehen, dass die Reihenfolge „Rückwärts“ ist.

Viel Glück bei der Reanimation Deines IPS!:wink:

…die Informationen habe ich von der PIGPIO-Website - aber erst nachdem ich den Entwickler angeschrieben habe…[emoji6]
Vorher hatte auch ich verzweifelt danach gesucht.

Bitwerte sind m.E. immer von rechts nach links zu lesen. Hier hat das außerdem den Vorteil, das 2^GPIO-Pin dann das richtigen Bit setzen - oder auch auslesen kann.

Da ich jetzt aktuell nicht „am lebenden Objekt“ testen kann, bin ich um so mehr an Deinen Ergebnissen/Erfolgen interessiert…[emoji6]

Bin nun schon so weit, dass ich dank Portweiterleitung den Pi neu starten konnte (mit einer iPhoneApp) - leider ohne Erfolg…[emoji17]

Will morgen mal sehen ob ich eine Putty-Verbindung aufbauen kann…

Joachim

Hallo Ernst,

da mein Test-IPS noch nicht wieder läuft:
Gibt es bei Dir neue interessante Fortschritte?

Joachim

Hallo Joachim,

leider Nein - hab da noch 1 … 2 andere „Baustellen“, die mit IPS nichts zu tun haben.
Bin in den letzten Tagen nicht weitergekommen --> Mal schaun was am Wochenende geht!

Hallo Ernst,

hier mal der aktuelle Stand:
Erfolg: Wenn die Taster gedrückt werden erscheint sofort eine Meldung im Client Socket!!:slight_smile:
(Auswertung der empfangenen Daten Zeichenlänge 12 über:

$response = unpack("S*", $Message);

)

Herausforderungen:
Entprellen: Die fehlenden Entprellung der Taster macht sich spontan in einem „Feuerwerk“ an Meldungen bemerkbar
74 08 00 00 EE 11 18 43 5F C1 01 01 75 08 00 00 F3 11 18 43 4F C1 01 01 76 08 00 00 FD 11 18 43 4F C1 01 00 77 08 00 00 3E 12 18 43 5F C1 01 01 78 08 00 00 43 12 18 43 4F C1 01 01 79 08 00 00 52 12 18 43 4F C1 01 00 7A 08 00 00 A7 12 18 43 4F C1 01 01 7B 08 00 00 B1 12 18 43 4F C1 01 00 7C 08 00 00 06 13 18 43 5F C1 01 01 7D 08 00 00 0B 13 18 43 4F C1 01 01 7E 08 00 00 15 13 18 43 4F C1 01 00 7F 08 00 00 1F 13 18 43 4F C1 01 01 80 08 00 00 29 13 18 43 4F C1 01 00 81 08 00 00 3E 13 18 43 4F C1 01 01 82 08 00 00 4D 13 18 43 4F C1 01 00 83 08 00 00 52 13 18 43 4F C1 01 01 84 08 00 00 BA 13 18 43 4F C1 01 00 85 08 00 00 2C 15 18 43 4F C1 01 01 86 08 00 00 45 15 18 43 4F C1 01 00 87 08 00 00 4A 15 18 43 4F C1 01 01

(Markierungen von mir zur besseren Erkennbarkeit)
Hier muss man sehen wie man damit umgeht. Eine Softwarelösung wäre wahrscheinlich der universellere Weg, da die meisten Bauanleitungen für Taster am Raspberry Pi keine Entprellung vorsehen…

Hier könnte ich mir vorstellen, dass ich bei empfangen Daten > 16 Zeichen nur die ersten 12 auswerte…

Ansonsten scheint diese Lösung eine funktionierende Erweiterung von IPS zu werden.:wink:

Muss mich aber jetzt noch ein bißchen mit der Mathematik auseinandersetzen…

Joachim

Hallo Joachim,

schau Dir mal folgende PIGPIO-Befehle an:

  • FG u stdy Set a glitch filter on a GPIO
  • FN u stdy actv Set a noise filter on a GPIO

Hallo Ernst,

der Tipp war Gold wert!

Habe jetzt in relativ kurzer Zeit eine neue „Input-Instanz“ erstellt - im Verhältnis zu den vorherigen in Spitzen-Zeit…[emoji6]

Bei den angeschlossen Tastern bekommt man mit 120ms Glitch-Zeit ein sehr stabiles Ergebnis…

Woran ich jetzt „bastel“ ist immer noch das empfangene Telegramm korrekt zu dekodieren…

Aber das wird schon, inzwischen ist ersichtlich, dass das Modul die zugedachte Aufgabe auch erfüllen wird![emoji2]

Im Telegrammauszug oben wechselt bei GPIO 4 der drittletzte Wert immer zwischen 4F und 5F.
Muss jetzt mal sehen, wie ich das programmtechnisch löse. Unpack übrigens hier mit „S*“…

Joachim

…dieses „unpack“ macht mich wahnsinnig!
Im Debug des Client Socket wechseln die letzten Bits immer schon von 5F C1 01 01 - wenn das gedrückt - auf 4F C1 01 01 wenn der Taster nicht gedrückt wird. Das ist nachvollziehbar…

Beim unpack, egal ob mit S*, L* oder v* kommen aber irgendwie immer wieder andere Werte!:confused:

Bei den 16 Zeichen kann man es sauber mit L* dekodieren, aber diese 12 Zeichen stellen mic echt vor Herausforderungen!

Bist Du da schon weiter?

Joachim

Schneid doch nur die Bytes raus, welche du brauchst.
Zähler, Timestamp etc brauchst du ja nicht für die Berechnung der Zustände.
Du kannst auf einzelne Zeichen eines String einfach wie auf ein Array zugreifen.
Mit ord dann in das ‚Zeichen‘ in dessen Byte konvertieren.

ord($Data[10]);

Oder bei größeren Werten dann nur Teile an unpack übergeben.
Und dann die Bits einzeln auswerten.

Keine Ahnung wie jetzt die Daten ‚wirklich‘ aussehen aber hier mal ein Beispiel wie man es machen könnte.
Im Array könnte sogar hier den Ident für die IPS-Variable stehen :wink:


	//Beispieldaten Byte 1-3 = 'Müll' 4 & 5 Nutzdaten
	$IOSample = chr(0x12).chr(0x13).chr(0x14).chr(bindec("00001001")).chr(bindec("10000011"));

	// so ?
	$GPIOs = array('IO_12','IO_11','IO_10','IO_09','IO_08','IO_07','IO_06','IO_05','IO_04','IO_03','IO_02','IO_01');
	// oder so ?
	$GPIOs = array('IO_01','IO_02','IO_03','IO_04','IO_05','IO_06','IO_07','IO_08','IO_09','IO_10','IO_11','IO_12');

	// Alle verarbeiten:
	$PinValue = unpack("n", substr($IOSample, 3, 2))[1];
	foreach ($GPIOs as $Index => $Name)
	{
		$Bit = pow(2, $Index);
		if ($PinValue & $Bit) 
			echo $Name." is true".PHP_EOL;
		else
			echo $Name." is false".PHP_EOL;
	}

	//Gezielt ein Bit
	$PinValue = unpack("n", substr($IOSample, 3, 2))[1];
	$Bit = pow(2, 7 /* 8. Bit*/);
	if ($PinValue & $Bit) 
		echo "8. Bit true".PHP_EOL;
	else
		echo "8.Bit false".PHP_EOL;


Ich hatte auch irgendwo mal ein Beispiel wo ich es mit verschieben der Quell-Bits umgesetzt hatte.
Und dann immer logisch mit 1 und-verknüpft um zu prüfen ob das Bit gesetzt ist.

Ist aber Grundzätzlich egal wie man es umsetzt…weil wir wollen ja wohl keinen Performance-Preis gewinnen :wink:

Und du dir zuerst gedanken machen solltest, welche Instanz welche Aufgabe übernimmt.
Wenn du jetzt einen Splitter hast, braucht er die Nutzdaten komplett zu zerlegen und feuert dann für jedes Bit der GPIOs ein ForwardData zu deinen Device-Instanzen ?
Oder wirfst du das ganze oder Teile vom Datentelegramm einfach weiter und jede Device-Instanz prüft ob ihr Bit gesetzt ist ?!

Michael

Hallo Michael,

alle Versuche - auch mit Teilen des Ganzen schlugen leider fehl. Dann erinnerte ich mich daran, dass bei der kurzen Datensendung plötzlich ein utf8_decode notwendig wurde um überhaupt korrekt die Länge zu bestimmen. Warum kann ich jetzt nicht mit Sicherheit sagen, aber jetzt habe ich auch die zu entpackende Message so decodiert und siehe da: Das Ergebnis entspricht dem des Bankread!

So soll es nun weitergehen:
Im Splitter werden nun die genutzten Input-GPIO herausgefiltert und der Status an die untergeordneten Input-Instanzen weitergeleitet. Stimmt der Pin mit dem in der Instanz überein, wird dort der Status aktualisiert…

Mühsam ernährt sich das Eichhörnchen ![emoji6]

Aber: Es geht weiter![emoji2]

Joachim