I need to make a system where the user can set a timer that goes off every x hours for x minutes (ideally starting from 0600 or at least on the 00 seconds of the actual time) over 24 hours
below is an example of the code i am trying to do, the problem is when it hits 00:00 (midnight) it goes back to being not ready.
import time
import argparse
from datetime import datetime
def main(start_time_hour, start_time_minute, watering_duration,
watering_interval_hour, watering_interval_minute):
# Watering loop, each cycle consists one application of water per watering
cycle.
while True:
# Sleep until start time is reached. Resets every 24 hours.
current_time = datetime.now()
while current_time.hour < start_time_hour: # This loop will only break after start hour is reached,
time.sleep(1) # at which point it will only pass for remainder of 24h
current_time = datetime.now()
print('Not Ready - Hour')
while current_time.minute < start_time_minute: # This loop will only break after start minute is reached,
time.sleep(1) # at which point the watering routine will execute for
current_time = datetime.now() # the remainder of the 24 hour period
print('Not Ready - minute')
while current_time.hour <= start_time_hour and current_time.minute < start_time_minute: # This loop will only break after start hour is reached,
time.sleep(1) # at which point it will only pass for remainder of 24h
current_time = datetime.now()
print('Not Ready - minute')
# Commence watering loop
print("call function to turn sprinkler valve relay ON here")
print('On time:', datetime.now().time().strftime('%H:%M:%S'))
time.sleep(watering_duration)
print("call function to turn sprinkler valve relay OFF here")
print('Off time:', datetime.now().time().strftime('%H:%M:%S'))
time.sleep(watering_interval_hour * 3600 + watering_interval_minute * 60 - watering_duration)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Watering timer code. Takes user input args and prints events to stdout")
parser.add_argument('start_time', metavar='start_time %s', help='start time in HHMM format with leading zeroes')
parser.add_argument('watering_duration', metavar='watering_duration %s', help='watering duration in seconds')
parser.add_argument('watering_interval', metavar='watering_interval %s', help='watering interval in HHMM format with leading zeroes')
args = parser.parse_args()
main(int(args.start_time[0:2]), int(args.start_time[2:4]), int(args.watering_duration),
int(args.watering_interval[0:2]), int(args.watering_interval[2:4]))
Thanks in Advance!
Linux crontab is a good option for the automated scheduler Job.
The crontab is a list of commands that you want to run on a regular schedule,
and also the user-defined functions/program it will be executed within the regular interval of time.
Usage:
MIN HOUR DOM MON DOW CMD
* * * * * /usr/local/bin/action-trigger.sh
MIN : Minute field 0 to 59
HOUR : Hour field 0 to 23
DOM : Day of Month 1-31
MON : Month field 1-12
DOW : Day Of Week 0-6
CMD : Command Any command to be executed
Related
I had to fetch live chat on Youtube and chose to use pytchat instead of Youtube API. There's no problem to fetch the chat, but it was a bit slow.
from pytchat import LiveChat
from datetime import datetime
chat = LiveChat(video_id = "36YnV9STBqc")
k=[]
while chat.is_alive():
now2 = datetime.now()
current_time2 = now2.strftime("%H:%M:%S")
print("Current Time =", current_time2,"==========") #A
try:
data = chat.get()
now3 = datetime.now()
current_time3 = now3.strftime("%H:%M:%S")
print("Current Time =", current_time3,"~~~~~~~~~~~~~") #B
for c in data.items:
comment=f"[{c.datetime}-{c.message}]"
k.append(comment) #I need to use k later
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print(comment,"Current Time =", current_time,"++++++++++++++++")
data.tick()
except KeyboardInterrupt:
chat.terminate()
break
Below shows the output of a video with 17,649 watching: (B to A took 5 secs)
Current Time = 18:49:33 ========== #A
Current Time = 18:49:33 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:29-hi] Current Time = 18:49:33 ++++++++++++++++ #4 seconds late
[2020-05-30 18:49:32-how are you] Current Time = 18:49:36 ++++++++++++++++
Current Time = 18:49:38 ========== #A
Current Time = 18:49:38 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:32-so good] Current Time = 18:49:38 ++++++++++++++++ #6 seconds late
Below shows the output of a video with 702 watching: (B to A took at least 10 secs)
Current Time = 18:49:09 ========== #A
Current Time = 18:49:10 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:06-hellp] Current Time = 18:49:10 ++++++++++++++++
[2020-05-30 18:49:07-love the music] Current Time = 18:49:15 ++++++++++++++++
Current Time = 18:49:20 ========== #A
Current Time = 18:49:20 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:15-???] Current Time = 18:49:20 ++++++++++++++++
I assume that different watching amounts will effect the time? It's also 4 to 6 secs late to fetch every chat, is it possible to solve it? Or it's just how Pytchat works?
This is a specification.
Pytchat gets the chat in exactly the same way as the browser.
If your browser displays the time of the chat and the current time down to the second, you'll get the same results.
The response of the YouTube server is presumably affected by the number of people watching the chat and the number of people posting the chat at any given time.
It needs to be verified, but as you pointed out, I'm guessing that if a lot of chat posts are made, it's taking longer for the YouTube server to process them and return the chats that are retrieved.
(If you comment out the data.tick(), you might get a little better results.)
Use
while chat.is_alive():
data = chat.get()
for c in data.sync_items():
#c can then be formatted for ur stuff
print("Formatting stuff")
sync_items() will give you appropriate realtime chat movement.
I have made a trading expert that goes through candlesticks to check if a signal has been found then execute buy , sell orders
for i in range (len(df['Open'])) :
if some logic :
buy or sell
Now I want this expert to work on real-time data, not a historical one and I struggle with making the logic on how it'd work
what I want to do is:
Looking for the last 30 bars then make some calculations on them, then
go in a loop to check the last 2 candlesticks to see if some signal
has been found
..I want the loop to work every 4 hours since I'm working on 4h
timeframe, so with every new candlestick
I'm trying to use MetaTrader5 library
copy_rates_from_pos(
symbol, // symbol name
timeframe, // timeframe
start_pos, // initial bar index
count // number of bars
)
this code would help me find the last 30 bars but still can't get my head around on how to make the for loop !
you could use something like this
import pytz
import pandas as pd
import MetaTrader5 as mt5
import time
from datetime import datetime
from threading import Timer
server_name = "AMPGlobalUSA-Demo"
server_num = # your server num
password = # password
#------------------------------------------------------------------------------
def actualtime():
# datetime object containing current date and time
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
#print("date and time =", dt_string)
return str(dt_string)
#------------------------------------------------------------------------------
def sync_60sec(op):
info_time_new = datetime.strptime(str(actualtime()), '%d/%m/%Y %H:%M:%S')
waiting_time = 60 - info_time_new.second
t = Timer(waiting_time, op)
t.start()
print(actualtime(), f'waiting till next minute and 00 sec...')
#------------------------------------------------------------------------------
def program(symbol):
if not mt5.initialize(login=server_num, server=server_name, password=password):
print("initialize() failed, error code =",mt5.last_error())
quit()
timezone = pytz.timezone("Etc/UTC")
utc_from = datetime.now()
######### Change here the timeframe
rates = mt5.copy_rates_from(symbol, mt5.TIMEFRAME_M1, utc_from, 70)
mt5.shutdown()
rates_frame = pd.DataFrame(rates)
rates_frame['time']=pd.to_datetime(rates_frame['time'], unit='s')
# If you want to work only with open, high, low, close you could use
#rates_frame = rates_frame.drop(['tick_volume', 'real_volume'], axis=1)
print(f"\n", actualtime(),f"|| waiting for signals {symbol} ||\n")
if not mt5.initialize():
print("initialize() failed, error code =",mt5.last_error())
quit()
point = mt5.symbol_info(symbol).point
price = mt5.symbol_info_tick(symbol).ask
request = {
"action": mt5.TRADE_ACTION_PENDING,
"symbol": symbol,
"volume": 1.0,
"type": mt5.ORDER_TYPE_BUY_LIMIT,
"price": price,
"sl": price + 40 * point,
"tp": price - 80 * point,
"deviation": 20,
"magic": 234000,
"comment": "st_1_min_mod_3",
"type_time": mt5.ORDER_TIME_GTC,
"type_filling": mt5.ORDER_FILLING_RETURN,
}
condition_buy_1 = (
(rates_frame.close.iloc[-2] > rates_frame.open.iloc[-2])&
(rates_frame.close.iloc[-2] > rates_frame.close.iloc[-3])
)
if condition_buy_1:
#result = mt5.order_send(request)
print('Sending Order!')
# Im using AMPGlobalUSA-Demo Server
# starting mt5
if not mt5.initialize(login=server_num, server=server_name, password=password):
print("initialize() failed, error code =",mt5.last_error())
quit()
#------------------------------------------------------------------------------
# S T A R T I N G M T 5
#------------------------------------------------------------------------------
authorized=mt5.login(server_num, password=password)
if authorized:
account_info=mt5.account_info()
if account_info!=None:
account_info_dict = mt5.account_info()._asdict()
df=pd.DataFrame(list(account_info_dict.items()),columns=['property','value'])
print("account_info() as dataframe:")
print(df)
else:
print(f"failed to connect to trade account {server_num} with password={password}, error code =",mt5.last_error())
mt5.shutdown()
#------------------------------------------------------------------------------
def trading_bot():
symbol_1 = 'EURUSD'
symbol_2 = 'EURCAD'
while True:
program(symbol_1)
program(symbol_2)
time.sleep(59.8) # it depends on your computer and ping
sync_60sec(trading_bot)
Here you have the basics how to connect and operate with Python and MT5. You can save it as py file. And you have the first script looking for signals in 1 min chart for your symbol. You could have two different scripts mor looking for signals in 5 and 15 min charts, (program_5min.py and program_15min.py). You should then, add a new sync function. For example, for 5 minutes you have to wait for one hour and 0,5,10,15 minutes and so one.
Hope it works for you, have fun!
I need to figure out if a service should be stopped or started given a start and stop time
e.g.
start_time = '16:00'
stop_time = '7:50'
if the time now is 16:50 the service should be running, if time now is 14:00, service should be stopped
start_time = '7:00'
stop_time = '20:00'
if the time now is 7:05 the service should be running, if the time is 21:00, the service should be stopped... you get the idea
so far I have this, but can't figure out the logic ;
import datetime
def test_time(start_time, stop_time):
now = datetime.datetime.now()
current_hour = int(now.hour)
current_minute = int(now.minute)
start_hour, start_minute = start_time.split(':')
stop_hour, stop_minute = stop_time.split(':')
print(f"hour: {current_hour}, minute: {current_minute}")
Use datetime to convert your text times to times. This gives you an interval during which the service should be on. If that period wraps around midnight, then split it into two intervals.
Then, simply check to see whether the current time is within the on period or off period; also check the status of the service. If the two don't match, then start/stop the service.
def sync_service(start_time, stop_time):
# start_time and stop_time are "datetime" items.
service_on = # Check status of service; return boolean
now = datetime.datetime.now()
# If interval wraps around midnight, then switch times
# to check when service is *off*
wrap_interval = stop_time < start_time
if wrap_interval:
start_time, stop_time = stop_time, start_time
# Should the service be on now?
# Check whether we're within the daily interval,
# and what type of interval we have (on or off)
want_service_on = wrap_interval != (start_time < now < stop_time)
# Adjust service status, if necessary
if want_service_on and not service_on:
service.start()
if not want_service_on and service_on:
service.stop()
Does that get you going?
I’m trying to make code run a minute before sunrise, but since updating the code (via another question) as I’ve changed time zones from GMT, I’m having trouble getting the syntax right when removing one minute.
sunriselessonemin = (ephem.date(sunrise)) + (1*ephem.minute)
Sunrise is obtained by
sunrise, sunset = ephem.localtime(home.next_rising(sun)),ephem.localtime(home.next_setting(sun))
Can anyone help a noob?
Merci
Edited to be more clearer:-)
Here is my original code. The raspberry pi i use reboots via crontab at 4am, on starting, this script runs. It ran fine in the UK, but now im not in that time zone, i needed to add in some local timezone work as per brandons previous advice.
import sys
import os
import time
import ephem
#find time of sun rise and sunset
sun = ephem.Sun()
home = ephem.Observer()
home.lat, home.lon = '45.226691', '0.013133' #your lat long
sun.compute(home)
sunrise, sunset = ephem.localtime(home.next_rising(sun)),ephem.localtime(home.next_setting(sun))
daylightminutes = (sunset - sunrise) * 1440 # find howmany minutes of daylight there are
sunriselessonemin = ephem.date(sunrise + 1*ephem.minute)
print "prog started at(home.date) = %s" %(home.date)
print "datetime = %s" % time.strftime("%Y/%-m/%-d %H:%M:%S")
print "sunrise = %s" %sunrise
print "sunset = %s" %sunset
print "daylight mins = %s" %(daylightminutes)
testmode = "yes" #yes or no
def dostuff() :
if testmode == "yes" or sunrise <= ephem.now() <= sunriselessonemin: #if time now is within a minute of sunrise, start taking pictures
print "it's sunrise!"
if testmode == "yes" :
print "TESTMODE - Taking 10 images with 10 seconds in between and uploading made mp4 to Dropbox"
FRAMES = daylightminutes # number of images you want in timelapse video
if testmode == "yes" :
FRAMES = 10
FPS_IN = 8 # number of images per second you want in video
FPS_OUT = 8 # number of fps in finished video 24 is a good value
TIMEBETWEEN = 60 # number of seconds between pictures, 60 = 1 minute
#take the pictures needed for the time lapse video
if testmode == "yes" :
TIMEBETWEEN = 10
frameCount = 1
while frameCount < (FRAMES + 1):
print "taking image number ", frameCount, " of ", daylightminutes
datetimenowis = ephem.now()
imageNumber = str(frameCount).zfill(7)
os.system("raspistill -o /home/pi/image%s.jpg"%(imageNumber)) # -rot 270 need for cam on side (put -rot 270 before -o)
os.system("/usr/bin/convert /home/pi/image%s.jpg -pointsize 72 -fill white -annotate +40+1590 'Chicken Cam %s' /home/pi/image%s.jpg"%(imageNumber,datetimenowis,imageNumber))
frameCount += 1
time.sleep(TIMEBETWEEN - 10) #Takes roughly 6 seconds to take a picture & 4 to add text to image
#record current time and date in variable datetime
datetimenowis = time.strftime("%Y%m%d-%H%M")
print "It's sunset, processing images into one mp4 video. Time now is ", datetimenowis
# make the timelapse video out of the images taken
os.system("avconv -r %s -i /home/pi/image%s.jpg -r %s -vcodec libx264 -crf 20 -g 15 -vf crop=2592:1458,scale=1280:720 /home/pi/timelapse%s.mp4" %(FPS_IN,'%7d',FPS_OUT,datetimenowis))
#send the timelapse video to dropbox
print "Sending mp4 video to dropbox."
from subprocess import call
photofile = "/home/pi/Dropbox-Uploader/dropbox_uploader.sh upload /home/pi/timelapse%s.mp4 timelapse%s.mp4" %(datetimenowis,datetimenowis)
call ([photofile], shell=True)
print "mp4 uploaded to dropbox! Cleaning up."
#remove the timelapse video copy and all images it is made up of that are held localy on the Rpi
os.system("rm /home/pi/timelapse%s.mp4"%(datetimenowis))
os.system("rm /home/pi/image*")
print "Finished, exiting program."
sys.exit()
while ephem.now() <= sunrise:
time.sleep(1)
dostuff()
The issue at the momnet, is that if i try to tringer the main code at one minute befoe sunset. the code fails here.
pi#raspberrypi ~ $ sudo python timelapseV3.py
Traceback (most recent call last):
File "timelapseV3.py", line 13, in <module>
sunriselessonemin = ephem.date(sunrise + 1*ephem.minute)
TypeError: unsupported operand type(s) for +: 'datetime.datetime' and
'float'
I cant seem to start the code a minute before sunrise like i could before.
cheers
Once you run localtime() on a PyEphem date, you move it away from being a value that PyEphem can reason about and instead create a value that Python’s native datetime module knows about. To use the value in PyEphem, keep a copy of the raw value returned by PyEphem, and do the math with it instead:
sunrise, sunset = home.next_rising(sun), home.next_setting(sun)
sunrise_localtime, sunset_localtime = ephem.localtime(sunrise), ephem.localtime(sunset)
daylightminutes = (sunset_localtime - sunrise_localtime) * 1440 # find howmany minutes of daylight there are
sunriselessonemin = ephem.date(sunrise + 1*ephem.minute)
You should find that this runs without error. Good luck!
I'm trying to make a scheduler to run scripts at certain times.
The code below is my own version, but there is a problem with when the time gets to 23:59:59 and goes across to 00:00:01 it for some reason doesn't continue idling... instead it calls the callscripts() once and then it will go back to idling...
from datetime import date, timedelta
from sched import scheduler
from time import time, sleep, strftime
import random
s = scheduler(time, sleep)
random.seed()
def periodically(runtime, intsmall, intlarge, function):
## Get current time
currenttime = strftime('%H:%M:%S')
## If currenttime is anywhere between 23:40 and 23:50 then...
if currenttime > '23:40:00' and currenttime < '23:50:00':
## Call clear
clear()
## Update time
currenttime = strftime('%H:%M:%S')
## Idle time
while currenttime > '23:40:00' and currenttime < '23:59:59' or currenttime > '00:00:00' and currenttime < '01:30:00':
## Update time
currenttime = strftime('%H:%M:%S')
runtime += random.randrange(intsmall, intlarge)
s.enter(runtime, 1, function, ())
s.run()
def callscripts():
print "Calling Functions"
main1()
main2()
def main1():
print "Main1"
def main2():
print "Main2"
def clear():
print "Clearing"
while True:
periodically(2, -1, +1, callscripts)
Anyone know how this can be fixed or know a better way to do this?
Many thanks AEA
This is just a concept on how you could go about things more efficiently than using strings.
import time, calendar
# Get the current time in a localtime manner (we need it for the day and year)
today = time.localtime(time.time())
# We put the day, month and year into a strftime -> localtime converter
# giving us the localtime version of 00:00:00 of today (there's cleaner version for this process)
today_strftime = time.strptime(str(today.tm_mday) + " " + time.strftime("%b") + " " + str(today.tm_year)[-2:], "%d %b %y")
# Then we take that localtime of 00:00:00 and put it into timegm which gives us the unix
# timestamp of 00:00:00 today, which we can subtract from time.time() to give us how many
# seconds of today has passed since 00:00:00.. Which we can use to compare integers with eachother (more efficient, and easy to compare)
unixtime_beginning_of_day = calendar.timegm(today_strftime)
time_passed_today = time.time() - unixtime_beginning_of_day
if time_passed_today > 3600:
# 60sec per min * 60 minutes per hour == 3600 seconds in one hour.
print "One hour has passed since the start of this day"