GPIOZero

Odpovědět
meki333
Příspěvky: 3
Registrován: čtv 28. dub 2022 9:35:11

GPIOZero

Příspěvek od meki333 » čtv 28. dub 2022 10:02:08

Zdravím,
potřeboval bych od zdejších guru trošku pomoci s problémem. Mám na stole projekt na ovládání turniketu včetně počítání osob. Technicky je ovládání turniketu vyřešeno (pomocí RFID čipu). Turniket má 5 RPi 3B(2x vchod, 2x východ a "polikač karet) a je ovládán přes seplé relé. Čtečky jsou připojené přes UART (+ bižuterie okolo - převodníky UART na 485 kvuli délce, diagnostické diody, pípak...). RPi komunikují se serverem přes API, který vyhodnocuje možnost průchodu a posílá zpět na RPi informaci, zda uživatel může projít, či ne. Poté je hlídáno "rameno" turniketu, zda člověk skutečně prošel, nebo se někde "zakecal" a turniketem neprošel. S tímto problém zatím nemám.

Problém nastává trochu s logikou. Pokud na 1 RPi někdo čipne, potřebuji zablokovat načítání čipů na protější RPi (aby se lidé v turniketu nesrazili čelem :D ). Toto řeším pomocí REMOTEGPIO a pythonu pomocí knihovny GPIOZero. Na 1 RPi sepnu pin pokud je přiložen čip a druhá malina po LAN načítá stav tohoto pinu - podle stavu pinu se zařídím (je-li remotePIN(26).on zastavím threading.Thread s načítáním čipů, pokud je off, odpauznu thread). Dále pomocí PingServer hlídám dostupnost ostatních RPi, pokud neodpovídá některá z RPi, nespínám blokovací pin.

Tak sem se trochu rozepsal a teď k problému. Pokud mi vypadne LAN, tak toto mám ošetřené. Pokud ale protější RPi restartuju, tak mi nastává chyba "Broken Pipe" a nejsem schopen se z ní "nějak" vymotat. Problém je pravděpodobně v tom, že než RPi zdetekuje, že je protější RPi off-line, tak tam vlítně ještě nějaký dotaz na stav pinu a ten už není možné vyřídit a celá komunikace se rozsype.

Dá se nějak v GPIOZero uzavřít navázaná komunikace a znovu ji sestavit? Nebo Broken Pipe nějak jinak ošetřit? Pokud někomu pomůže python kód, tak mu ho klidně zašlu, ale má cca 800 řádků a sem ho asi nemá smysl dávat...

Za jakýkoliv nápad děkuji
Uživatelský avatar
PetrSmetana
Příspěvky: 310
Registrován: pon 22. črc 2019 9:06:45
Bydliště: Mnich
Dal poděkování: 28 poděkování
Dostal poděkování: 60 poděkování
Kontaktovat uživatele:

Re: GPIOZero

Příspěvek od PetrSmetana » pon 02. kvě 2022 7:15:02

Ahoj, já bych to asi centralizoval a udělal někde mqtt brokera místo použití GPIO přes síť. Podle toho co popisuješ tam budou problémy se "zaseknutými" sockety na straně GPIOZero. Pokud je to open source, tak se v tom můžeš zkusit pošťourat, ale jinak bych si od toho moc nesliboval a radši se vydal nějakou standardizovanou cestou. Pokud tam máš tolik RPi a chtěl bys tam mít navíc zajištěnou nějakou redundanci, tak bych zvážil nasazení k8s por tento účel.
Modré z nebe na počkání, zázraky do dvou dnů.
meki333
Příspěvky: 3
Registrován: čtv 28. dub 2022 9:35:11

Re: GPIOZero

Příspěvek od meki333 » úte 10. kvě 2022 12:17:05

Zdravím,
díky za pošťouchnutí, MQTT jsem zprovoznil, nastavil. Dělá přesně to, co potřebuji (na 98% :D ). Na jednom RPi mi běží Broker (pro redudanci v každém turniketu zvlášť), klienti se hlásí do adresářů, kde ukládají/načítají data a podle toho přepínají stav RFID čteček (může čipovat / čtečka odpojena). Pokud některé RPi restaruju (nebo odpojím od LAN), tak se pošle will_set a ostatní o tom vědí.

Abych byl zcela uspokojen ( :roll: ), dá se nějak vypsat, který klient poslal zprávu, nebo se odpojil? Používám client = mqtt.Client("Stanice1"), popřípadě jsem zkoušel i client = mqtt.Client(client_id = "Stanice1"), ale nějak jsem nepřišel na to, jak client_id někde vypsat...

Za nápady děkuji.
meki333
Příspěvky: 3
Registrován: čtv 28. dub 2022 9:35:11

Re: GPIOZero

Příspěvek od meki333 » úte 10. kvě 2022 16:05:47

Tak doreseno, samozrejme spatny if :). V definici on_message jsem odchytaval pouze stav "1" a else jsem nezobrazoval. Ted odchytavam stav "0" a "1" a ostatni zobrazim. Do will_set generuju nazev stanice a ten se mi krasne propise na ostatni RPi, takze vsechny vedi, ktere RPi vypadlo a muzu se podle toho zaridit. Na RPi, kde vypadne LAN, tak tento stav odchytavam na client.on_disconnect a taky se podle toho zaridim (pruchod cipem porovnavam s lokalni databazi). PERFEKTNI!!!

Diky za napad, jak toto udelat.
Odpovědět