From da144a2b89349360eaf4fb73157576b66b8919f0 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sun, 26 Oct 2025 07:26:54 -0700 Subject: [PATCH] scheduler enhancment this brings scheduler into the 19th century --- etc/custom_scheduler.py | 75 +++++++++++++++-------------- mesh_bot.py | 4 +- modules/scheduler.py | 103 ++++++++++++++++++++++------------------ 3 files changed, 96 insertions(+), 86 deletions(-) diff --git a/etc/custom_scheduler.py b/etc/custom_scheduler.py index 39a3be8..ffa5999 100644 --- a/etc/custom_scheduler.py +++ b/etc/custom_scheduler.py @@ -3,50 +3,53 @@ from modules.log import logger from modules.system import send_message def setup_custom_schedules(send_message, tell_joke, welcome_message, handle_wxc, MOTD, schedulerChannel, schedulerInterface): - # custom scheduler job to run the schedule see examples below - logger.debug(f"System: Starting the custom_scheduler.py default to send reminder every Monday at noon on Device:{schedulerInterface} Channel:{schedulerChannel}") - schedule.every().monday.at("12:00").do(lambda: logger.info("System: Scheduled Broadcast Enabled Reminder")) - - # Enhanced Examples of using the scheduler, Times here are in 24hr format - # https://schedule.readthedocs.io/en/stable/ + """ + Set up all custom schedules. Edit this function to add or remove scheduled tasks. + """ + ### Example schedules # Send a joke every 2 minutes - #logger.debug(f"System: Custom Scheduler: Send a joke every 2 minutes on Device:{schedulerInterface} Channel:{schedulerChannel}") - #schedule.every(2).minutes.do(lambda: send_message(tell_joke(), schedulerChannel, 0, schedulerInterface)) + #schedule.every(2).minutes.do(send_joke, send_message, tell_joke, schedulerChannel, schedulerInterface) + # Send a good morning message every day at 9 AM + #schedule.every().day.at("09:00").do(send_good_morning, send_message, schedulerChannel, schedulerInterface) + # Send weather update every day at 8 AM + #schedule.every().day.at("08:00").do(send_wx, send_message, handle_wxc, schedulerChannel, schedulerInterface) + # Send weather alerts every Wednesday at noon + #schedule.every().wednesday.at("12:00").do(send_weather_alert, send_message, schedulerChannel, schedulerInterface) + # Send configuration URL every 2 days at 10 AM + #schedule.every(2).days.at("10:00").do(send_config_url, send_message, schedulerChannel, schedulerInterface) + # Send net starting message every Wednesday at 7 PM + #schedule.every().wednesday.at("19:00").do(send_net_starting, send_message, schedulerChannel, schedulerInterface) + # Send welcome message every 2 days at 8 AM + #schedule.every(2).days.at("08:00").do(send_welcome, send_message, schedulerChannel, schedulerInterface) + # Send MOTD every day at 1 PM + #schedule.every().day.at("13:00").do(send_motd, send_message, MOTD, schedulerChannel, schedulerInterface) + # Send bbslink message every 2 days at 10 AM + #schedule.every(2).days.at("10:00").do(send_bbslink, send_message, schedulerChannel, schedulerInterface) - # Good Morning Every day at 09:00 using send_message function to channel 2 on device 1 - #schedule.every().day.at("09:00").do(lambda: send_message("Good Morning", 2, 0, 1)) +def send_joke(send_message, tell_joke, channel, interface): + send_message(tell_joke(), channel, 0, interface) - # Send WX every Morning at 08:00 using handle_wxc function to channel 2 on device 1 - #logger.debug("System: Custom Scheduler: Send WX every Morning at 08:00") - #schedule.every().day.at("08:00").do(lambda: send_message(handle_wxc(0, 1, 'wx'), 2, 0, 1)) +def send_good_morning(send_message, channel, interface): + send_message("Good Morning", channel, 0, interface) - # Send Weather Channel Notice Wed. Noon on channel 2, device 1 - #schedule.every().wednesday.at("12:00").do(lambda: send_message("Weather alerts available on 'Alerts' channel with default 'AQ==' key.", 2, 0, 1)) +def send_wx(send_message, handle_wxc, channel, interface): + send_message(handle_wxc(0, 1, 'wx'), channel, 0, interface) - # Send config URL for Medium Fast Network Use every other day at 10:00 to default channel 2 on device 1 - #logger.debug("System: Custom Scheduler: Config URL for Medium Fast Network Use every other day at 10:00") - #schedule.every(2).days.at("10:00").do(lambda: send_message("Join us on Medium Fast https://meshtastic.org/e/#CgcSAQE6AggNEg4IARAEOAFAA0gBUB5oAQ", 2, 0, 1)) +def send_weather_alert(send_message, channel, interface): + send_message("Weather alerts available on 'Alerts' channel with default 'AQ==' key.", channel, 0, interface) - # Send a Net Starting Now Message Every Wednesday at 19:00 using send_message function to channel 2 on device 1 - #schedule.every().wednesday.at("19:00").do(lambda: send_message("Net Starting Now", 2, 0, 1)) +def send_config_url(send_message, channel, interface): + send_message("Join us on Medium Fast https://meshtastic.org/e/#CgcSAQE6AggNEg4IARAEOAFAA0gBUB5oAQ", channel, 0, interface) - # Send a Welcome Notice for group on the 15th and 25th of the month at 12:00 using send_message function to channel 2 on device 1 - #schedule.every().day.at("12:00").do(lambda: send_message("Welcome to the group", 2, 0, 1)).day(15, 25) +def send_net_starting(send_message, channel, interface): + send_message("Net Starting Now", channel, 0, interface) - # Send a Welcome Notice for group on the 15th and 25th of the month at 12:00 - #logger.debug(f"System: Custom Scheduler: Welcome Notice for group on the 15th and 25th of the month at 12:00 on Device:{schedulerInterface} Channel:{schedulerChannel}") - #schedule.every().day.at("12:00").do(lambda: send_message("Welcome to the group", schedulerChannel, 0, schedulerInterface)).day(15, 25) +def send_welcome(send_message, channel, interface): + send_message("Welcome to the group", channel, 0, interface) - # Send a joke every 6 hours - #schedule.every(6).hours.do(lambda: send_message(tell_joke(), schedulerChannel, 0, schedulerInterface)) +def send_motd(send_message, MOTD, channel, interface): + send_message(MOTD, channel, 0, interface) - # Send the Welcome Message every other day at 08:00 - #schedule.every(2).days.at("08:00").do(lambda: send_message(welcome_message, schedulerChannel, 0, schedulerInterface)) - - # Send the MOTD every day at 13:00 - #schedule.every().day.at("13:00").do(lambda: send_message(MOTD, schedulerChannel, 0, schedulerInterface)) - - # Send bbslink looking for peers every other day at 10:00 - #logger.debug("System: Custom Scheduler: bbslink MeshBot looking for peers every other day at 10:00") - #schedule.every(2).days.at("10:00").do(lambda: send_message("bbslink MeshBot looking for peers", schedulerChannel, 0, schedulerInterface)) \ No newline at end of file +def send_bbslink(send_message, channel, interface): + send_message("bbslink MeshBot looking for peers", channel, 0, interface) diff --git a/mesh_bot.py b/mesh_bot.py index 85c5aa2..14291ff 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -1616,9 +1616,7 @@ def handle_boot(mesh=True): logger.debug("System: Logging Metadata Stats Enabled, leaderboard") if my_settings.scheduler_enabled: - logger.debug("System: Scheduler Enabled") - - + logger.debug(f"System: Scheduler Enabled. Default Device:{my_settings.schedulerInterface} Channel:{my_settings.schedulerChannel}") except Exception as e: logger.error(f"System: Error during boot: {e}") diff --git a/modules/scheduler.py b/modules/scheduler.py index 32b7d67..f8c9531 100644 --- a/modules/scheduler.py +++ b/modules/scheduler.py @@ -3,6 +3,7 @@ import asyncio import schedule from datetime import datetime +from functools import partial from modules.log import logger from modules.settings import MOTD from modules.system import send_message @@ -47,13 +48,21 @@ def extract_schedule_fields(jobs): start = part.find('Every') if start != -1: # Find the start of 'do ()' - do_idx = part.find('do ()') + do_idx = part.find('do ') if do_idx != -1: summary = part[start:do_idx].strip() # Find the (last run: ... next run: ...) part paren_idx = part.find('(', do_idx) if paren_idx != -1: summary += ' ' + part[paren_idx:].strip() + while '', f_start) + if f_end == -1: + break + func_str = summary[f_start+10:f_end] + func_name = func_str.split(' ')[0] + summary = summary[:f_start] + func_name + summary[f_end+1:] results.append(summary) return results @@ -84,65 +93,65 @@ def setup_scheduler( schedulerIntervalInt = safe_int(schedulerInterval, 5, type="interval") try: - if schedulerMotd: - scheduler_message = MOTD - else: - scheduler_message = schedulerMessage + scheduler_message = MOTD if schedulerMotd else schedulerMessage + + def send_sched_msg(): + send_message(scheduler_message, schedulerChannel, 0, schedulerInterface) # Basic Scheduler Options basicOptions = ['day', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun', 'hour', 'min'] - if any(option.lower() in schedulerValue.lower() for option in basicOptions): - # Basic scheduler job to run the schedule see examples below for custom schedules - if schedulerValue.lower() == 'day': - if schedulerTime != '': - schedule.every().day.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) + if any(option in schedulerValue for option in basicOptions): + if schedulerValue == 'day': + if schedulerTime: + schedule.every().day.at(schedulerTime).do(send_sched_msg) else: - schedule.every(schedulerIntervalInt).days.do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'mon' in schedulerValue.lower() and schedulerTime != '': - schedule.every().monday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'tue' in schedulerValue.lower() and schedulerTime != '': - schedule.every().tuesday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'wed' in schedulerValue.lower() and schedulerTime != '': - schedule.every().wednesday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'thu' in schedulerValue.lower() and schedulerTime != '': - schedule.every().thursday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'fri' in schedulerValue.lower() and schedulerTime != '': - schedule.every().friday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'sat' in schedulerValue.lower() and schedulerTime != '': - schedule.every().saturday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'sun' in schedulerValue.lower() and schedulerTime != '': - schedule.every().sunday.at(schedulerTime).do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'hour' in schedulerValue.lower(): - schedule.every(schedulerIntervalInt).hours.do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) - elif 'min' in schedulerValue.lower(): - schedule.every(schedulerIntervalInt).minutes.do(lambda: send_message(scheduler_message, schedulerChannel, 0, schedulerInterface)) + schedule.every(schedulerIntervalInt).days.do(send_sched_msg) + elif 'mon' in schedulerValue and schedulerTime: + schedule.every().monday.at(schedulerTime).do(send_sched_msg) + elif 'tue' in schedulerValue and schedulerTime: + schedule.every().tuesday.at(schedulerTime).do(send_sched_msg) + elif 'wed' in schedulerValue and schedulerTime: + schedule.every().wednesday.at(schedulerTime).do(send_sched_msg) + elif 'thu' in schedulerValue and schedulerTime: + schedule.every().thursday.at(schedulerTime).do(send_sched_msg) + elif 'fri' in schedulerValue and schedulerTime: + schedule.every().friday.at(schedulerTime).do(send_sched_msg) + elif 'sat' in schedulerValue and schedulerTime: + schedule.every().saturday.at(schedulerTime).do(send_sched_msg) + elif 'sun' in schedulerValue and schedulerTime: + schedule.every().sunday.at(schedulerTime).do(send_sched_msg) + elif 'hour' in schedulerValue: + schedule.every(schedulerIntervalInt).hours.do(send_sched_msg) + elif 'min' in schedulerValue: + schedule.every(schedulerIntervalInt).minutes.do(send_sched_msg) logger.debug(f"System: Starting the basic scheduler to send '{scheduler_message}' on schedule '{schedulerValue}' every {schedulerIntervalInt} interval at time '{schedulerTime}' on Device:{schedulerInterface} Channel:{schedulerChannel}") - # value can also be 'joke' (interval), 'weather' (time), or 'link' (interval) for special auto messages - elif 'joke' in schedulerValue.lower(): - # Schedule to send a joke every specified interval minutes - schedule.every(schedulerIntervalInt).minutes.do(lambda: send_message(tell_joke(), schedulerChannel, 0, schedulerInterface)) + elif 'joke' in schedulerValue: + schedule.every(schedulerIntervalInt).minutes.do( + partial(send_message, tell_joke(), schedulerChannel, 0, schedulerInterface) + ) logger.debug(f"System: Starting the joke scheduler to send a joke every {schedulerIntervalInt} minutes on Device:{schedulerInterface} Channel:{schedulerChannel}") - elif 'link' in schedulerValue.lower(): - # Schedule to send a link message every specified interval hours - schedule.every(schedulerIntervalInt).hours.do(lambda: send_message(handle_satpass(schedulerInterface, 'link'), schedulerChannel, 0, schedulerInterface)) + elif 'link' in schedulerValue: + schedule.every(schedulerIntervalInt).hours.do( + partial(send_message, handle_satpass(schedulerInterface, 'link'), schedulerChannel, 0, schedulerInterface) + ) logger.debug(f"System: Starting the link scheduler to send link messages every {schedulerIntervalInt} hours on Device:{schedulerInterface} Channel:{schedulerChannel}") - elif 'weather' in schedulerValue.lower(): - # Schedule to send weather updates every specified time every day - schedule.every().day.at(schedulerTime)(lambda: send_message(handle_wxc(0, schedulerInterface, 'wx'), schedulerChannel, 0, schedulerInterface)) + elif 'weather' in schedulerValue: + schedule.every().day.at(schedulerTime).do( + partial(send_message, handle_wxc(0, schedulerInterface, 'wx'), schedulerChannel, 0, schedulerInterface) + ) logger.debug(f"System: Starting the weather scheduler to send weather updates every {schedulerIntervalInt} hours on Device:{schedulerInterface} Channel:{schedulerChannel}") - elif 'custom' in schedulerValue.lower(): - # Import and setup custom schedules from custom_scheduler.py + elif 'custom' in schedulerValue: try: - # This file is located in etc/custom_scheduler.py and copied to modules/custom_scheduler.py at install - from modules.custom_scheduler import setup_custom_schedules # type: ignore # pylance + from modules.custom_scheduler import setup_custom_schedules # type: ignore setup_custom_schedules( send_message, tell_joke, welcome_message, handle_wxc, MOTD, schedulerChannel, schedulerInterface) - logger.debug("System: Custom scheduler file imported and custom schedules set up.") + logger.debug(f"System: Starting the custom_scheduler.py ") + schedule.every().monday.at("12:00").do( + lambda: logger.info("System: Scheduled Broadcast Enabled Reminder") + ) except Exception as e: - logger.debug(f"System: Failed to import custom scheduler. {e}") logger.warning("Custom scheduler file not found or failed to import. cp etc/custom_scheduler.py modules/custom_scheduler.py") except Exception as e: logger.error(f"System: Scheduler Error {e}") - return True - + return True \ No newline at end of file