In che modo init viene a conoscenza degli eventi di potenza?


8

Ho un Pi Model B Rev 2.0 (penso) e intendo usarlo per un sistema di automazione domestica. Dato che ho un contatore di pagamento anticipato sulla mia fornitura di energia elettrica, di tanto in tanto esaurisco gli elettroni per aggirare la fornitura di corrente di casa mia!

Per evitare problemi ho ottenuto un UPS sotto forma di UPis Basic realizzato da PiModules . L'ho configurato in modo da poter eseguire il polling delle tensioni di alimentazione tramite la porta seriale del Pi (non la configurazione predefinita ma una configurazione supportata documentata nel manuale ).

Al momento utilizza un pin GPIO dedicato (pin 13 nell'intestazione, credo GPIO27) e il microcontrollore incorporato lo utilizza e uno script Python in esecuzione da rc.local per indicare a Pi shutdown -h nowquando il pin è basso - che si verifica quando si preme il pulsante "Spegnimento" dell'UPS o se l'alimentazione della batteria si esaurisce in modo critico in caso di interruzione dell'alimentazione principale. Per la cronaca lo script è:

#!/usr/bin/python

# import the  libraries to use time delays, send os commands and access GPIO pins
import PRi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM) # Set pin numbering to board numbering
GPIO.setup(27, GPIO.IN, pull_up_don=GPIO.PUD_UP) # Setup pin 27 as an input
while True: # Setup a whille loopto wait for a button press
    if(GPIO.input(27)==0): # Setup an if loop to run a shutdown command when button press sensed
        os.system("sudo shutdown -h now") # Send shutdown command to os
        break
    time.sleep(1) # Allow a sleep time of 1 second to reduce CPU usage

Questo mi sembra un po 'inelegante dato che initha la capacità integrata di gestire eventi di potenza. Vorrei ribadire che sto usando Sysvinit su Raspbian Jessie NON default systemd per tale release (per preferenze personali e motivi di familiarità).

Vorrei, inizialmente, sostituire lo script sopra con qualcosa che dice a init di farlo powerfailnowquando il pin diventa basso - e di fare un powerokwaitse successivamente ritorna alto. Alla fine ho anche voglia di interrogare la porta seriale e tenere d'occhio le risposte a @rpi, @bate @upsche ritorno le tensioni attuali su rotaia 5V del Pi, la batteria Li-Po e le Upis proprio ingresso MicroUSB rispettivamente - in modo che il Pi può dare un avviso / gestire un'interruzione di corrente (dovrebbe comportare powerfailun'azione di inizializzazione e consentire al Pi di segnalarmi lo stato di perdita di potenza, l'utente - supponendo che non me ne sia già accorto!)

Tuttavia, ho difficoltà a scoprire come i dispositivi UPS Linux segnalano initche devono essere eseguiti i comandi powerfail\ powerwait\ powerfailnow\ powerokwaitdefiniti \etc\inittab.

Qualcuno può darmi consigli, per esempio, come UPS "adulti" dicono a un kernel Linux su un normale PC che si stanno verificando eventi di "alimentazione" e come potrei riprodurre lo stesso in questo sistema su un Pi?


Grazie @ Jacobm001 per aver individuato l'assenza del tag per la parte di Python di questa domanda, nelle ultime ore ho seguito un corso intensivo nella lingua (sto facendo qualche passo avanti) ma poco tempo fa non avrei ho conosciuto il mio Asp dal mio gomito ...
SlySven

Sono anche curioso di sapere come il Pi (o init) sia a conoscenza degli eventi di potere. Spero che qualcuno risponda presto.
PNDA

Guarderei acpid e forse potresti cambiare il tuo script per reagire quando qualcosa cambia (pin alto -> basso) invece di sondare il valore ogni secondo?
Diederik de Haas,

2
@ PandaLion98 L'hardware Pi non ha eventi di potenza, quindi non c'è nulla da sapere su di loro. Se alcuni sono implementati, init ne verrebbe a conoscenza solo se viene comunicato dal kernel (a causa di un evento del driver, che nel caso del pi sarebbe presumibilmente un driver per qualche hardware aggiuntivo) o tramite un'applicazione di terra dell'utente.
riccioli d'oro

Risposte:


5

Ah ah! Alcuni paragrafi nelle pagine man per si init(8)riferiscono all'interfaccia deprezzata di scrivere un valore di una lettera in /etc/powerstatus(ora sostituito da /var/run/powerstatus) e quindi inviare initun SIGPWRsegnale; la lettera dovrebbe essere una delle seguenti:

  • Potenza in sofferenza " F ": [alimentazione principale non funzionante e] l'UPS sta fornendo energia, eseguire le voci powerwaite powerfail.
  • Power ' O ' kay: l'alimentazione [principale] è stata ripristinata, eseguire l' powerokwaitimmissione.
  • ' L ' deve energia: l'alimentazione non funziona e l'UPS ha una batteria [criticamente] scarica, eseguire l' powerfailnowimmissione.
