I'm trying to use this python library https://github.com/pimoroni/keybow-python to control a raspberry pi (initiate events, e.g. launch a script or shutdown the pi).
This works will so far. I'm struggling to detect a long press. The API linked above allows 'catching' the event of pressing the button or releasing it. Not sure how I go about measuring the time between one and the other... I tried this:
`
def time_string_to_decimals(time_string):
fields = time_string.split(":")
hours = fields[0] if len(fields) > 0 else 0.0
minutes = fields[1] if len(fields) > 1 else 0.0
seconds = fields[2] if len(fields) > 2 else 0.0
return float(hours) + (float(minutes) / 60.0) + (float(seconds) / pow(60.0, 2))
while True:
t = datetime.now().strftime('%H:%M:%S')
now = time_string_to_decimals(t)
#keybow.on()
def handle_key(index, state):
key0Up = 0
key0Down = 0
if index == 0 and state:
key0Down = now
print ("down: " + str(now))
if index == 0 and not state:
key0Up = now
downtime = key0Up - key0Down
print ("down: " + str(now))
print ("up: " + str(now))
print ("downtime: " + str(downtime))
if downtime >= 0.001:
print ("shutdown!")
if index == 3 and not state:
print ("Hello!")
if index == 6 and not state:
print ("World!")
`
... the print commands are just to follow what's going on. The problem is that the key0Down also get's set to the current time when the button is released. I'm stumped. Can anyone point me in the right direction?
Thanks!
Best regards,
Andrew
See above... I keep getting the same 'timestamp' for the key Down und key Up event...
It sounds like your issue is that when the #keybow.on decorator attaches the callback it has a static value for now that doesn't get updated by the while loop which will be in a different scope. Repeatedly declaring the callback during the while loop looks wrong also.
I don't have this hardware so it is not possible for me to test this. However, looking through the repository you linked to I would be tempted to do the following...
As you need to share the key events timings between functions I would put them into a class and have class variables for the key0up and key0down values.
I have also gone for different event handlers for the different keys to simplify the complex chain of if statements.
I was not sure if the keybow on decorator would do the right thing if used inside a class, so I have attached callbacks to keys without using a decorator.
import keybow
import time
class MyKeys:
key0Up = 0
key0Down = 0
def handle_key0(self, index, state):
if state:
self.key0Down = time.time()
print("down: ", self.key0Down)
elif not state:
self.key0Up = time.time()
downtime = self.key0Up - self.key0Down
print("down: ", self.key0Down)
print("up: ", self.key0Up)
print("downtime: ", downtime)
if downtime >= 1: # Greater than 1 second
print("shutdown!")
def handle_key3(self, index, state):
if not state:
print("Hello!")
def handle_key6(self, index, state):
if not state:
print("World!")
def main():
my_keys = MyKeys()
keybow.on(0, my_keys.handle_key0)
keybow.on(3, my_keys.handle_key3)
keybow.on(6, my_keys.handle_key6)
while True:
keybow.show()
time.sleep(1.0 / 60.0)
if __name__ == '__main__':
main()
Related
I'm developing a reminder app in Python. My question is when I execute my code. It should wait until current date equals to specific date. But it's not working, here's my code.
CODE:
from threading import Thread
from datetime import datetime, timedelta
# Current date, 8/15/2020 - 10:00
a = datetime.now()
# Specific date (1 minute later from current date), 8/15/2020 - 10:01
b = a + timedelta(minutes = 1)
# Reminder name
d = "stack reminder"
# Reminder list
c = {}
# Target function
def createThread():
while True:
if(b.second == a.second and
b.minute == a.minute and
b.hour == a.hour and
b.day == a.day and
b.month == a.month and
b.year == a.year):
print("worked")
# If thread name in reminder list
if d in c:
print("canceling")
t.cancel()
break
# Set thread and thread name and print thread name
t = Thread(target = createThread)
t.setName(d)
print(t.getName())
# Append reminder name to reminder list and print
c[d] = b
print(c)
# Start thread
t.start()
This code isn't working. Is if statement wrong? I'm creating Thread because while program waiting for specific date, I want to do different things. Where is my fault and how to run this code?
You are never updating the a variable again.
datetime.now() doesn't constantly update so you will have to call this in your thread.
a = datetime.now() in every iteration of your while loop.
At the moment you are never getting get your if condition to match as the time in a stays in the past.
Also you should be able to simplify this.
(b.second == a.second and
b.minute == a.minute and
b.hour == a.hour and
b.day == a.day and
b.month == a.month and
b.year == a.year):
To just simply
if b == a:
As both should be datetimes.
But its probably better to do use > in your condition as by using == you would have to match to the millisecond. Even matching to the second could cause issues and the condition might be missed.
i.e
If "a" (i.e the current time) >= "b" the time you want to check for.
Then fire the condition.
or put another way... If the current time is greater than or equal to the calendar entry time - then its time to alert the user.
if a >= b:
Complete Example:
from threading import Thread
from datetime import datetime, timedelta
# Current date, 8/15/2020 - 10:00
# Specific date (1 minute later from current date), 8/15/2020 - 10:01
b = datetime.now() + timedelta(minutes = 1)
# Reminder name
d = "stack reminder"
# Reminder list
c = {}
# Target function
def createThread():
while True:
a = datetime.now()
if a > b :
print("worked")
# If thread name in reminder list
if d in c:
print("canceling")
t.cancel()
break
# Set thread and thread name and print thread name
t = Thread(target = createThread)
t.setName(d)
print(t.getName())
# Append reminder name to reminder list and print
c[d] = b
print(c)
# Start thread
t.start()
Hi I am new to using Simpy.
I have a simulation for workers that work various shifts and I want to keep track of which shift is happening right now and also which day it is based off of env.now but I am having trouble with this.
I want my simulation to run but I'd like some form of a clock that prints out if a shift has ended or if a day has ended and such.
def do_task(env):
yield env.timeout(30) # each task takes 30 minutes to complete
print("Completed task")
def start(env):
while True:
# at the end of 24 hours (24 * 60)...
if env.now != 0 and env.now % 1440 == 0:
print("Day is done")
# shift is 4 hours (4 * 60)..
elif env.now != 0 and env.now % 240 == 0:
print("Shift is done")
yield env.process(do_task(env)) # I want this to be running with the above print statements printing stuff at the right times.
env = simpy.Environment()
env.process(start(env))
env.run(until = 7200) # 3 days (3 * 24 * 60 minutes)
The code above, of course, does not work. The statement env.now % 1440 == 0 doesn't quite work because if the timeout process isn't factored perfectly into 1440, it's not going to print that the day is done. How do I achieve the behavior I want?
Maybe this is too simple but this worked for me.
def ShiftClock(env):
shift=1
while True:
if env.now % 8*3600 == 0:
shift+=1
if shift>3:shift=1
print(shift)
env=simpy.Environment()
TimeClock=env.process(ShiftClock(env))
env.run(until=7*24*3600)
I think you're overcomplicating this. What you need is a simple process that does a timeout to 1440:
def day_timer(env):
while True:
yield env.timeout(1440)
print(print("Day is done"))
Your code will become more complex if you want to actually interrupt current processes at the end of your day or the end of the shift. Say it gets to the end of the day and you want your workers to stop their work and go home (even if in the middle of a job). In this case then refer to the machine shop example, where a process gets interrupted:
class Machine(object):
"""A machine produces parts and my get broken every now and then.
If it breaks, it requests a *repairman* and continues the production
after the it is repaired.
A machine has a *name* and a numberof *parts_made* thus far.
"""
def __init__(self, env, name, repairman):
self.env = env
self.name = name
self.parts_made = 0
self.broken = False
# Start "working" and "break_machine" processes for this machine.
self.process = env.process(self.working(repairman))
env.process(self.break_machine())
def working(self, repairman):
"""Produce parts as long as the simulation runs.
While making a part, the machine may break multiple times.
Request a repairman when this happens.
"""
while True:
# Start making a new part
done_in = time_per_part()
while done_in:
try:
# Working on the part
start = self.env.now
yield self.env.timeout(done_in)
done_in = 0 # Set to 0 to exit while loop.
except simpy.Interrupt:
self.broken = True
done_in -= self.env.now - start # How much time left?
# Request a repairman. This will preempt its "other_job".
with repairman.request(priority=1) as req:
yield req
yield self.env.timeout(REPAIR_TIME)
self.broken = False
# Part is done.
self.parts_made += 1
def break_machine(self):
"""Break the machine every now and then."""
while True:
yield self.env.timeout(time_to_failure())
if not self.broken:
# Only break the machine if it is currently working.
self.process.interrupt()
So in my tkinter python program I am calling on a command when a button is clicked. When that happens it runs a function but in the function I have it set a label to something on the first time the button is clicked and after that it should only update the said label. Basically after the attempt it changes the attempt to 1 ensuring the if statement will see that and not allow it to pass. However it keeps resetting and I don't know how to stop it. When you click the button no matter first or third the button resets and proof of that occurs because the h gets printed. It's as if the function restarts but it shouldn't since it's a loop for the GUI.
def fight(): #Sees which one is stronger if user is stronger he gets win if no he gets loss also displays enemy stats and removes used characters after round is finished
try:
attempt=0
namel = ""
namer=""
left = lbox.curselection()[0]
right = rbox.curselection()[0]
totalleft = 0
totalright = 0
if left == 0:
namel = "Rash"
totalleft = Rash.total
elif left==1:
namel = "Untss"
totalleft = Untss.total
elif left==2:
namel = "Illora"
totalleft = 60+35+80
if right == 0:
namer = "Zys"
totalright = Zys.total
elif right==1:
namer = "Eentha"
totalright = Eentha.total
elif right==2:
namer = "Dant"
totalright = Dant.total
lbox.delete(lbox.curselection()[0])
rbox.delete(rbox.curselection()[0])
print(namel)
print(namer)
if attempt == 0:
wins.set("Wins")
loss.set("Loss")
print("h")
attempt=1
if (totalleft>totalright):
wins.set(wins.get()+"\n"+namel)
loss.set(loss.get()+"\n"+namer)
else:
wins.set(wins.get()+"\n"+namer)
loss.set(loss.get()+"\n"+namel)
except IndexError:
pass
Also for those of you who saw my previous question I still need help with that I just also want to fix this bug too.
At beginning of function fight you set attempt = 0 so you reset it.
Besides attempt is local variable. It is created when you execute function fight and it is deleted when you leave function fight. You have to use global variable (or global IntVar)
attempt = 0
def fight():
global attempt
BTW: of you use only values 0/1 in attempt then you can use True/False.
attempt = False
def fight():
global attempt
...
if not attempt:
attempt = True
I am trying to create a thread in Python that will poll some server as long as it won't get proper answer (HTTP GET). In order to provide convenient text UI I want to print progress dots. Another dot with every connection attempt until it finish (or just another dot with every another second of waiting).
I have found something like this: http://code.activestate.com/recipes/535141-console-progress-dots-using-threads-and-a-context-/
In this example we have context manager:
with Ticker("A test"):
time.sleep(10)
I am not sure if I understand that properly. I would like to do something like:
with Ticker("A test: "):
result = -1
while result != 0:
result = poll_server()
print "Finished."
But this does not work. Any ideas?
Cheers
Python buffers your output, so many dots will appear at once. One way around that is to import sys and use that: whenever you want to print a dot, say:
sys.stdout.write(".")
sys.stdout.flush()
The flush makes the dot appear immediately.
#! /usr/bin/python3
import sys
import time
def progress(message):
i = 0
while True:
dots = ""
i = (i % 3) + 1
dots += "." * i + " " * (3 - i)
sys.stdout.write("\r{}".format(message + dots))
sys.stdout.flush()
i += 1
time.sleep(0.3)
if __name__ == "__main__":
progress("Waiting")
More useful example:
#! /usr/bin/python3
import sys
import time
def progress_gen(message):
i = 0
while True:
for x in range(0, 4):
dots = "." * x
sys.stdout.write("{}\r".format(message + dots))
i += 1
time.sleep(0.5)
sys.stdout.write("\033[K")
yield
if __name__ == "__main__":
p = progress_gen("Waiting")
for x in range(1, 100):
next(p)
if x == 3:
break
print("Finished")
You can test it online: https://repl.it/#binbrayer/DotsProgress
I am trying to create a stopwatch that starts and stops through the user pressing the enter. Once to start and again to stop. The start works perfectly but the stopping section is not working. I've tried creating a variable called stop that is like so:
stop = input("stop?")
But it's still not working.
import time
def Watch():
a = 0
hours = 0
while a < 1:
for minutes in range(0, 60):
for seconds in range(0, 60):
time.sleep(1)
print(hours,":", minutes,":", seconds)
hours = hours + 1
def whiles():
if start == "":
Watch()
if start == "":
return Watch()
def whiltr():
while Watch == True:
stop = input("Stop?")
#Ask the user to start/stop stopwatch
print ("To calculate your speed, we must first find out the time that you have taken to drive from sensor a to sensor b, consequetively for six drivers.")
start = input("Start?")
start = input("Stop")
whiles()
Perhaps all you need is something simple like:
import time
input('Start')
start = time.time()
input('Stop')
end = time.time()
print('{} seconds elapsed'.format(end-start))
Should probably use the time function instead of
def Watch():