Eu tenho um Pi Modelo B Rev 2.0 (eu acho) e pretendo usá-lo para um sistema de automação residencial. Como tenho um medidor de pré-pagamento em meu suprimento de eletricidade, ocasionalmente fico sem elétrons para contornar o fornecimento de energia elétrica da minha casa!
Para evitar problemas, obtive um no-break na forma de um UPis Basic da PiModules . Eu o configurei para que eu possa pesquisar as tensões de alimentação através da porta serial do Pi (não a configuração padrão, mas uma instalação suportada documentada no manual ).
No momento, ele usa um pino GPIO dedicado (pino 13 no cabeçalho, GPIO27, eu acredito) e o microcontrolador embutido usa isso e um script python executado em rc.local para informar ao Pi shutdown -h now
quando o pino está baixo - o que acontece quando o botão "Desligar" do no-break é pressionado ou se a alimentação da bateria ficar muito baixa no caso de falha na alimentação principal. Para o registro, o 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
Isso me parece um pouco deselegante, pois init
possui a capacidade integrada de lidar com eventos de energia. Devo reiterar que estou usando o sysVinit no Raspbian Jessie, NÃO o sistema padrão para essa versão (por preferência pessoal e por motivos de familiaridade).
Gostaria, inicialmente, de substituir o script acima por algo que diga ao init para fazer isso powerfailnow
quando o pino estiver baixo - e para fazer um powerokwait
se, posteriormente, retornar alto. Eventualmente, também quero pesquisar a porta serial e acompanhar as respostas @rpi
, @bat
e @ups
que retornam as tensões atuais no trilho de 5V do Pi, a bateria LiPo e a própria entrada microUsb da UPis, respectivamente - para que o Pi possa emitir um alerta em / lida com uma falha de energia (deve resultar em uma powerfail
ação init e deixar o Pi relatar o status de perda de energia para mim, o usuário - supondo que eu ainda não tenha notado!)
No entanto, estou tendo dificuldade em descobrir como dispositivos Linux UPS sinalizar para init
que o powerfail
\ powerwait
\ powerfailnow
\ powerokwait
comandos definidos no \etc\inittab
deve ser realizada.
Alguém pode me aconselhar, por exemplo, como o UPS "adulto" diz a um kernel Linux em um PC normal que eventos de "energia" estão acontecendo e como eu posso reproduzir o mesmo neste sistema em um Pi?
Respostas:
Ah ha! Alguns parágrafos nas páginas de manual
init(8)
referem-se à interface depreciada de escrever um valor de uma letra/etc/powerstatus
(agora substituído por/var/run/powerstatus
) e enviarinit
umSIGPWR
sinal; a carta deve ser uma das seguintes:- Energia em ' F ': a energia principal falhou e o no-break está fornecendo energia, execute as entradas
- Power ' O ' kay: a energia [principal] foi restaurada, execute a
- ' L poder ow': a energia está a falhar e a UPS tem um [criticamente] bateria fraca, executar a
Se o arquivo especificado não existir ou contiver nada além das letraspowerwait
epowerfail
.powerokwait
entrada.powerfailnow
entrada.F
,O
ouL
, init se comportará como se tivesse lido a letraF
.Abaixo deste é o aviso:
Portanto, embora isso possa ser uma resposta , não é a resposta - a seguir, preciso examinar o código-fonte que é mantido como um projeto não-GNU hospedado no site de hospedagem do GNU .
fonte
Eu acho que a abordagem mais limpa seria ter um driver de dispositivo do kernel gerenciando o GPIO27 e configurado para receber uma interrupção quando ficar baixo. O manipulador de interrupção notificaria o init. A página http://elinux.org/RPi_Low-level_peripherals diz que o Raspbian Wheezy suporta interrupções de GPIO.
Peço desculpas pela resposta de baixa qualidade, não olhei para os drivers gpio do Linux e como estendê-los / aprimorá-los. Também não procurei o método aprovado atual para notificar init de dentro de um manipulador de interrupções. Espero que este post estimule melhores respostas.
fonte
powerstat
sinal do arquivo / SIGPWR parece relativamente simples e direto, mas parece estar obsoleto. Eu estou tentando descobrir agora sobre o uso da vida real dainitctl
tubulação ...Ao pesquisar o código-fonte do SysV
init
disponível no servidor Savannah da Free Software Foundation, fui capaz de enviar solicitações aos meus RPiinit
preenchendo umstruct init_request
conforme detalhado noinitreq.h
arquivo de cabeçalho. Especificamente, esta requeria amagic
,sleeptime
e, para os meus propósitos oscmd
campos a ser preenchida, com o último conjunto de estar a um dosINIT_CMD_POWERFAIL
,INIT_CMD_POWERFAILNOW
ouINIT_CMD_POWEROK
.Meu daemon / programa que precisa ser executado como usuário com permissão para gravar no canal de controle init {originalmente no
/dev/initctrl
Debian e, portanto, Raspbian para/run/initctrl
} foi capaz de enviar a estrutura àinit
qual respondeu apropriadamente, respondendo ao seguintes entradas em/etc/inittab
:Nota: essa interface - ou pelo menos a notificação da fonte de alimentação NÃO foi adotada pelo novo fangled
systemd
-, embora pelo que possa ser considerado um pouco de programação de culto à carga, ele tente garantir a existência doinitctrl
tubo. Por outro lado, isso faz exatamente o que eu quero que ele faça no meu sistema RPi!fonte
systemd
que a energia principal falhou dessa maneira, será registrada a mensagem: "Solicitação de UPS / power initctl recebida. Isso não foi implementado no systemd. Atualize o daemon do UPS!"initctl
interface para o van van Smoorenburg init foi declarada privada e não para terceiros por um dos (então) mantenedores do programa em 2012. Miquel van Smoorenburgpowerd
, mais tarde Tom Webstergenpowerd
, originalmente usou o/etc/powerstatus
mecanismo.