Running a python script at at system boot as a daemon - python

I am attempting to create a daemon that will execute my script at boot.
using this code as my template Running a python script
my python script works interactively when a user is logged in.
def wait_for_network():
while os.system("ping -c 1 8.8.8.8") != 0:
time.sleep(1)
return
from getmac import get_mac_address
from datetime import datetime
import RPi.GPIO as GPIO
import os
import time
import random
import RPi.GPIO as GPIO
import requests
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN)
GPIO.setup(6, GPIO.IN)
GPIO.setup(23, GPIO.IN)
GPIO.setup(24, GPIO.IN)
GPIO.setup(14, GPIO.IN)
eth_mac = get_mac_address()
#print(eth_mac)
API_ENDPOINT = "https://xxxxxx.com/handlers/receiveStatus.ashx"
CUSTOMER_KEY = "1234567890"
# Define a callback function that will be called by the GPIO
# event system:
def onButton(channel):
if channel == 14:
dt_string = (datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3])
data = {'ID':CUSTOMER_KEY,
'UUID':str(eth_mac),
'DT':dt_string,
'A':str(GPIO.input(6)),
'B':str(GPIO.input(24)),
'C':str(GPIO.input(23)),
'D':str(GPIO.input(5))
}
r = requests.post(url = API_ENDPOINT, data = data)
#print r.text
#print data
GPIO.add_event_detect(14, GPIO.RISING, callback=onButton, bouncetime=20)
#input()
My question is this - the #input() do i need it when running as a daemon?
With it, the script runs until the users presses ctrl-c to break out of.
When I comment it out, the script runs once then returns to the prompt.

The GPIO is making a thread and the main thread needs to wait for it. That was done with the input(). What you can do instead is to make a loop that sleeps instead in place of the input().
while True:
time.sleep(1)
That will hold the process from exiting until a ctrl c happens.

Related

How run 2 script python in same time?

I explain my need : i wish to run ffmpeg with a python script (that's ok) but i need to know of the script is launched with a blink led connected on the GPIO of my RPI, But i dont know why i can launch my script and start le blink (or just a led on)
Can u help me ? show me the light, please ;)
import RPi.GPIO as GPIO
import time
import os
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22,GPIO.IN)
# fonction qui fait clignoter la led
def blink(led):
GPIO.output(led,True)
time.sleep(0.5)
GPIO.output(led,False)
time.sleep(1)
# input of the switch will change the state of the LED
while 1:
if ( GPIO.input(22) == True ):
print "start broadcast"
os.system("sudo /home/pi/videopi/webcam.sh")
blink(4) << not ok like this !
time.sleep(1)
Assuming your os script runs successfully (I would recommend subprocess instead), what you're describing is called concurrency -- https://realpython.com/python-concurrency/
I would structure your code like this:
import RPi.GPIO as GPIO
import time
import os
from threading import Thread
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22,GPIO.IN)
# fonction qui fait clignoter la led
def blink(led):
while True:
GPIO.output(led,True)
time.sleep(0.5)
GPIO.output(led,False)
time.sleep(1)
# input of the switch will change the state of the LED
while True:
if ( GPIO.input(22) == True ):
blinking = Thread(target=blink, args=(4,)) # create thread
blinking.start() # start blinking
print("start broadcast")
os.system("sudo /home/pi/videopi/webcam.sh")
blinking.join() # stops blinking once webcam.sh completed
print("broadcast complete")

how to run a part of a python program when it is a certain time

I would like to run my a function within my python program when the time is 7am. Almost like a when function when time == time:
I don't want to use cron because I want this to be internal function not executing the whole script
Here is my python script I have created:
#sprinkler.py file for sprinkler system
#this is the main file for the sprinklerOS
#functions to import for our test_run.py file
import RPi.GPIO as GPIO
import time
import argparse
import sys
import datetime
#how many zones the user/YOU have set up
zone_count = 10
#gpio pins on the raspberry pi for sprinkler system
pin = [12,7,16,11,18,13,22,15,32,29]
#set mode to board meaning the pin number on pi (1-40) instead of gpio number
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
#setting up all of the lights or relays as outputs(in a while loop)
for a in range(10):
GPIO.setup(pin[a],GPIO.OUT)
GPIO.output(pin[a], GPIO.LOW)
def run_sprinklers():
for b in range(zone_count):
run_time = 5
GPIO.output(pin[b], GPIO.HIGH)
time.sleep(run_time)
GPIO.output(pin[b], GPIO.LOW)
time.sleep(1)
I want to run_sprinklers() when the time is 7am
Thank you in advanced
As others have mentioned in the comments, cron is probably the best solution. However if this is a persistent process and you cannot rely on a tool like cron the schedule module, https://github.com/dbader/schedule, might be of interest to you.
import RPi.GPIO as GPIO
import time
import argparse
import sys
import datetime
import schedule
#how many zones the user/YOU have set up
zone_count = 10
#gpio pins on the raspberry pi for sprinkler system
pin = [12,7,16,11,18,13,22,15,32,29]
#set mode to board meaning the pin number on pi (1-40) instead of gpio number
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
#setting up all of the lights or relays as outputs(in a while loop)
for a in range(10):
GPIO.setup(pin[a],GPIO.OUT)
GPIO.output(pin[a], GPIO.LOW)
def run_sprinklers():
for b in range(zone_count):
run_time = 5
GPIO.output(pin[b], GPIO.HIGH)
time.sleep(run_time)
GPIO.output(pin[b], GPIO.LOW)
time.sleep(1)
schedule.every().day.at("7:00").do(run_sprinklers)
while True:
schedule.run_pending()
time.sleep(1)

