First off, I'm very new to python. I have a raspberry pi connected via lan to a few nodes. I want the pi to be the power interface for the nodes. When a button is pressed, magic packets get sent to the nodes to wake them up. Once the nodes have been powered up, the same momentary switch will be able to power off the nodes, by ssh-ing into each and executing the "poweroff" command. While the machines are coming up, and while the machines are powering off, an LED should be blinking.
My attempt so far has most of the functionality I described, but the LED blinking is spotty, and I'm noticing that some of my threads are being redundantly executed.
My Question is, how do I get the led blinking to more accurately represent the state change of the machines.
Here is the script:
#!/usr/bin/python
import RPi.GPIO as GPIO
import threading
import time
import os
from subprocess import call
nodes = [
{
"name": "node-1",
"mac": "80:EE:73:AE:AA:7C",
"ip": "10.15.1.254",
},
#more nodes...
]
#function to blink the leds
def blink(pin,number):
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
count =0
while count < number:
GPIO.output(pin,GPIO.HIGH)
time.sleep(.5)
GPIO.output(pin,GPIO.LOW)
time.sleep(.5)
count +=1
return
except Exception as inst:
print "error: could not blink"
#function to turn LED on or off based on power state
def led(pin, state):
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
if state ==1:
GPIO.output(pin, GPIO.HIGH)
else:
GPIO.output(pin, GPIO.LOW)
except:
print "error: could not turn on LED"
#function to wake up a node
def wake(node, mac):
try:
print "waking" +node
call(["wakeonlan", mac])
except Exception as inst:
print "error: could not wake " + node
#function to power off nodes
def shutdown(node, ip):
try:
print "shutting down " +node
call(["ssh", "-o", "StrictHostKeyChecking=no", "root@"+ip, "poweroff"])
except Exception as inst:
print "error: could not shutdown " + node
#function to check the state of the nodes (if node can be pinged, it is up)
def checkstate(node,ip):
try:
response = os.system("ping -i 0.1 -c 1 -w2 " + ip + " > /dev/null 2>&1")
if response == 0:
state =1
else:
state =0
return state
except:
print "error could not ping"
#function checks if all node states are the same
def checksame(list):
try:
list = iter(list)
first = next(list)
return all(first == rest for rest in list)
except StopIteration:
return list[0]
def main():
while True:
state = []
for node in nodes:
node_name = node.get('name', '')
node_ip = node.get('ip', '')
state.append(checkstate(node_name,node_ip)) #write each node state to an array
power_state = state[1]
if power_state ==1:
led(40,1) #turn LED on because all the nodes are on
if not checksame(state): #checks that all values in state array are the same. If not, led should blink because there is a state change or an error in a node
t = threading.Thread(target=blink, args=(40,8) )
t.start()
else:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(05, GPIO.IN, pull_up_down=GPIO.PUD_UP)
button_state = GPIO.input(05)
if button_state == False: #this is the button press detection
if power_state ==1:
#button has been pressed, and machines are on, need to be off
for node in nodes:
node_name = node.get('name', '')
node_ip = node.get('ip', '')
shutdown(node_name, node_ip)
print "Nodes have been shut down"
else:
#button has been pressed, machines are off, need to be on
for node in nodes:
node_name = node.get('name', '')
node_mac = node.get('mac', '')
wake(node_name,node_mac)
print "Nodes have been powered on"
t = threading.Thread(target=blink, args=(40, 180) )#this is a hack to show the LED blinking until the nodes can be pinged, otherwise, the LED would be off until the nodes were ping-able
t.start()
time.sleep(0.2)
if __name__ == "__main__":
main()