Se il file specificato non esiste o contiene qualcosa di diverso dalle lettere F, Ooppure L, init si comporterà come se avesse letto la lettera F.

Sotto questo è l'avviso:

L'uso di SIGPWRed /etc/powerstatusè scoraggiato. Qualcuno che vuole interagire con initdovrebbe usare il /run/initctlcanale di controllo - vedi il codice sorgente del sysvinitpacchetto per ulteriori documentazione al riguardo.

Quindi, anche se questa potrebbe essere una risposta, non è la risposta, poi devo guardare il codice sorgente che è mantenuto come un progetto non GNU ospitato sul sito di hosting della GNU .


1

Immagino che l'approccio più pulito sarebbe quello di far gestire GPIO27 da un driver di dispositivo del kernel e configurarlo per ricevere un interrupt quando diventa basso. Il gestore di interrupt notificherebbe init. La pagina http://elinux.org/RPi_Low-level_peripherals afferma che Raspbian Wheezy supporta gli interrupt GPIO.

Mi scuso per la risposta di bassa qualità, non ho esaminato i driver gpio di Linux e come estenderli / migliorarli. Inoltre non ho cercato l'attuale metodo approvato per la notifica di init all'interno di un gestore di interrupt. Spero che questo post stimoli risposte migliori.


Sì, un interruzione sembrerebbe migliore del sondaggio - Diederik de Haas lo ha menzionato sopra. Il focus della mia indagine al momento è però "Il gestore di interrupt notificherebbe init ..." è quel meccanismo che è sconcertante, il powerstatsegnale file / SIGPWR sembra relativamente semplice e diretto ma sembra deprecato. Sto cercando di scoprire ora sull'uso nella vita reale del initctltubo ...
SlySven,

1

Analizzando il codice sorgente del SysV initdisponibile dal server Savannah della Free Software Foundation sono stato in grado di inviare richieste ai miei RPi initcompilando un struct init_requestcome dettagliato nel initreq.hfile di intestazione. Nello specifico ciò ha richiesto il magic, sleeptimee, per i miei scopi, la compilazione dei cmdcampi, con quest'ultimo impostato su uno dei INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWo INIT_CMD_POWEROK.

Il mio demone / programma che deve essere eseguito come utente con il permesso di scrivere sulla pipe di controllo init {originariamente su /dev/initctrlma spostato su Debian e quindi Raspbian su /run/initctrl} è stato quindi in grado di inviare quella struttura alla initquale quindi ha risposto in modo appropriato rispondendo al seguenti voci in /etc/inittab:

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

Nota: questa interfaccia - o almeno la notifica di alimentazione NON è stata adottata dal nuovo zangolato systemd- anche se, da quello che potrebbe essere considerato un po 'di programmazione di culto del carico , cerca di garantire l' initctrlesistenza del tubo. D'altra parte, questo fa esattamente quello che voglio che faccia sul mio sistema RPi!


Mentre ammiro la tua dedizione a questo tuo problema, non posso fare a meno di notare che hai impiegato molto tempo per implementare una soluzione che è funzionalmente equivalente al tuo script iniziale e non è nemmeno una prova futura.
Dmitry Grigoryev

Bene, sebbene funzionalmente equivalente al sistema iniziale, utilizza l'interfaccia fornita consigliata anziché quella deprecata. Per quanto riguarda le prove future, non sta alle persone che scrivono il sistema futuro implementare l' interfaccia nota del sistema che stanno tentando di soppiantare per garantire la retrocompatibilità ove possibile.
SlySven

Dopotutto, ottenere una notifica di interruzione dell'alimentazione principale è piuttosto importante per un sistema con un UPS, quindi un responsabile di processo / sistema mezzo decente dovrebbe essere consapevole di come il suo predecessore ha fatto le cose e cercare altri processi utilizzando tale API - un'interfaccia che esiste ma viene ignorato sembra un po 'miope ... 8- / Secondo il codice su: github.com/systemd/systemd/blob/master/src/initctl/initctl.c tutto un UPS systemdche dice che l'alimentazione principale è fallita in questo modo verrà registrato il messaggio: "Richiesta UPS / power initctl ricevuta. Questo non è implementato in systemd. Aggiorna il demone UPS!"
SlySven

"Questo non è implementato in systemd. Aggiorna il tuo demone UPS" - questo è tutto ciò che devi sapere sulla retrocompatibilità in Linux;)
Dmitry Grigoryev

L' initctlinterfaccia di van Smoorenburg Init è stata dichiarata privata e non per terze parti da uno dei (allora) manutentori del programma nel 2012. Miquel van Smoorenburg powerd, in seguito Tom Webster genpowerd, ha inizialmente utilizzato il /etc/powerstatusmeccanismo.
JdeBP
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.