I'm trying to create a timer that starts when a condition for an if statement is met and then stops and returns the duration when elif condition is met, is this possible?
The purpose of the application is to send a true or false value to AWS IoT from an Android application. The Python script is subscribed to AWS and receives the value and uses it to determine whether the led should be on or off.
The code I have:
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import RPi.GPIO as GPIO
import sys
import logging
import time
from time import sleep
from timeit import default_timer as timer
import getopt
import grovepi
msgpay = None
# Custom MQTT message callback
def customCallback(client, userdata, message):
print("Received a new message: ")
print(message.payload)
print("from topic: ")
print(message.topic)
print("--------------\n\n")
global msgpay
msgpay = message.payload
led = 5
grovepi.pinMode(led, "OUTPUT")
start_time = timer()
if msgpay == "true":
print("turning on")
grovepi.digitalWrite(led, 1)
#time.sleep(3)
elif msgpay == "false":
print("turning off")
grovepi.digitalWrite(led, 0)
duration = timer() - start_time
print duration
Any help how to go about this would be appreciated.
Thanks
Related
I know that this question has been asked multiple times, however I couldn't solve the issue by going over the answers. I need help. I wrote this telegram bot in Python in order to practice, and everything works ok, however yesterday I tried to implement an "uptime" timer, I wrote the function and on its own if works, however when I call it in the main file it will override everything else and the bot will not work. Furthermore, I tried to implement threading and multithreading and pretty much everything I could find online, however it still did not work. I think that I'm doing something wrong. I'm providing you with the code that I have, but I have removed the threading section from it.
Timer function
import time
import os
import Responses
def cls():
os.system('cls' if os.name == 'nt' else 'clear')
def uptime():
days = 0
hours = 0
minutes = 0
seconds = 0
while True:
time.sleep(1)
seconds += 1
if seconds > 59:
seconds = 0
minutes += 1
if minutes > 59:
minutes = 0
hours += 1
if hours > 23:
hours = 0
days += 1
cls()
print(f"{Responses.bot_name} has started...")
print(f"Uptime {days}d:{hours}h:{minutes}m:{seconds}s")
Main Bot file
import os
import telebot
import Gif
import Responses as R
import Weather
from dotenv import load_dotenv
import timer
load_dotenv()
bot_name = R.bot_name
TELEGRAM_KEY = os.getenv('TELEGRAM_KEY')
bot = telebot.TeleBot(TELEGRAM_KEY, parse_mode=None)
print(f"{bot_name} Started...")
#bot.message_handler(commands=['start'])
def greet(message):
photo = open(r"Bot Demo.png", 'rb')
bot.send_message(message.chat.id, f"Hi {message.chat.first_name}, my name is <b>{bot_name}</b>!", parse_mode='html')
bot.send_photo(message.chat.id, photo, caption="This is me! \nI can send Pictures!")
bot.send_message(message.chat.id, "Use <i>/help</i> to find out what else I can do!", parse_mode='html')
#bot.message_handler(commands=['help'])
def help(message):
bot.send_message(message.chat.id, "Hi I'm a <b>DEMO</b> Bot!"
"\nYou can greet me and I'll <b>respond</b>."
"\nYou can ask me about the <b>time</b> and the <b>date</b>."
"\nYou can ask me to tell you a <b>joke</b>."
"\nYou can ask for a <b>gif</b> and you will receive a random gif from the API."
"\nYou can use <i>/weather</i> to get the <b>Weather</b>."
"\nYou can use <i>/gif</i> to get a <b>GIF</b> from a specific category."
"\nYou can also use <i>/info</i> to get more <b>information</b> about my creator.", parse_mode='html')
#bot.message_handler(commands=['info'])
def info(message):
bot.send_message(message.chat.id, "Hi, my name is Kaloian Kozlev and I am the creator of this bot."
"\nIf you need a Bot for your social media, "
"you can contact me on kbkozlev#gmail.com")
#bot.message_handler(commands=['gif'])
def gif(message):
sent = bot.send_message(message.chat.id, "If you want a specific GIF "
"\nenter <search_term>"
"\nexample: cat")
bot.register_next_step_handler(sent, condition)
def condition(message):
q = str(message.text).lower()
bot.send_video(message.chat.id, Gif.search_gif(q), caption=f"Here is a picture of a random {q}")
#bot.message_handler(commands=['weather'])
def weather(message):
sent = bot.send_message(message.chat.id, "Enter City name:")
bot.register_next_step_handler(sent, city)
def city(message):
q = str(message.text).lower()
bot.send_message(message.chat.id, Weather.get_weather(q))
#bot.message_handler()
def handle_message(message):
text = str(message.text).lower()
response = R.sample_responses(text)
bot.send_message(message.chat.id, response)
if "gif" in text:
bot.send_video(message.chat.id, Gif.get_gif(), caption="I'm using an API to get this GIF")
timer.uptime()
bot.polling()
This is a wild guess, because you didn't show your threading code. A common mistake when using the threading module, is executing your function in the call, rather than just passing the name. Perhaps you did this:
threading.Thread(target=myfunction())
Instead of this:
threading.Thread(target=myfunction)
It's a common error.
Maybe try out threading or multiprocessing if you haven't already.
Threading Example - from this site
import threading
def function_1():
print("Inside The Function 1")
def function_2():
print("Inside The Function 2")
# Create a new thread
Thread1 = threading.Thread(target=function_1)
# Create another new thread
Thread2 = threading.Thread(target=function_2)
# Start the thread
Thread1.start()
# Start the thread
Thread2.start()
# Wait for the threads to finish
Thread1.join()
Thread2.join()
print(“Done!”)
So I'm creating a Password Manager, and as a security feature I wanted to add session time that logs the user out after some time of inactivity (in the example code 3 seconds), and I have this code :
import os
import time
import threading
# Checks what OS you're using
def check_platform():
if os.name == "nt":
platform = "Windows"
else:
platform = "Linux"
return platform
# Starts inactivity timer
def start_timer():
platform = check_platform()
if platform == "Windows":
def timer_start():
while True:
time.sleep(1)
check_if_idle_windows()
thread1 = threading.Thread(target=timer_start)
thread1.start()
elif platform == "Linux":
def timer_start():
while True:
time.sleep(1)
check_if_idle_linux()
thread1 = threading.Thread(target=timer_start)
thread1.start()
# Checks if the user is idle on Windows
def check_if_idle_windows():
import win32api
idle_time = (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
if idle_time > 3:
os.system("cls")
print("You have been logged out due to inactivity.")
os._exit(0)
# Checks if the user is idle on Linux
def check_if_idle_linux():
### Code to get idle time here ###
if idle_time > 3:
os.system("clear")
print("You have been logged out due to inactivity.")
os._exit(0)
def random_function_for_main_thread():
while True:
my_string = input("Enter something or stay inactive for 3 seconds : ")
print("You entered something.")
def main():
start_timer()
random_function_for_main_thread()
if __name__ == "__main__":
main()
What can I use to get idle time on Linux?
I tried this and this, and neither of them worked.
Hope my question isn't repeated, thank you.
import os
import time
import threading
# Starts inactivity timer
def start_timer():
platform = check_platform()
if platform == "Windows":
def timer_start():
while True:
time.sleep(1)
check_if_idle_windows()
thread1 = threading.Thread(target=timer_start)
thread1.start()
elif platform == "Linux":
def timer_start():
while True:
time.sleep(1)
check_if_idle_linux()
thread1 = threading.Thread(target=timer_start)
thread1.start()
# Checks what OS you're using
def check_platform():
if os.name == "nt":
platform = "Windows"
else:
platform = "Linux"
return platform
# Checks if the user is idle on Windows
def check_if_idle_windows():
import win32api
idle_time = (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
if idle_time > 3:
os.system("cls")
print("You have been logged out due to inactivity.")
os._exit(0)
# Checks if the user is idle on Linux
def check_if_idle_linux():
import subprocess
idle_time = int(subprocess.getoutput('xprintidle')) / 1000 # Requires xprintidle (sudo apt install xprintidle)
if idle_time > 3:
os.system("clear")
print("You have been logged out due to inactivity.")
os._exit(0)
def random_function_for_main_thread():
while True:
my_string = input("Enter something or stay inactive for 3 seconds : ")
print("You entered something.")
def main():
start_timer()
random_function_for_main_thread()
if __name__ == "__main__":
main()
I am fairly new to python and still learning so please be gentle on me. I have got my python script which subscribes to a MQTT topic and receives a code.
If the payload is equal to that code then it would set the timer which would turn on the display. After the time has elapsed the display would turn off until the payload is again equal to the same code as described previously.
Here is my code:
import paho.mqtt.client as mqttClient
import time
from subprocess import call
from time import sleep
def on_connect(client, userdata, flags, rc):
# print("Connected with result code "+str(rc))
client.subscribe("home/OpenMQTTGateway/433toMQTT")
#def on_message(client, userdata, msg):
# if msg.topic == 'home/OpenMQTTGateway/433toMQTT':
# print(str(msg.payload))
def on_message(client, userdata, msg):
global myGlobalMessagePayload
if msg.topic == 'home/OpenMQTTGateway/433toMQTT':
myGlobalMessagePayload = msg.payload
timeUntilDisplayOff = 240
timer = timeUntilDisplayOff
while True:
if msg.payload == '1381683':
timer = timeUntilDisplayOff
print ("Motion detected! Setting timer to " + str(timer) + " seconds.")
if timer > 0:
if timer % 10 == 0:
print ("Timer: " + str(timer) + " seconds")
timer -= 1
elif timer == 0:
call(['vcgencmd', 'display_power', '0'])
print ("Timer is 0. Display turned off. Waiting for motion...")
# display is now off. we wait for motion and turn it on
myGlobalMessagePayload == '1381683'
call(['vcgencmd', 'display_power', '1'])
timer = timeUntilDisplayOff
sleep(1)
Problem:
When I run my code, I get an error saying:
Traceback (most recent call last):
File "test2.py", line 26, in <module>
if msg.payload == '1381683':
NameError: name 'msg' is not defined
Also I have used the generic code to repeat the process i.e. near the end after # display is now off. we wait for motion and turn it on, does it look correct? or can it be made any better?
Thanks
UPDATE:
So I sorted my code thanks to #blt. However my code keeps on looping when the msg.payload matches '1381683'. I get the following:
Motion detected! Setting timer to 240 seconds.
Timer: 240 seconds
Motion detected! Setting timer to 240 seconds.
Timer: 240 seconds
Motion detected! Setting timer to 240 seconds.
Timer: 240 seconds
the above keeps on looping...
Indentation is important in python.
You need to indent the following block by one level:
timeUntilDisplayOff = 1800
timer = timeUntilDisplayOff
while True:
Otherwise the code that follows this section will not have the msg variable in scope (hence the error).
So the first half of the on_message function is:
def on_message(client, userdata, msg):
global myGlobalMessagePayload
if msg.topic == 'home/OpenMQTTGateway/433toMQTT':
myGlobalMessagePayload = msg.payload
timeUntilDisplayOff = 1800
timer = timeUntilDisplayOff
while True:
if msg.payload == '1381683':
timer = timeUntilDisplayOff
print ("Motion detected! Setting timer to " + str(timer) + " seconds.")
how should the code look so the below script runs only between 06.30h and 8.00h??
best regards
#!/usr/bin/python
from time import strftime
import sys
import subprocess from subprocess
import Popen
import pifacedigitalio
from time import sleep
pfd = pifacedigitalio.PiFaceDigital() # creates a PiFace Digital
object testprocess = None
while strftime('%H:%M') >= '06:29':
while(True):
sleep(0.1)
if pfd.input_pins[0].value == 1 and not testprocess:
subprocess.Popen(["/bin/myscript"])
testprocess = Popen(["/bin/myscript1"])
if pfd.input_pins[0].value == 0:
if testprocess:
testprocess.kill()
testprocess = None
subprocess.Popen(["/bin/mycript"])
sleep(1)
if strftime('%H:%M') == '08:00':
sys.exit()
I would do it with something like this:
from time import strftime
import sys
while strftime('%H:%M') >= '18:00':
#Your code
if strftime('%H:%M') == '20:30':
sys.exit()
You can learn more about time module here: https://docs.python.org/2/library/time.html
just get time into a time struct and compute the number of minutes from midnight, test the time window in minutes:
lt = time.localtime()
minutes = 60*lt.tm_hour + lt.tm_min
if 60*6+30 <= minutes <= 60*8:
subprocess.Popen(["/bin/myscript"])
testprocess = Popen(["/bin/myscript1"])
I have this function in a python script that detects 2 vibrations sensors, the problem is the sensors are very sensitive so usually when one is hit they are both detected which gives me a false reading. How would I stop them both from being detected at the same time? I want to detect whichever was first. This is what I have tried -
#!/usr/bin/env python
import RPi.GPIO as GPIO
from time import sleep
def setup():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(KnockPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(ShockPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def shock():
print('shock')
def knock():
print('knock')
def register_callbacks():
if GPIO.add_event_detect(ShockPin, GPIO.FALLING, callback=shock, bouncetime=5000):
sleep(5)
elif GPIO.add_event_detect(KnockPin, GPIO.FALLING, callback=knock, bouncetime=5000):
sleep(5)
if __name__ == '__main__':
try:
setup()
register_callbacks()
Just a suggestion, I don't have the setup to test it. Save the time of the last event (using datetime), and then check if the last event is more than 5 seconds ago.
import datetime
sensor_delay = 5 #delay in seconds
last_event = datetime.datetime.now()
def shock():
global last_event
if datetime.datetime.now() > last_event + datetime.timedelta(seconds=sensor_delay):
print ('shock')
last_event = datetime.datetime.now()
def knock():
global last_event
if datetime.datetime.now() > last_event + datetime.timedelta(seconds=sensor_delay):
print('knock')
last_event = datetime.datetime.now()