Given start & stop time, check if service should be on - python

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?

Related

How can I make my Python script run after 2 hours?

I wrote a program that will close the hard drive with BitLocker in Windows by using libraries datetime and subprocess but I cannot get the correct result.
Here is my code:
import subprocess
import datetime
now = datetime.datetime.today()
delta = datetime.timedelta(hours=2)
time_delta = now + delta
# print(time_delta)
# print(now)
try:
if now == time_delta:
close = subprocess.check_output(['manage-bde', '-lock', 'D:', '-ForceDismount'])
close.decode('utf-8').split('\n')
print('done')
except Exception:
pass
That is because you are checking the current time now = datetime.datetime.today(), then add 2 hours to it and immediately after check, if time_delta is equal to now.
Thus the if statement always results in false and the code in it does not get executed.
You need to put something in place to wait. Something like that.
import subprocess
import datetime
import time
now = datetime.datetime.today()
delta = datetime.timedelta(hours=2)
time_delta = now + delta
while now != time_delta:
time.sleep(1) # wait for a second
now = datetime.datetime.today()
# when now == time_delta we continue here:
try:
close = subprocess.check_output(['manage-bde', '-lock', 'D:', '-ForceDismount'])
close.decode('utf-8').split('\n')
print('done')
except Exception:
pass
This is not the best way to schedule a task, but it should be working.

Logic for real-time Algo trading expert

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!

Function with a Cooldown

Hello i have a Person Detector script i want to send an info if any person detected by mail.In order to prevent mail spamming i need a timer for sendMail function.Function might be triggered anytime but it will only respond if its not on cooldown.
I tried using async task but couldn't implemented because if a person detected it goes to a loop where it sends email every 5 minutes even if there isn’t any person detected after the first sight.
Example:
Person detection script is running.
Person detected on camera -> Send an email(start the 5 minute cooldown)
Person sighted again after 2 minutes(didn't send any email because there is still 3 minutes cooldown).
Person sighted after 6 minutes send another email(because 5 minute cooldown is over).
Summary of my code.(Necessary parts only detection and sending mail works cooldown (timer) doesn't work
async def sendAlert():
server.sendmail(sender_email, receiver_email, message)
print('sent!')
await asyncio.sleep(300)
if __name__ == "__main__":
while True:
for i in range(len(boxes)):
if classes[i] == 1 and scores[i] > threshold:
with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as server:
sendAlert(server)
box = boxes[i]
cv2.rectangle(img,(box[1],box[0]),(box[3],box[2]),(255,0,0),2)
If there is a person detected, script will send an alert by email.Afterwards if a person detected again in 5 minutes sendAlert function shouldn't respond until 5 minutes passed
I agree with #Prune that you need to create a small (minimal) use-case and present your code so that it is not only relevant to you, but also relevant to others. Additionally, your question should have a section with a verifiable example. Without these attributes, your question becomes hard for people to grasp, solve and/or suggest any verifiable solution.
However, as I understand, you have some action (sending email if a person is detected) that you would like to perform after certain cool-off period. So, in other words, you want a mechanism of keeping track of time. Hence, you would need the datetime library.
So, your pseudo code should look something like this:
Pseudo Code
import datetime
start = capture_timestamp()
cutoff = '00:05:00'
dt_cutoff = read_in_cutoff_as_timedelta(cutoff)
if person_detected:
now = capture_timestamp()
dt = now - start
if dt >= dt_cutoff:
# Send notification
send_email_notification()
else:
# Do not Send Notification
print('now: {} | dt: {}'.format(now, dt))
You could use datetime.datetime.utcnow() for timestamp. And datetime.timedelta() for defining dt_cutoff. For reading in a time-string as time you could do this:
tm = datetime.datetime.strptime(cutoff).time()
dt_cutoff = datetime.timedelta(hours = tm.hour, minutes = tm.minute, seconds = tm.second)
I hope this gives you some idea about how to model this.
Additional Resources
https://www.guru99.com/date-time-and-datetime-classes-in-python.html
https://docs.python.org/3/library/datetime.html
https://thispointer.com/python-how-to-convert-a-timestamp-string-to-a-datetime-object-using-datetime-strptime/
Complete Solution
Now, finally if you are in a hurry to use a ready made solution, you may use the following class object as shown. All you would need is to instantiate the class object by specifying your cool-off-period (timer_cutoff) and then call the method is_timeout(). If this returns True, then you send your notification. There is also an obj.istimeout attribute which stores this decision (True/False).
import time
# Set cutoff time to 2 seconds to test the output
# after 5 seconds: expect istimeout = True
# and instantiate the TimeTracker class object.
ttk = TimeTracker(timer_cutoff = '00:00:02') # 'HH:MM:SS'
# Wait for 3 seconds
time.sleep(3)
print('start timestamp: {}'.format(ttk.timestamp_start_str))
print('cutoff timestamp'.format(ttk.timestamp_cutoff_str))
print('timer_cutoff: {}'.format(ttk.timer_cutoff_str))
# Now check if cutoff time reached
ttk.is_timeout()
print('Send Notification: {}'.format(ttk.istimeout))
print('now_timestamp: {}'.format(ttk.timestamp_now_str))
class TimeTracker
Here is the class TimeTracker class:
import datetime
class TimeTracker(object):
def __init__(self,
timer_cutoff = '00:05:00',
cutoff_strformat = '%H:%M:%S'):
self.timer_cutoff_str = timer_cutoff
self.cutoff_strformat = cutoff_strformat
self.timestamp_start, self.timestamp_start_str = self.get_timestamp()
self.dt_cutoff = None # timedelta for cutoff
self.timestamp_cutoff = None
self.timestamp_cutoff_str = None
self.update_timestamp_cutoff()
self.timestamp_now = None
self.timestamp_now_str = None
self.dt_elapsed = None
self.istimeout = False
def get_timestamp(self):
ts = datetime.datetime.utcnow()
tss = str(ts)
return (ts, tss)
def readin_cutoff_as_timedelta(self):
td = datetime.datetime.strptime(self.timer_cutoff_str,
self.cutoff_strformat)
tdm = td.time()
self.dt_cutoff = datetime.timedelta(hours = tdm.hour,
minutes = tdm.minute,
seconds = tdm.second)
def update_timestamp_cutoff(self):
self.readin_cutoff_as_timedelta()
self.timestamp_cutoff = self.timestamp_start + self.dt_cutoff
self.timestamp_cutoff_str = str(self.timestamp_cutoff)
def time_elapsed(self):
self.dt_elapsed = self.timestamp_now - self.timestamp_start
def is_timeout(self):
self.timestamp_now, self.timestamp_now_str = self.get_timestamp()
self.time_elapsed()
if (self.dt_elapsed < self.dt_cutoff):
self.istimeout = False
else:
self.istimeout = True
return self.istimeout

Run Function Every "X" hours for "X" Seconds over 24 hours

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

Scheduler to run certain tasks during certain times not working correctly

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"

Categories

Resources