#!/usr/bin/env python # # bmcd - BMC Daemon program # # This program works as a background daemon for the RPi BMC. It provides # functionality to interface with the GPIOs in an asynchronous way via two # pipes, one read-only and one write-only from the outside perspective. The read # pipe provides the current system power status while the write pipe listens # for commands. # # Part of the RPiBMC project - (c)2017 Joshua Boniface # This software is licenced under the terms of the GNU GPL version 3. For # details please see LICENSE # import socket, os, time, struct from threading import Thread, Event from daemon import runner import RPi.GPIO as GPIO # These are GPIOs 1-4 gpio_rsw = 17 gpio_psw = 18 gpio_state = 27 gpio_pled = 22 # The pipes and PID file (sorry I manage this here...) bmcd_state = '/run/bmcd/bmcd.state' bmcd_cmd = '/run/bmcd/bmcd.cmd' pidfile = '/run/bmcd/bmcd.pid' # Event for LED flash (i.e. locator) is_pled_flashing = Event() # Turn the power LED on def powerled_on(): GPIO.output(gpio_pled, 1) # Turn the power LED off def powerled_off(): GPIO.output(gpio_pled, 0) # Flash the power LED def powerled_flash(is_pled_flashing): while is_pled_flashing.isSet(): GPIO.output(gpio_pled, 1) time.sleep(1) GPIO.output(gpio_pled, 0) time.sleep(1) is_pled_flashing.clear() return # Press the power button def powersw_press(): GPIO.output(gpio_psw, 1) time.sleep(0.5) GPIO.output(gpio_psw, 0) # Hold the power button (8 seconds) def powersw_hold(): GPIO.output(gpio_psw, 1) time.sleep(8) GPIO.output(gpio_psw, 0) # Press the reset button def resetsw_press(): GPIO.output(gpio_rsw, 1) time.sleep(0.5) GPIO.output(gpio_rsw, 0) # Turn on the locator (subthread) def locate_on(): is_pled_flashing.set() t = Thread(name='non-block', target=powerled_flash, args=(is_pled_flashing,)) t.start() # Turn off the locator def locate_off(): is_pled_flashing.clear() # Main loop to read a command from the pipe def readcmd(): fcmd = open(bmcd_cmd, 'r+', 0) while True: line = fcmd.readline() try: globals()[line.rstrip()]() except: pass # Main loop to write power state to the pipe def writestate(is_pled_flashing): while True: state_now = GPIO.input(gpio_state) fstate = open(bmcd_state, 'w+', 0) fstate.write(str(state_now) + '\n') fstate.close() if not is_pled_flashing.isSet(): if state_now == 1: powerled_on() else: powerled_off() time.sleep(1) # Main app definiton - sets default states and runs main loop class App(): def __init__(self): self.stdin_path = '/dev/null' self.stdout_path = '/var/log/bmcd.log' self.stderr_path = '/var/log/bmcd.log' self.pidfile_path = pidfile self.pidfile_timeout = 5 def run(self): if not os.path.exists(bmcd_state): os.mkfifo(bmcd_state) if not os.path.exists(bmcd_cmd): os.mkfifo(bmcd_cmd) GPIO.setmode(GPIO.BCM) GPIO.setup(gpio_state, GPIO.IN) GPIO.setup(gpio_psw, GPIO.OUT) GPIO.setup(gpio_rsw, GPIO.OUT) GPIO.setup(gpio_pled, GPIO.OUT) t1 = Thread(target=readcmd) t2 = Thread(target=writestate, args=(is_pled_flashing,)) t1.setDaemon(True) t2.setDaemon(True) t1.start() t2.start() while True: pass # App definition - start it up app = App() daemon_runner = runner.DaemonRunner(app) daemon_runner.do_action()