From 4fa22eda2b33bfc258ccb5128f3b01cff4f4ad49 Mon Sep 17 00:00:00 2001 From: Justin Emter Date: Sat, 15 Jul 2017 09:19:26 -0700 Subject: [PATCH] The controller is now working, triggering the play state of the scheduled episodes. Currently alot todo to add movies, commercials and options to disable / use certain features. --- pseudo-tv.db | Bin 466944 -> 474112 bytes pseudo_generate_daily_scheduledb.py | 101 ++++++++++++++++++++-------- pseudo_tv_controller.py | 94 ++++++++++++++++++++++++++ schedule.sh | 8 ++- 4 files changed, 174 insertions(+), 29 deletions(-) create mode 100644 pseudo_tv_controller.py diff --git a/pseudo-tv.db b/pseudo-tv.db index ad9f246334d236fe3b2e553bbff95a04c2ad9e07..fe31290fa1c72f3f3a7f7988b2295b19d00021b0 100644 GIT binary patch delta 4513 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 J)eoD<`9H>6WSam0 delta 3524 zcmZveYitzP702&mcV_)uKQK1?fH7b@j?J>O56|wz0U7MY5F4-UwZSB68QEid>&>pU zyT-CWT@<4B15$)*$rH7WFeIU+4;9J>7nG(^OIx@7k|>cdaC^eeu>-)q!g6OCaFi-&}l+t~qVf z6#shsmo|f;n$Rcg#uojOK4FN@sSW?82`ukc*1!!8^&p39ra>mt=0C-trKl+ zxbl^jD!#e16JJ=kwSR9NzHqkvyJy=m3<86~Fu*Wwo^9tY{%PklqQ9lD(f~D)yW~6x zkZSw^UdJKaj6Ok^HQ{ycV4XZ(i43MzlhtH*Plfven)-m-XBjIt29_cbVKBCoP(@9# z@|I?|>~_jdr#xCTZ$SGL7Mp_^qdh|$&}vD(we zT-EkU6h-tp9VJi5_lbo6jF(|k-dPj2j;{u})KFzLa}37dnLhhec<@(2C7z6`@k9d| zR;G`voKfSV2pb^u4U2xKbDvX$uK*@bkL-3i{9eiFbS|sv!i=(#n5tkjNk{8fBFR{^ zTR5gnF9@+&0bHpj>htJck!@}X+bMe_*#+z#ua5l<6JrnH3cJagQL23v=4`2s{0_m^ z6qB5O+3NzBL-YVBuX2=Uq%IvPG_MMw@XM-jNQusblkEj$sW?EoTtIa=MKO(R$-Maj z$CyVkhV9R)`^#r^CvMb6KcbD=8;>~Nqw}BBCwn2X{SLoNuS_vAidRnw{*`XS4QYzO z2fkW=!ZoEtSjQIT{C>*7)`^%vG-aO7-e@u$i70cbF#d8lIlr=tzoZWlsoYy&0>6t6 zm&DwaV^2}W-d|vE4yD4$WCWb0Doa8z7GGGgm$J*;Cdtko+2eM2e0ugIVeC#FyFV7~ zND3fyK{y^;wiR-9A}#Iy_)2h@QX<+@S-9VsJKM%TZxai9~jka?AAg z$go9DufxqYE$<7KF{@B-GonAH!{jOX37I4m-@yIo3$%`UA$jg>IN8J=?Z?=f-HSWg z!vNi$GSWaitVU-NUKa7eqSM5}UH14K?qct3W282WyKk$(7Q*MyQd2TXkTD8dH-?@n}sswoGo1?DEMjufyr{ z>8RgoVAR7HdvkL8gkYSh3&mnW-C%fbUYL!=g|RRcu0*AFWr}OkPFs0Cr8^j+mr3?| z9HOLm{AhhvaW25`WSlvxOsmGU;-ewqa6Gm=<1Y8EmwDGMK|TSs`Mn&i%OO))y|^<^|15n^*h9(^E+l{%npp9%B9cY?UAS|3@M4E@Ip9|s4x`Do2#HR zl}oCgbZ+rG+>+j}!?g?wDLM}wpH~)DVPeswpW}(mIurjh zy0-@1MYZTn8QrHprQe~8bdo*?tElgO59c}6wyTCm25hJHsks|>^M$L^ z^|xH1#Lpr7YTu5EPRu5D(LLG+ly6?pN#0k@?zB-65Lbyl3v=@u<(V44jw&J1z^AP$ zv#=EwZV)yz7v|ePJ6$*d+P5)pm5V}+kZy$kjp{R;>|e>ma8^13xMh+}M?lif1!!wM z=_bU%E=0V9c+qZ_&b0qw-m>>qa*e<_y?#4&-my+@D+NAo}nSwlHJsZ z|A}Wbn}NRujqTMP?iThyI~|ysyLpi0Dm8lx)(*UcKgJ(JSBsvlW7E258@%f$Y1ipe zCCt{RQu0GWE+cZ8Y>=NL=#5K02bvkmOAl+9<84-bRx3$rS~thPfy~|@(#H`j* z$vohQwq@a6<`X5xN-G#AnGy1QW@bQBPC};(xqOd#g5AkCwE=C-%I~*@ijDd}cBOS~ zK7~49_z@gU!}|NwU?TK+M6c54nPWuSFx|`&!ic`6vXJfP3pLeKnxUb5e@#t&X*(nJ a=}8+?)Z*d_q_SKuWxGgsx>?Jmy#E7{LTKdx diff --git a/pseudo_generate_daily_scheduledb.py b/pseudo_generate_daily_scheduledb.py index 96c0303..48e271c 100644 --- a/pseudo_generate_daily_scheduledb.py +++ b/pseudo_generate_daily_scheduledb.py @@ -29,15 +29,15 @@ def create_table(): c.execute('DROP TABLE IF EXISTS daily_schedule') - c.execute('CREATE TABLE daily_schedule(id INTEGER PRIMARY KEY AUTOINCREMENT, unix INTEGER, mediaID INTEGER, title TEXT, episodeNumber INTEGER, seasonNumber INTEGER, showTitle TEXT, duration INTEGER, startTime INTEGER, endTime INTEGER, dayOfWeek TEXT)') + c.execute('CREATE TABLE daily_schedule(id INTEGER PRIMARY KEY AUTOINCREMENT, unix INTEGER, mediaID INTEGER, title TEXT, episodeNumber INTEGER, seasonNumber INTEGER, showTitle TEXT, duration INTEGER, startTime INTEGER, endTime INTEGER, dayOfWeek TEXT, startTimeUnix INTEGER)') -def add_daily_schedule_to_db(mediaID, title, episodeNumber, seasonNumber, showTitle, duration, startTime, endTime, dayOfWeek): +def add_daily_schedule_to_db(mediaID, title, episodeNumber, seasonNumber, showTitle, duration, startTime, endTime, dayOfWeek, startTimeUnix): unix = int(time.time()) try: - c.execute("INSERT OR REPLACE INTO daily_schedule (unix, mediaID, title, episodeNumber, seasonNumber, showTitle, duration, startTime, endTime, dayOfWeek) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (unix, mediaID, title, episodeNumber, seasonNumber, showTitle, duration, startTime, endTime, dayOfWeek)) + c.execute("INSERT OR REPLACE INTO daily_schedule (unix, mediaID, title, episodeNumber, seasonNumber, showTitle, duration, startTime, endTime, dayOfWeek, startTimeUnix) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (unix, mediaID, title, episodeNumber, seasonNumber, showTitle, duration, startTime, endTime, dayOfWeek, startTimeUnix)) conn.commit() @@ -63,8 +63,8 @@ def time_diff(time1,time2): * Getting the offest by comparing both times from the unix epoch time and getting the difference. * ''' - timeA = datetime.datetime.strptime(time1, "%H:%M") - timeB = datetime.datetime.strptime(time2, "%H:%M") + timeA = datetime.datetime.strptime(time1, "%I:%M %p") + timeB = datetime.datetime.strptime(time2, "%I:%M %p") timeAEpoch = calendar.timegm(timeA.timetuple()) timeBEpoch = calendar.timegm(timeB.timetuple()) @@ -73,6 +73,11 @@ def time_diff(time1,time2): return int(tdelta/60) + +def adjust_start_time_if_duration_is_too_short(duration): + + print("") + ''' * * Passing in the endtime from the prev episode and desired start time of this episode, calculate the best start time @@ -80,45 +85,58 @@ def time_diff(time1,time2): * Returns time - for new start time * ''' -def calculate_start_time_offset_from_prev_episode_endtime(prevEndTime, intendedStartTime): +def calculate_start_time_offset_from_prev_episode_endtime(prevEndTime, intendedStartTime, duration, prevEpDuration): - time1 = prevEndTime.strftime('%H:%M') + time1 = prevEndTime.strftime('%I:%M %p') - # time2 = intendedStartTime.strftime('%H:%M') - - timeB = datetime.datetime.strptime(intendedStartTime, '%Y-%m-%d %H:%M:%S').strftime('%H:%M') - - print(timeB) + timeB = datetime.datetime.strptime(intendedStartTime, '%Y-%m-%d %H:%M:%S').strftime('%I:%M %p') timeDiff = time_diff(time1, timeB) print("timeDiff "+ str(timeDiff)) + print("startTimeUNIX: "+ str(intendedStartTime)) + + newTimeObj = datetime.datetime.strptime(intendedStartTime, "%Y-%m-%d %H:%M:%S") + + newStartTime = datetime.datetime.strptime(intendedStartTime, '%Y-%m-%d %H:%M:%S') ''' * * If time difference is negative, then we know there is overlap * ''' - if timeDiff < 0: + if timeDiff <= 0: print("There is overlap ") - elif timeDiff > 10: + + ''' + * + * If timeDiff is not more than 15 minutes, or 30 minutes just adjust by 15 or 30. If more than adjust by the exact difference + * + ''' + newStartTime = newTimeObj + datetime.timedelta(minutes=abs(timeDiff + 5)) + + elif timeDiff <= 5: + + print("timeDiff is less than or equal to 5 minutes") + + elif timeDiff > 5: print("Time gap is more than ten, let's start next media earlier than inended") - elif timeDiff > 20: + # if prevEpDuration < 10 - print("Time gap is more than 20 minutes, let's start next media earlier than inended") - - elif timeDiff > 30: - - print("Time gap is more than 30 minutes, let's start next media earlier than inended") + newStartTime = newTimeObj - datetime.timedelta(minutes=timeDiff-5) else: print("Not sure what to do here") + + + return newStartTime.strftime('%I:%M %p') + ''' * * Using datetime to figure out when the media item will end based on the scheduled start time or the offset @@ -191,6 +209,8 @@ def generate_daily_schedule(): * ''' prevEpisodeEndTime = None + + prevEpDuration = None ''' * * Everytime this function is run it drops the previous "scheduled_shows" & table recreates it @@ -247,12 +267,21 @@ def generate_daily_schedule(): ''' endTime = get_end_time_from_duration(row[5], first_episode[4]); - print("End time: " + str(endTime)); + if prevEpisodeEndTime != None: + + newStartTime = calculate_start_time_offset_from_prev_episode_endtime(prevEpisodeEndTime, row[8], first_episode[4], prevEpDuration) + + else: + + prevEpisodeEndTime = endTime + + prevEpDuration = first_episode[4] + print("prevEpisodeEndTime: " + str(prevEpisodeEndTime)); - add_daily_schedule_to_db(0, first_episode_title, first_episode[5], first_episode[6], row[3], 0, row[5], endTime, row[7]) + startTimeUnix = datetime.datetime.strptime(newStartTime, '%I:%M %p') - prevEpisodeEndTime = endTime + add_daily_schedule_to_db(0, first_episode[3], first_episode[5], first_episode[6], row[3], first_episode[4], newStartTime, endTime, row[7], startTimeUnix) else: ''' @@ -300,22 +329,28 @@ def generate_daily_schedule(): * ''' - newStartTime = '' + newStartTime = row[5] if prevEpisodeEndTime != None: - calculate_start_time_offset_from_prev_episode_endtime(prevEpisodeEndTime, row[8]) + newStartTime = calculate_start_time_offset_from_prev_episode_endtime(prevEpisodeEndTime, row[8], next_episode[4], prevEpDuration) else: prevEpisodeEndTime = endTime + prevEpDuration = first_episode[4] + print("prevEpisodeEndTime: " + str(prevEpisodeEndTime)); - add_daily_schedule_to_db(0, next_episode[3], next_episode[5], next_episode[6], row[3], 0, row[5], endTime, row[7]) + startTimeUnix = datetime.datetime.strptime(newStartTime, '%I:%M %p') + + add_daily_schedule_to_db(0, next_episode[3], next_episode[5], next_episode[6], row[3], next_episode[4], newStartTime, endTime, row[7], startTimeUnix) prevEpisodeEndTime = endTime + prevEpDuration = next_episode[4] + else: print("Not grabbing next episode for some reason") @@ -344,19 +379,29 @@ def generate_daily_schedule(): print("End time: " + str(endTime)); + newStartTime = row[5] + if prevEpisodeEndTime != None: - calculate_start_time_offset_from_prev_episode_endtime(prevEpisodeEndTime, row[8]) + newStartTime = calculate_start_time_offset_from_prev_episode_endtime(prevEpisodeEndTime, row[8], first_episode[4], prevEpDuration) else: prevEpisodeEndTime = endTime + prevEpDuration = next_episode[4] + + print("prevEpisodeEndTime: " + str(prevEpisodeEndTime)); + + startTimeUnix = datetime.datetime.strptime(newStartTime, '%I:%M %p') + + add_daily_schedule_to_db(0, first_episode[3], first_episode[5], first_episode[6], row[3], first_episode[4], newStartTime, endTime, row[7], startTimeUnix) - add_daily_schedule_to_db(0, first_episode_title, first_episode[5], first_episode[6], row[3], 0, row[5], endTime, row[7]) prevEpisodeEndTime = endTime + prevEpDuration = next_episode[4] + # raise e diff --git a/pseudo_tv_controller.py b/pseudo_tv_controller.py new file mode 100644 index 0000000..aeb2d65 --- /dev/null +++ b/pseudo_tv_controller.py @@ -0,0 +1,94 @@ +#!/usr/bin/python + +from plexapi.server import PlexServer +from datetime import datetime +import sqlite3 + +import logging +import logging.handlers + +from pseudo_config import * + +plex = PlexServer(baseurl, token) + +conn = sqlite3.connect('pseudo-tv.db', timeout=10) +c = conn.cursor() + +my_logger = logging.getLogger('MyLogger') +my_logger.setLevel(logging.DEBUG) + +handler = logging.handlers.SysLogHandler(address = '/dev/log') + +my_logger.addHandler(handler) + +def showConnectedClients(): + for client in plex.clients(): + print(client.title) + +def playMovie(): + cars = plex.library.section('Movies').get('Dumb and Dumber') + client = plex.client("RasPlex") + print(cars) + client.playMedia(cars) +''' +* +* Play Media +* +''' +def play_media(mediaType, mediaParentTitle, mediaTitle): + media = plex.library.section(mediaType).get(mediaParentTitle).episodes() + client = plex.client("RasPlex") + last_episode = plex.library.section('TV Shows') + for part in media: + # print(part.title) + if part.title == mediaTitle: + client.playMedia(part) + break + +''' +* +* Check DB / current time. If that matches a scheduled shows startTime then trigger play via Plex API +* +''' +def tv_controller(): + + currentTime = datetime.now() + + sql = """SELECT * + FROM scheduled_shows + WHERE datetime(startTimeUnix) = ? AND + datetime(startTimeUnix) = ? """ + + + c.execute("SELECT * FROM daily_schedule ORDER BY datetime(startTimeUnix) ASC") + + datalist = list(c.fetchall()) + + my_logger.debug('TV Controller') + + for row in datalist: + + timeB = datetime.strptime(row[8], '%I:%M %p') + + if currentTime.hour == timeB.hour: + + if currentTime.minute == timeB.minute: + + print("Starting Epsisode: " + row[3]) + print(row) + + play_media("TV Shows", row[6], row[3]) + + my_logger.debug('Trying to play: ' + row[3]) + + break + + + + +tv_controller() + +#showConnectedClients() + +#playMovie() +#play_media("TV Shows", "The Office (US)", "Garage Sale") \ No newline at end of file diff --git a/schedule.sh b/schedule.sh index b8b3175..5d5e368 100644 --- a/schedule.sh +++ b/schedule.sh @@ -30,4 +30,10 @@ python pseudo_channel.py -a "shows" -n "the office (us)" -t "4:30 PM" -d "weekda python pseudo_channel.py -a "shows" -n "friends" -t "5:00 PM" -d "weekdays" python pseudo_channel.py -a "shows" -n "friends" -t "5:30 PM" -d "weekdays" -python pseudo_channel.py -a "shows" -n "friends" -t "5:40 PM" -d "weekdays" +python pseudo_channel.py -a "shows" -n "friends" -t "5:31 PM" -d "weekdays" + +python pseudo_channel.py -a "shows" -n "friends" -t "6:30 PM" -d "weekdays" +python pseudo_channel.py -a "shows" -n "friends" -t "8:34 PM" -d "weekdays" +python pseudo_channel.py -a "shows" -n "friends" -t "8:50 PM" -d "weekdays" +python pseudo_channel.py -a "shows" -n "friends" -t "9:00 PM" -d "weekdays" +python pseudo_channel.py -a "shows" -n "the it crowd" -t "9:30 PM" -d "weekdays"