function called twice with urllib.urlopen

I have a small piece of code detecting event on a specific GPIO of my raspberry. When the event is detected, a function named increase_counter is called, if inside the function i only keep the "print('Flash ... ')" i only have one print per event,but if i call a url with urllib2 the whole increase_counter is executed twice, so i will have 2 flashes counted.
import RPi.GPIO as GPIO
import time
import urllib2,json
def increase_counter(ch):
print('Flash ... ')
requete='http://192.168.1.20:8080/json.htm?type=command&param=udevice&idx=52&svalue=1'
response=urllib2.urlopen(requete)
data = json.loads(response.read())
print data
IRPIN = 4
GPIO.setmode(GPIO.BCM) #GPIO SETUP
GPIO.setup(IRPIN,GPIO.IN) #GPIO SETUP
GPIO.add_event_detect(IRPIN, GPIO.FALLING, callback=increase_counter, bouncetime=3) #Calling event when flash is detected
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print(' Stopped !!!')
except:
print(' Stopped !!!')
raise
finally:
GPIO.remove_event_detect(IRPIN)
GPIO.cleanup(IRPIN) # GPIO cleanup

Set handler for GPIO state change using python signal module

I want to detect change in gpio input of raspberry pi and set handler using signal module of python. I am new to signal module and I can't understand how to use it. I am using this code now:
import RPi.GPIO as GPIO
import time
from datetime import datetime
import picamera
i=0
j=0
camera= picamera.PiCamera()
camera.resolution = (640, 480)
# handle the button event
def buttonEventHandler (pin):
global j
j+=1
#camera.close()
print "handling button event"
print("pressed",str(datetime.now()))
time.sleep(4)
camera.capture( 'clicked%02d.jpg' %j )
#camera.close()
def main():
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(2,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(2,GPIO.FALLING)
GPIO.add_event_callback(2,buttonEventHandler)
# RPIO.add_interrupt_callback(2,buttonEventHandler,falling,RPIO.PUD_UP,False,None)
while True:
global i
print "Hello world! {0}".format(i)
i=i+1
time.sleep(5)
# if(GPIO.input(2)==GPIO.LOW):
# GPIO.cleanup()
if __name__=="__main__":
main()
I just changed code in a different manner tough you are free to implement same using SIGNAL module.You can start new thread and poll or register call back event their, by using following code and write whatever your functional logic in it's run() method.
import threading
import RPi.GPIO as GPIO
import time
import time
from datetime import datetime
import picamera
i=0
j=0
camera= picamera.PiCamera()
camera.resolution = (640, 480)
PIN = 2
class GPIOThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
if GPIO.input(PIN) == False: # adjust this statement as per your pin status i.e HIGH/LOW
global j
j+=1
#camera.close()
print "handling button event"
print("pressed",str(datetime.now()))
time.sleep(4)
camera.capture( 'clicked%02d.jpg' %j )
def main():
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(PIN,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(PIN,GPIO.FALLING)
gpio_thread = GPIOThread()
gpio_thread.start()
while True:
global i
print "Hello world! {0}".format(i)
i=i+1
time.sleep(5)
if __name__=="__main__":
main()
The above code will iterate until PIN input goes high, so once PIN goes high the condition in while loop inside run method breaks and picture is captured.
So, in order to call above thread do this.
gpio_thread = GPIOThread()
gpio_thread.start()
this will call the thread constructor init and will initialize the variable inside constructor if any, and execute the run method.
You can also call join() method , to wait until thread completes it's execution.
gpio_thread.join()
This always works for me, so Cheers!!

Python multiprocessing more infinite loops at the same time

EDIT: I SOLVED IT! DON'T MAKE THE SAME MISTAKE AS ME
replace this line:
p = multiprocessing.Process(target=check(mval,mname))
with:
p = multiprocessing.Process(target=check, args=(mval,mname))
---------------------------------------------------------------------------------------
.
.
.
I am making a robot with Raspberry Pi and some microswitches and I want to check the microswitches if they are triggered so I'm using the multiprocessing module, the process class to be exact with a few infinite while loops and the problem is that one starts and waits until it is triggered and ends and starts the next one instead of all of them starting and running independently. Here is my code so far.
import multiprocessing
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(32, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.setup(7, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.setup(12, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.setup(36, GPIO.IN, pull_up_down = GPIO.PUD_UP)
def check(mval, mname):
while True:
time.sleep(0.01)
check = GPIO.input(mval)
if check == False:
print("triggered " + mname)
with open("tmp.txt", "w"):
pass
f = open("tmp.txt", "w")
f.write(mname)
f.close()
break
def startcheck(mval, mname):
p = multiprocessing.Process(target=check(mval,mname))
p.start()
p.join()
startcheck(32, "m1")
startcheck(7, "m2")
startcheck(12, "m3")
startcheck(36, "m4")
The join() function causes each loop to terminate before the next one starts. From the standard library docs:
"join([timeout])
If the optional argument timeout is None (the default), the method blocks until the process whose join() method is called terminates. If timeout is a positive number, it blocks at most timeout seconds.
A process can be joined many times.
A process cannot join itself because this would cause a deadlock. It is an error to attempt to join a process before it has been started."
Solution: remove the join() line.

Categories

Resources