function called twice with urllib.urlopen - python

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

Related

Running a python script at at system boot as a daemon

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.

Python script doesn't start on boot

I have a python script in my Raspberry Pi that is connected to a rain gauge. When the rain gauge detects rain, the script shows 0.2 and write it to file. This is the code:
#!/usr/bin/env python3
import time
import RPi.GPIO as GPIO
BUTTON_GPIO = 16
if __name__ == '__main__':
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP)
pressed = False
while True:
# button is pressed when pin is LOW
if not GPIO.input(BUTTON_GPIO):
if not pressed:
print("0.2")
pressed = True
# button not pressed (or released)
else:
pressed = False
time.sleep(0.1)
My idea is to use a code like that to save the total amount of rain. When the python script show 0.2 > write it to file.
python3 rain.py >> rain.txt
The code creates a file but doesn't write anything until execution is finished by Ctrl + C.
I need to execute it on boot. I have tried to add it to crontab and rc.local but doesn't work.
I tried to execute it with sudo and pi. The permissions are 755.
Thank you!
try this
import time
import RPi.GPIO as GPIO
BUTTON_GPIO = 16
if __name__ == '__main__':
outputfile=open("/var/log/rain.txt","a",0)
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP)
pressed = False
while True:
# button is pressed when pin is LOW
if not GPIO.input(BUTTON_GPIO):
if not pressed:
openputfile.write("0.2\n")
pressed = True
# button not pressed (or released)
else:
pressed = False
time.sleep(0.1)
open a file in append mode with non buffered write.
Then when an event occurs, write to that file.
Do not use shell redirect as it will (in this case) buffer all the program output until exit and then write to a file. Of course, the exit never happens as you have a "while True" with no break
Indeed, this construct command >> file takes the whole of stdout and flushes into the file. It's done only when command execution is over. You must write to the file as soon as your intermediate result is ready:
#!/usr/bin/env python3
import sys
import time
import RPi.GPIO as GPIO
BUTTON_GPIO = 16
if __name__ == '__main__':
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP)
pressed = False
# command line arguments
if len(sys.argv) > 1: ## file name was passed
fname = sys.argv[1]
else: ## standard output
fname = None
## this will clear the file with name `fname`
## exchange 'w' for 'a' to keep older data into it
outfile = open(fname, 'w')
outfile.close()
try:
while True:
# button is pressed when pin is LOW
if not GPIO.input(BUTTON_GPIO):
if not pressed:
if fname is None: ## default print
print("0.2")
else:
outfile = open(fname, 'a')
print("0.2", file=outfile)
outfile.close()
pressed = True
# button not pressed (or released)
else:
pressed = False
time.sleep(0.1)
except (Exception, KeyboardInterrupt):
outfile.close()
In this approach you should run python3 rain.py rain.txt and everything will be fine. The try except pattern ensures the file will be properly closed when execution is interrupted by errors or keyboard events.
Notice the file keyword argument in call to print. It selects an open file object to write printed stuff. It defaults to sys.stdout.

Unable to use GPIO PWM when multiple threads are available

I am working on a project which continuously waits for an user input on a screen. Once a user input was detected a servo mechanism needs to open and then close. The whole solution is written in such a way that there's one main thread and few others that are forked from the main one as follows:
The problem with this setup is the this one:
If I execute only the operations handled in the main thread -> BoxOpeningManager.py works as expected. It opens and closes the servo.
If I execute once an operation handled in the main thread and then operation handled in the forked thread, the next time I try to execute operation on the main thread BoxOpeningManager.py is not working. No error, no nothing. It is just not opening the servo. I need to restart the program.
If first I execute an operation handled in the forked thread and then try to execute one handled in the main thread, main thread is again not working.
The long story short, every time I execute something on the forked thread, I can not use the BoxOpeningManager.py in the main thread anymore.
Here is the code of both scripts:
from servoManager import ServoManager
from proximitySensorManager import ProximitySensorManager
from configurationWrapping import GlobalConfigurationWrapper
from loggingManager import Logger
import time
class BoxOpeningManager():
def __init__(self):
self.configuration = GlobalConfigurationWrapper()
self.timeToKeepTheBoxOpen = self.configuration.box_time_to_keep_the_box_open()
self.logger = Logger()
self.servoManager = ServoManager()
self.proximitySensorManager = ProximitySensorManager();
def start_box_opening_procedure(self):
try:
self.servoManager.open()
t_end = time.time() + (int)(self.timeToKeepTheBoxOpen)
while time.time() < t_end:
continue
while True:
if not self.proximitySensorManager.object_in_front() :
self.servoManager.close()
break;
else :
time.sleep(1)
except BaseException as e:
self.logger.log_critical('<BoxOpeningManager.start_box_opening_procedure> => ' + str(e))
Servo manager:
import RPi.GPIO as GPIO
from time import sleep
from patternImplementations import Singleton
from loggingManager import Logger
class ServoManager():
__metaclass__ = Singleton
__OUTPUT_GPIO_PIN_NUMBER = 12
def __init__(self):
GPIO.setmode(GPIO.BOARD)#Numbers GPIOs by physical location
GPIO.setup(self.__OUTPUT_GPIO_PIN_NUMBER, GPIO.OUT)
self.pwm=GPIO.PWM(self.__OUTPUT_GPIO_PIN_NUMBER,50)
self.pwm.start(0)
self.logger = Logger()
def open(self):
try:
self.__set_angle(13)
except BaseException as e:
self.logger.log_critical('<ServoManager.open> => ' + str(e))
def close(self):
try:
self.__set_angle(185)
except BaseException as e:
self.logger.log_critical('<ServoManager.close> => ' + str(e))
def __set_angle(self, angle):
duty = (angle/18 + 2)
GPIO.output(self.__OUTPUT_GPIO_PIN_NUMBER, True)
self.pwm.ChangeDutyCycle(duty)
sleep(1)
GPIO.output(self.__OUTPUT_GPIO_PIN_NUMBER, False)
self.pwm.ChangeDutyCycle(0)

Breaking a loop whilst in GPIO

I am using a while loop to power an LED at regular intervals. I want to run the loop as normal, but have it break and clean up when a key is pressed.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(12,GPIO.OUT)
while True:
GPIO.output(12,GPIO.HIGH)
time.sleep(0.2)
GPIO.output(12,GPIO.LOW)
time.sleep(0.2)
Where should I add a keyboard interrupt command?
Well Ctrl-C raises KeyboardInterrupt. So, you just need to catch it:
while True:
try:
#code
except KeyboardInterrupt:
break
To catch all other errors use:
except Exception as ex : # catch other exceptions #
print(ex)
So, applied to your code:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(12,GPIO.OUT)
while True:
try:
GPIO.output(12,GPIO.HIGH)
time.sleep(0.2)
GPIO.output(12,GPIO.LOW)
time.sleep(0.2)
except KeyboardInterrupt:
break
except Exception as ex : # catch other exceptions #
print(ex)

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!!

Categories

Resources