From 2673b638bfb3543b38d6d9d0902e2f05be02b4d4 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 01:42:27 -0700 Subject: [PATCH 01/22] newidea --- config.template | 7 +++++ modules/settings.py | 3 ++ modules/system.py | 68 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/config.template b/config.template index 0e71c2f..adece3e 100644 --- a/config.template +++ b/config.template @@ -89,3 +89,10 @@ signalHoldTime = 10 # the following are combined to reset the monitor signalCooldown = 5 signalCycleLimit = 5 + +[sentry] +sentry_enabled = True +# holdoff time multiplied by minutes(20) of the watchdog +sentry_holdoff = 9 +# channel to send a message to when the watchdog is triggered +secure_channel = 2 \ No newline at end of file diff --git a/modules/settings.py b/modules/settings.py index 30e93c7..ce16957 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -90,6 +90,9 @@ try: signalHoldTime = config['radioMon'].getint('signalHoldTime', 10) # default 10 seconds signalCooldown = config['radioMon'].getint('signalCooldown', 5) # default 1 second signalCycleLimit = config['radioMon'].getint('signalCycleLimit', 5) # default 5 cycles, used with SIGNAL_COOLDOWN + sentry_enabled = config['sentry'].getboolean('enabled', False) + secure_channel = config['sentry'].getint('secure_channel', 2) # default 2 + sentry_holdoff = config['sentry'].getint('holdoff', 9) # default 9 except KeyError as e: print(f"System: Error reading config file: {e}") print(f"System: Check the config.ini against config.template file for missing sections or values.") diff --git a/modules/system.py b/modules/system.py index 02f06a9..04c5a7e 100644 --- a/modules/system.py +++ b/modules/system.py @@ -275,6 +275,50 @@ def get_node_location(number, nodeInt=1, channel=0): else: logger.warning(f"System: No nodes found") return position + +def get_closest_nodes(nodeInt=1): + node_list = [] + if nodeInt == 1: + if interface1.nodes: + for node in interface1.nodes.values(): + if 'position' in node: + try: + latitude = node['position']['latitude'] + longitude = node['position']['longitude'] + except Exception as e: + logger.error(f"System: Error getting location data for {node['id']}. Error: {e}") + node_list.append({'id': node['id'], 'latitude': latitude, 'longitude': longitude}) + # else: + # # request location data + # try: + # logger.debug(f"System: Requesting location data for {node['id']}") + # interface1.sendPosition(destinationId=node['id'], wantResponse=False, channelIndex=publicChannel) + # except Exception as e: + # logger.error(f"System: Error requesting location data for {node['id']}. Error: {e}") + #sort by distance closest to lattitudeValue, longitudeValue + node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) + # return the 3 closest nodes + return node_list[:3] + else: + logger.error(f"System: No nodes found in closest_nodes on interface {nodeInt}") + return ERROR_FETCHING_DATA + if nodeInt == 2: + if interface2.nodes: + for node in interface2.nodes.values(): + if 'position' in node: + try: + latitude = node['position']['latitude'] + longitude = node['position']['longitude'] + except Exception as e: + logger.error(f"System: Error getting location data for {node['id']}. Error: {e}") + node_list.append({'id': node['id'], 'latitude': latitude, 'longitude': longitude}) + #sort by distance closest to lattitudeValue, longitudeValue + node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) + # return the 3 closest nodes + return node_list[:3] + else: + logger.error(f"System: No nodes found in closest_nodes on interface {nodeInt}") + return ERROR_FETCHING_DATA def send_message(message, ch, nodeid=0, nodeInt=1): if message == "": @@ -529,3 +573,27 @@ async def watchdog(): except Exception as e: logger.error(f"System: retrying interface2: {e}") + # Locate Closest Nodes and report them to a secure channel + sentry_enabled = True + secure_channel = 2 + if sentry_enabled: + try: + closest_nodes1 = get_closest_nodes(1) + if closest_nodes1 != ERROR_FETCHING_DATA: + for node in closest_nodes1: + if node is not None: + node_name = get_name_from_number(node['id'], 'long', 1) + send_message(f"{node_name} is close to your location", secure_channel, 0, 1) + logger.warning(f"System: {node_name} {node['id']} is close to your location on Interface1") + + if interface2_enabled: + closest_nodes2 = get_closest_nodes(2) + if closest_nodes2 != ERROR_FETCHING_DATA: + for node in closest_nodes2: + if node is not None: + node_name = get_name_from_number(node['id'], 'long', 2) + send_message(f"{node_name} is close to your location", secure_channel, 0, 2) + logger.warning(f"System: {node_name} {node['id']} is close to your location on Interface2") + except Exception as e: + logger.error(f"System: Sentry Error: {e}") + From 814303c521fbd943199aa0cb38622f3151a3d72a Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 01:47:00 -0700 Subject: [PATCH 02/22] fix --- config.template | 15 +++++++-------- modules/settings.py | 7 ++++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/config.template b/config.template index adece3e..5a972f9 100644 --- a/config.template +++ b/config.template @@ -41,6 +41,12 @@ zuluTime = True URL_TIMEOUT = 10 # logging to file of the non Bot messages LogMessagesToFile = False +# detect anyone close to the bot +SentryEnabled = True +# holdoff time multiplied by minutes(20) of the watchdog +SentryChannel = 9 +# channel to send a message to when the watchdog is triggered +SentryHoldoff = 2 [bbs] enabled = True @@ -88,11 +94,4 @@ signalDetectionThreshold = -10 signalHoldTime = 10 # the following are combined to reset the monitor signalCooldown = 5 -signalCycleLimit = 5 - -[sentry] -sentry_enabled = True -# holdoff time multiplied by minutes(20) of the watchdog -sentry_holdoff = 9 -# channel to send a message to when the watchdog is triggered -secure_channel = 2 \ No newline at end of file +signalCycleLimit = 5 \ No newline at end of file diff --git a/modules/settings.py b/modules/settings.py index ce16957..4288554 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -75,6 +75,9 @@ try: dad_jokes_enabled = config['general'].getboolean('DadJokes', False) store_forward_enabled = config['general'].getboolean('StoreForward', False) log_messages_to_file = config['general'].getboolean('LogMessagesToFile', True) # default True + sentry_enabled = config['general'].getboolean('SentryEnabled', True) # default True + secure_channel = config['general'].getint('SentryChannel', 2) # default 2 + sentry_holdoff = config['general'].getint('SentryHoldoff', 9) # default 9 config['general'].get('motd', MOTD) urlTimeoutSeconds = config['general'].getint('URL_TIMEOUT', 10) # default 10 seconds forecastDuration = config['general'].getint('NOAAforecastDuration', 4) # NOAA forcast days @@ -90,9 +93,7 @@ try: signalHoldTime = config['radioMon'].getint('signalHoldTime', 10) # default 10 seconds signalCooldown = config['radioMon'].getint('signalCooldown', 5) # default 1 second signalCycleLimit = config['radioMon'].getint('signalCycleLimit', 5) # default 5 cycles, used with SIGNAL_COOLDOWN - sentry_enabled = config['sentry'].getboolean('enabled', False) - secure_channel = config['sentry'].getint('secure_channel', 2) # default 2 - sentry_holdoff = config['sentry'].getint('holdoff', 9) # default 9 + except KeyError as e: print(f"System: Error reading config file: {e}") print(f"System: Check the config.ini against config.template file for missing sections or values.") From 07e6042e676a69142db439da478a920c9868a5c8 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 01:55:55 -0700 Subject: [PATCH 03/22] Update system.py --- modules/system.py | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/modules/system.py b/modules/system.py index 04c5a7e..68c927a 100644 --- a/modules/system.py +++ b/modules/system.py @@ -552,6 +552,27 @@ async def watchdog(): logger.error(f"System: communicating with interface1, trying to reconnect: {e}") retry_int1 = True + # Locate Closest Nodes and report them to a secure channel + if sentry_enabled: + try: + closest_nodes1 = get_closest_nodes(1) + if closest_nodes1 != ERROR_FETCHING_DATA: + if closest_nodes1[0]['id'] is not None: + enemySpotted = get_name_from_number(closest_nodes1[0]['id'], 'long', 1) + enemySpotted += ", " + get_name_from_number(closest_nodes1[0]['id'], 'short', 1) + enemySpotted += ", " + str(closest_nodes1[0]['id']) + enemySpotted += ", " + decimal_to_hex(closest_nodes1[0]['id']) + except Exception as e: + logger.error(f"System: Sentry Error: on interface 1 {e}") + + if sentry_loop >= sentry_holdoff and lastSpotted != enemySpotted: + logger.warning(f"System: {enemySpotted} is close to your location on Interface1") + send_message(f"SentryP1: {enemySpotted}", secure_channel, 0, 1) + sentry_loop = 0 + lastSpotted = enemySpotted + else: + sentry_loop += 1 + if retry_int1: try: await retry_interface(1) @@ -573,27 +594,3 @@ async def watchdog(): except Exception as e: logger.error(f"System: retrying interface2: {e}") - # Locate Closest Nodes and report them to a secure channel - sentry_enabled = True - secure_channel = 2 - if sentry_enabled: - try: - closest_nodes1 = get_closest_nodes(1) - if closest_nodes1 != ERROR_FETCHING_DATA: - for node in closest_nodes1: - if node is not None: - node_name = get_name_from_number(node['id'], 'long', 1) - send_message(f"{node_name} is close to your location", secure_channel, 0, 1) - logger.warning(f"System: {node_name} {node['id']} is close to your location on Interface1") - - if interface2_enabled: - closest_nodes2 = get_closest_nodes(2) - if closest_nodes2 != ERROR_FETCHING_DATA: - for node in closest_nodes2: - if node is not None: - node_name = get_name_from_number(node['id'], 'long', 2) - send_message(f"{node_name} is close to your location", secure_channel, 0, 2) - logger.warning(f"System: {node_name} {node['id']} is close to your location on Interface2") - except Exception as e: - logger.error(f"System: Sentry Error: {e}") - From 7b8779fc4857587587daddefd7b3d412a9334671 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 01:58:39 -0700 Subject: [PATCH 04/22] Update system.py --- modules/system.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/system.py b/modules/system.py index 68c927a..9f18e93 100644 --- a/modules/system.py +++ b/modules/system.py @@ -539,6 +539,8 @@ def suppress_stdout(): async def watchdog(): global retry_int1, retry_int2 + sentry_loop = 0 + lastSpotted = "" # watchdog for connection to the interface while True: await asyncio.sleep(20) From 9efbbb4f2023b8cbe9c5dd2c716bd6ed4217c8cd Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 02:00:24 -0700 Subject: [PATCH 05/22] Update system.py --- modules/system.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/system.py b/modules/system.py index 9f18e93..cf5a1a1 100644 --- a/modules/system.py +++ b/modules/system.py @@ -565,7 +565,7 @@ async def watchdog(): enemySpotted += ", " + str(closest_nodes1[0]['id']) enemySpotted += ", " + decimal_to_hex(closest_nodes1[0]['id']) except Exception as e: - logger.error(f"System: Sentry Error: on interface 1 {e}") + pass if sentry_loop >= sentry_holdoff and lastSpotted != enemySpotted: logger.warning(f"System: {enemySpotted} is close to your location on Interface1") From 98b9e0471cc98b0ad8fe9ec9ddcbef3ab01f0b9e Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 02:00:39 -0700 Subject: [PATCH 06/22] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c30a855..8233085 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Along with network testing, this bot has a lot of other features, like simple ma The bot is also capable of using dual radio/nodes, so you can monitor two networks at the same time and send messages to nodes using the same `bbspost @nodeNumber #message` function. There is a small message board to fit in the constraints of Meshtastic for posting bulletin messages with `bbspost $subject #message`. +The bot will report on anyone who is getting close to the device if in a remote location. + Store and forward-like message re-play with `messages`, and there is a repeater module for dual radio bots to cross post messages. Messages are also logged locally to disk. The bot can also be used to monitor a frequency and let you know when activity is seen. Using Hamlib to watch the S meter on a connected radio. You can send alerts to channels when a frequency is detected for 20 seconds within the thresholds set in config.ini @@ -97,6 +99,9 @@ enabled = False [general] DadJokes = False StoreForward = False + +# detect and report the closest to the bot +SentryEnabled = False ``` The BBS has admin and block lists; see the [config.template](config.template) From be32fd4a176410737a7f4e199537f66e3c34d2a4 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 02:04:21 -0700 Subject: [PATCH 07/22] Update system.py --- modules/system.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/modules/system.py b/modules/system.py index cf5a1a1..a8754cd 100644 --- a/modules/system.py +++ b/modules/system.py @@ -541,6 +541,8 @@ async def watchdog(): global retry_int1, retry_int2 sentry_loop = 0 lastSpotted = "" + sentry_loop2 = 0 + lastSpotted2 = "" # watchdog for connection to the interface while True: await asyncio.sleep(20) @@ -589,6 +591,27 @@ async def watchdog(): except Exception as e: logger.error(f"System: communicating with interface2, trying to reconnect: {e}") retry_int2 = True + + # Locate Closest Nodes and report them to a secure channel + if sentry_enabled: + try: + closest_nodes2 = get_closest_nodes(2) + if closest_nodes2 != ERROR_FETCHING_DATA: + if closest_nodes2[0]['id'] is not None: + enemySpotted2 = get_name_from_number(closest_nodes2[0]['id'], 'long', 2) + enemySpotted2 += ", " + get_name_from_number(closest_nodes2[0]['id'], 'short', 2) + enemySpotted2 += ", " + str(closest_nodes2[0]['id']) + enemySpotted2 += ", " + decimal_to_hex(closest_nodes2[0]['id']) + except Exception as e: + pass + + if sentry_loop2 >= sentry_holdoff and lastSpotted2 != enemySpotted2: + logger.warning(f"System: {enemySpotted2} is close to your location on Interface2") + send_message(f"SentryP2: {enemySpotted2}", secure_channel, 0, 2) + sentry_loop2 = 0 + lastSpotted2 = enemySpotted2 + else: + sentry_loop2 += 1 if retry_int2: try: From cfbda17cfbc8c9feb031bc4859cc7382848ac6e6 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 02:06:52 -0700 Subject: [PATCH 08/22] Update system.py --- modules/system.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/system.py b/modules/system.py index a8754cd..c11ffb0 100644 --- a/modules/system.py +++ b/modules/system.py @@ -539,10 +539,13 @@ def suppress_stdout(): async def watchdog(): global retry_int1, retry_int2 - sentry_loop = 0 - lastSpotted = "" - sentry_loop2 = 0 - lastSpotted2 = "" + if sentry_enabled: + sentry_loop = 0 + lastSpotted = "" + enemySpotted = "" + sentry_loop2 = 0 + lastSpotted2 = "" + enemySpotted2 = "" # watchdog for connection to the interface while True: await asyncio.sleep(20) From c48851719a68d99a8824554869236495588bbd7f Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 02:53:13 -0700 Subject: [PATCH 09/22] Update system.py --- modules/system.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/system.py b/modules/system.py index c11ffb0..9ded459 100644 --- a/modules/system.py +++ b/modules/system.py @@ -285,9 +285,10 @@ def get_closest_nodes(nodeInt=1): try: latitude = node['position']['latitude'] longitude = node['position']['longitude'] + nodeID = node['num'] + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: - logger.error(f"System: Error getting location data for {node['id']}. Error: {e}") - node_list.append({'id': node['id'], 'latitude': latitude, 'longitude': longitude}) + pass # else: # # request location data # try: @@ -309,9 +310,11 @@ def get_closest_nodes(nodeInt=1): try: latitude = node['position']['latitude'] longitude = node['position']['longitude'] + nodeID = node['num'] + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: - logger.error(f"System: Error getting location data for {node['id']}. Error: {e}") - node_list.append({'id': node['id'], 'latitude': latitude, 'longitude': longitude}) + pass + #sort by distance closest to lattitudeValue, longitudeValue node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) # return the 3 closest nodes From 67af1ba39eb37aa7d08b18ece3558cc4462bcbc1 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 02:57:52 -0700 Subject: [PATCH 10/22] sentry notification --- mesh_bot.py | 2 ++ pong_bot.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mesh_bot.py b/mesh_bot.py index 4e9429d..e53e6c1 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -351,6 +351,8 @@ async def start_rx(): logger.debug(f"System: Location Telemetry Enabled using NOAA API") if dad_jokes_enabled: logger.debug(f"System: Dad Jokes Enabled!") + if sentry_enabled: + logger.debug(f"System: Sentry Mode Enabled") if store_forward_enabled: logger.debug(f"System: Store and Forward Enabled using limit: {storeFlimit}") if useDMForResponse: diff --git a/pong_bot.py b/pong_bot.py index 9f8b32e..4804c50 100755 --- a/pong_bot.py +++ b/pong_bot.py @@ -221,6 +221,8 @@ async def start_rx(): f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}") if log_messages_to_file: logger.debug(f"System: Logging Messages to disk") + if sentry_enabled: + logger.debug(f"System: Sentry Enabled") if store_forward_enabled: logger.debug(f"System: Store and Forward Enabled using limit: {storeFlimit}") if useDMForResponse: From c1b493b7c762da6c5ef278a9b4f0cbc4c6f93bb0 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 03:35:43 -0700 Subject: [PATCH 11/22] Update system.py --- modules/system.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/system.py b/modules/system.py index 9ded459..1afe67b 100644 --- a/modules/system.py +++ b/modules/system.py @@ -56,6 +56,10 @@ if dad_jokes_enabled: trap_list = trap_list + ("joke",) help_message = help_message + ", joke" +if sentry_enabled: + from math import sqrt + radius = 1.00 # in kilometer + # Store and Forward Configuration if store_forward_enabled: trap_list = trap_list + ("messages",) @@ -286,7 +290,12 @@ def get_closest_nodes(nodeInt=1): latitude = node['position']['latitude'] longitude = node['position']['longitude'] nodeID = node['num'] - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + # set radius around lattitudeValue, longitudeValue position + a = latitudeValue - latitude + b = longitudeValue - longitude + c = sqrt(a * a + b * b) + if (c < radius): + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass # else: @@ -298,6 +307,7 @@ def get_closest_nodes(nodeInt=1): # logger.error(f"System: Error requesting location data for {node['id']}. Error: {e}") #sort by distance closest to lattitudeValue, longitudeValue node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) + # return the 3 closest nodes return node_list[:3] else: @@ -311,12 +321,18 @@ def get_closest_nodes(nodeInt=1): latitude = node['position']['latitude'] longitude = node['position']['longitude'] nodeID = node['num'] - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + # set radius around lattitudeValue, longitudeValue position + a = latitudeValue - latitude + b = longitudeValue - longitude + c = sqrt(a * a + b * b) + if (c < radius): + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass #sort by distance closest to lattitudeValue, longitudeValue node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) + # return the 3 closest nodes return node_list[:3] else: From 72f049452b5a036e57116d868e1c019868c6830a Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 11:51:50 -0700 Subject: [PATCH 12/22] fix depends --- README.md | 1 + modules/wx_meteo.py | 2 +- requirements.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8233085..1237fe3 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ pip install maidenhead pip install beautifulsoup4 pip install dadjokes pip install openmeteo_requests +pip install retry_requests ``` To enable emoji in the Debian console, install the fonts `sudo apt-get install fonts-noto-color-emoji` diff --git a/modules/wx_meteo.py b/modules/wx_meteo.py index f89f1fb..88d04c5 100644 --- a/modules/wx_meteo.py +++ b/modules/wx_meteo.py @@ -1,5 +1,5 @@ import openmeteo_requests # pip install openmeteo-requests -from retry_requests import retry +from retry_requests import retry # pip install retry-requests #import requests_cache from modules.log import * diff --git a/requirements.txt b/requirements.txt index cd19afd..e68cce2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ maidenhead beautifulsoup4 dadjokes openmeteo_requests +retry_requests From 066f7edfd965f231c56cd75a253fd0c138040f1b Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 11:52:13 -0700 Subject: [PATCH 13/22] Revert "fix depends" This reverts commit 72f049452b5a036e57116d868e1c019868c6830a. --- README.md | 1 - modules/wx_meteo.py | 2 +- requirements.txt | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 1237fe3..8233085 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,6 @@ pip install maidenhead pip install beautifulsoup4 pip install dadjokes pip install openmeteo_requests -pip install retry_requests ``` To enable emoji in the Debian console, install the fonts `sudo apt-get install fonts-noto-color-emoji` diff --git a/modules/wx_meteo.py b/modules/wx_meteo.py index 88d04c5..f89f1fb 100644 --- a/modules/wx_meteo.py +++ b/modules/wx_meteo.py @@ -1,5 +1,5 @@ import openmeteo_requests # pip install openmeteo-requests -from retry_requests import retry # pip install retry-requests +from retry_requests import retry #import requests_cache from modules.log import * diff --git a/requirements.txt b/requirements.txt index e68cce2..cd19afd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,3 @@ maidenhead beautifulsoup4 dadjokes openmeteo_requests -retry_requests From 66d44c3a6da8b43b40035d42b3e4a3403121fc3c Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 12:21:55 -0700 Subject: [PATCH 14/22] ignorelist --- config.template | 2 ++ modules/settings.py | 1 + modules/system.py | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/config.template b/config.template index 5a972f9..af28afc 100644 --- a/config.template +++ b/config.template @@ -47,6 +47,8 @@ SentryEnabled = True SentryChannel = 9 # channel to send a message to when the watchdog is triggered SentryHoldoff = 2 +# list of ignored nodes numbers ex: 2813308004,4258675309 +sentryIgnoreList = [bbs] enabled = True diff --git a/modules/settings.py b/modules/settings.py index 4288554..774d49c 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -78,6 +78,7 @@ try: sentry_enabled = config['general'].getboolean('SentryEnabled', True) # default True secure_channel = config['general'].getint('SentryChannel', 2) # default 2 sentry_holdoff = config['general'].getint('SentryHoldoff', 9) # default 9 + sentryIgnoreList = config['general'].get('sentryIgnoreList', '').split(',') config['general'].get('motd', MOTD) urlTimeoutSeconds = config['general'].getint('URL_TIMEOUT', 10) # default 10 seconds forecastDuration = config['general'].getint('NOAAforecastDuration', 4) # NOAA forcast days diff --git a/modules/system.py b/modules/system.py index 1afe67b..cc2a745 100644 --- a/modules/system.py +++ b/modules/system.py @@ -295,7 +295,8 @@ def get_closest_nodes(nodeInt=1): b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + if nodeID != myNodeNum1 and nodeID not in sentryIgnoreList: + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass # else: @@ -326,7 +327,8 @@ def get_closest_nodes(nodeInt=1): b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + if nodeID != myNodeNum2 and nodeID not in sentryIgnoreList: + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass From 0e97953adf2ba19e3393a251de5de768478cadf0 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 12:32:17 -0700 Subject: [PATCH 15/22] Update system.py --- modules/system.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/system.py b/modules/system.py index cc2a745..146ed77 100644 --- a/modules/system.py +++ b/modules/system.py @@ -295,8 +295,8 @@ def get_closest_nodes(nodeInt=1): b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - if nodeID != myNodeNum1 and nodeID not in sentryIgnoreList: - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + if nodeID != myNodeNum1 and nodeID not in sentryIgnoreList: + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass # else: @@ -327,8 +327,8 @@ def get_closest_nodes(nodeInt=1): b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - if nodeID != myNodeNum2 and nodeID not in sentryIgnoreList: - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + if nodeID != myNodeNum2 and nodeID not in sentryIgnoreList: + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass From 27ece919d7408d1bd36dd006283dec03707aaaf4 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 12:41:29 -0700 Subject: [PATCH 16/22] Update system.py --- modules/system.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/system.py b/modules/system.py index 146ed77..8f5d8d9 100644 --- a/modules/system.py +++ b/modules/system.py @@ -295,7 +295,7 @@ def get_closest_nodes(nodeInt=1): b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - if nodeID != myNodeNum1 and nodeID not in sentryIgnoreList: + if nodeID != myNodeNum1 and str(nodeID) not in sentryIgnoreList: node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass @@ -327,7 +327,7 @@ def get_closest_nodes(nodeInt=1): b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - if nodeID != myNodeNum2 and nodeID not in sentryIgnoreList: + if nodeID != myNodeNum2 and str(nodeID) not in sentryIgnoreList: node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass From 9f658fc0609fbf4ec20bf9da82e80687907ff6a6 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 8 Aug 2024 22:52:04 -0700 Subject: [PATCH 17/22] Update wx_meteo.py --- modules/wx_meteo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/wx_meteo.py b/modules/wx_meteo.py index 88d04c5..af65088 100644 --- a/modules/wx_meteo.py +++ b/modules/wx_meteo.py @@ -1,5 +1,5 @@ import openmeteo_requests # pip install openmeteo-requests -from retry_requests import retry # pip install retry-requests +from retry_requests import retry # pip install retry_requests #import requests_cache from modules.log import * From 91f11e4828b19f665696d888fd6fb8dd50185475 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sat, 10 Aug 2024 00:17:24 -0700 Subject: [PATCH 18/22] enhance --- modules/settings.py | 1 + modules/system.py | 19 +++++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/settings.py b/modules/settings.py index 774d49c..b7343f3 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -22,6 +22,7 @@ max_retry_count1 = 4 # max retry count for interface 1 max_retry_count2 = 4 # max retry count for interface 2 retry_int1 = False retry_int2 = False +radius = 0.10 # in kilometer for sentry detection # Read the config file, if it does not exist, create basic config file config = configparser.ConfigParser() diff --git a/modules/system.py b/modules/system.py index 9b2d2d2..1ffacc1 100644 --- a/modules/system.py +++ b/modules/system.py @@ -58,7 +58,6 @@ if dad_jokes_enabled: if sentry_enabled: from math import sqrt - radius = 1.00 # in kilometer # Store and Forward Configuration if store_forward_enabled: @@ -293,22 +292,22 @@ def get_node_location(number, nodeInt=1, channel=0): logger.warning(f"System: No nodes found") return position -def get_closest_nodes(nodeInt=1): +def get_closest_nodes(nodeInt=1,returnCount=3): node_list = [] if nodeInt == 1: if interface1.nodes: for node in interface1.nodes.values(): if 'position' in node: try: + nodeID = node['num'] latitude = node['position']['latitude'] longitude = node['position']['longitude'] - nodeID = node['num'] # set radius around lattitudeValue, longitudeValue position a = latitudeValue - latitude b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - if nodeID != myNodeNum1 and str(nodeID) not in sentryIgnoreList: + if nodeID != myNodeNum1 and myNodeNum2 and str(nodeID) not in sentryIgnoreList: node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass @@ -322,8 +321,8 @@ def get_closest_nodes(nodeInt=1): #sort by distance closest to lattitudeValue, longitudeValue node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) - # return the 3 closest nodes - return node_list[:3] + # return the first 3 closest nodes by default + return node_list[:returnCount] else: logger.error(f"System: No nodes found in closest_nodes on interface {nodeInt}") return ERROR_FETCHING_DATA @@ -332,15 +331,15 @@ def get_closest_nodes(nodeInt=1): for node in interface2.nodes.values(): if 'position' in node: try: + nodeID = node['num'] latitude = node['position']['latitude'] longitude = node['position']['longitude'] - nodeID = node['num'] # set radius around lattitudeValue, longitudeValue position a = latitudeValue - latitude b = longitudeValue - longitude c = sqrt(a * a + b * b) if (c < radius): - if nodeID != myNodeNum2 and str(nodeID) not in sentryIgnoreList: + if nodeID != myNodeNum1 and myNodeNum2 and str(nodeID) not in sentryIgnoreList: node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) except Exception as e: pass @@ -348,8 +347,8 @@ def get_closest_nodes(nodeInt=1): #sort by distance closest to lattitudeValue, longitudeValue node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) - # return the 3 closest nodes - return node_list[:3] + # return the first 3 closest nodes by default + return node_list[:returnCount] else: logger.error(f"System: No nodes found in closest_nodes on interface {nodeInt}") return ERROR_FETCHING_DATA From 1e921dd5ea28bca0fefe5880fa81c29d288b7a62 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sat, 10 Aug 2024 01:48:12 -0700 Subject: [PATCH 19/22] geopy tired of maths --- README.md | 1 + modules/settings.py | 2 +- modules/system.py | 38 ++++++++++++++++++++++---------------- requirements.txt | 3 ++- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 9ac8a29..3e51b3f 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ pip install geopy pip install maidenhead pip install beautifulsoup4 pip install dadjokes +pip install geopy ``` The following is needed for open-meteo use ``` diff --git a/modules/settings.py b/modules/settings.py index b7343f3..f8a3f92 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -22,7 +22,7 @@ max_retry_count1 = 4 # max retry count for interface 1 max_retry_count2 = 4 # max retry count for interface 2 retry_int1 = False retry_int2 = False -radius = 0.10 # in kilometer for sentry detection +radius = 100 # radius for sentry alerts in meters # Read the config file, if it does not exist, create basic config file config = configparser.ConfigParser() diff --git a/modules/system.py b/modules/system.py index 1ffacc1..4a4981a 100644 --- a/modules/system.py +++ b/modules/system.py @@ -58,6 +58,7 @@ if dad_jokes_enabled: if sentry_enabled: from math import sqrt + import geopy.distance # pip install geopy # Store and Forward Configuration if store_forward_enabled: @@ -302,13 +303,15 @@ def get_closest_nodes(nodeInt=1,returnCount=3): nodeID = node['num'] latitude = node['position']['latitude'] longitude = node['position']['longitude'] - # set radius around lattitudeValue, longitudeValue position - a = latitudeValue - latitude - b = longitudeValue - longitude - c = sqrt(a * a + b * b) - if (c < radius): + + # set radius around BOT position + distance = round(geopy.distance.geodesic((latitudeValue, longitudeValue), (latitude, longitude)).m, 2) + + if (distance < radius): if nodeID != myNodeNum1 and myNodeNum2 and str(nodeID) not in sentryIgnoreList: - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude, 'distance': distance}) + # calculate distance to node and report + except Exception as e: pass # else: @@ -318,9 +321,9 @@ def get_closest_nodes(nodeInt=1,returnCount=3): # interface1.sendPosition(destinationId=node['id'], wantResponse=False, channelIndex=publicChannel) # except Exception as e: # logger.error(f"System: Error requesting location data for {node['id']}. Error: {e}") + #sort by distance closest to lattitudeValue, longitudeValue node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) - # return the first 3 closest nodes by default return node_list[:returnCount] else: @@ -334,13 +337,15 @@ def get_closest_nodes(nodeInt=1,returnCount=3): nodeID = node['num'] latitude = node['position']['latitude'] longitude = node['position']['longitude'] - # set radius around lattitudeValue, longitudeValue position - a = latitudeValue - latitude - b = longitudeValue - longitude - c = sqrt(a * a + b * b) - if (c < radius): + + # set radius around BOT position + distance = geopy.distance.geodesic((latitudeValue, longitudeValue), (latitude, longitude)).m + + if (distance < radius): if nodeID != myNodeNum1 and myNodeNum2 and str(nodeID) not in sentryIgnoreList: - node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude}) + node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude, 'distance': distance}) + # calculate distance to node and report + except Exception as e: pass @@ -602,12 +607,13 @@ async def watchdog(): enemySpotted += ", " + get_name_from_number(closest_nodes1[0]['id'], 'short', 1) enemySpotted += ", " + str(closest_nodes1[0]['id']) enemySpotted += ", " + decimal_to_hex(closest_nodes1[0]['id']) + enemySpotted += f" at {closest_nodes1[0]['distance']}m" except Exception as e: pass if sentry_loop >= sentry_holdoff and lastSpotted != enemySpotted: logger.warning(f"System: {enemySpotted} is close to your location on Interface1") - send_message(f"SentryP1: {enemySpotted}", secure_channel, 0, 1) + send_message(f"Sentry1: {enemySpotted}", secure_channel, 0, 1) sentry_loop = 0 lastSpotted = enemySpotted else: @@ -638,12 +644,13 @@ async def watchdog(): enemySpotted2 += ", " + get_name_from_number(closest_nodes2[0]['id'], 'short', 2) enemySpotted2 += ", " + str(closest_nodes2[0]['id']) enemySpotted2 += ", " + decimal_to_hex(closest_nodes2[0]['id']) + enemySpotted += f" at {closest_nodes1[0]['distance']}m" except Exception as e: pass if sentry_loop2 >= sentry_holdoff and lastSpotted2 != enemySpotted2: logger.warning(f"System: {enemySpotted2} is close to your location on Interface2") - send_message(f"SentryP2: {enemySpotted2}", secure_channel, 0, 2) + send_message(f"Sentry2: {enemySpotted2}", secure_channel, 0, 2) sentry_loop2 = 0 lastSpotted2 = enemySpotted2 else: @@ -654,4 +661,3 @@ async def watchdog(): await retry_interface(2) except Exception as e: logger.error(f"System: retrying interface2: {e}") - diff --git a/requirements.txt b/requirements.txt index c6b205a..dd20ae8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ beautifulsoup4 dadjokes openmeteo_requests retry_requests -numpy \ No newline at end of file +numpy +geopy \ No newline at end of file From 9e205155a50acdfd0b38c3a61dfc64c63c6ad98e Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sat, 10 Aug 2024 09:58:30 -0700 Subject: [PATCH 20/22] Update system.py --- modules/system.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/system.py b/modules/system.py index 4a4981a..c610df8 100644 --- a/modules/system.py +++ b/modules/system.py @@ -322,8 +322,9 @@ def get_closest_nodes(nodeInt=1,returnCount=3): # except Exception as e: # logger.error(f"System: Error requesting location data for {node['id']}. Error: {e}") - #sort by distance closest to lattitudeValue, longitudeValue - node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) + # sort by distance closest + #node_list.sort(key=lambda x: (x['latitude']-latitudeValue)**2 + (x['longitude']-longitudeValue)**2) + node_list.sort(key=lambda x: x['distance']) # return the first 3 closest nodes by default return node_list[:returnCount] else: From 28514adf007cfb4ad8d9a43cd45fbc95f720d62b Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sun, 11 Aug 2024 23:02:19 -0700 Subject: [PATCH 21/22] enhance --- README.md | 14 +++++++++++--- config.template | 2 ++ modules/settings.py | 2 +- modules/system.py | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3e51b3f..add0c92 100644 --- a/README.md +++ b/README.md @@ -99,9 +99,17 @@ enabled = False [general] DadJokes = False StoreForward = False - -# detect and report the closest to the bot -SentryEnabled = False +``` +Sentry Bot detects anyone comeing close to the bot-node +``` +# detect anyone close to the bot +SentryEnabled = True +# holdoff time multiplied by minutes(20) of the watchdog +SentryChannel = 9 +# channel to send a message to when the watchdog is triggered +SentryHoldoff = 2 +# list of ignored nodes numbers ex: 2813308004,4258675309 +sentryIgnoreList = ``` The BBS has admin and block lists; see the [config.template](config.template) diff --git a/config.template b/config.template index af28afc..a8476cd 100644 --- a/config.template +++ b/config.template @@ -43,6 +43,8 @@ URL_TIMEOUT = 10 LogMessagesToFile = False # detect anyone close to the bot SentryEnabled = True +# radius in meters to detect someone close to the bot +SentryRadius = 100 # holdoff time multiplied by minutes(20) of the watchdog SentryChannel = 9 # channel to send a message to when the watchdog is triggered diff --git a/modules/settings.py b/modules/settings.py index f8a3f92..a79ef43 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -22,7 +22,6 @@ max_retry_count1 = 4 # max retry count for interface 1 max_retry_count2 = 4 # max retry count for interface 2 retry_int1 = False retry_int2 = False -radius = 100 # radius for sentry alerts in meters # Read the config file, if it does not exist, create basic config file config = configparser.ConfigParser() @@ -80,6 +79,7 @@ try: secure_channel = config['general'].getint('SentryChannel', 2) # default 2 sentry_holdoff = config['general'].getint('SentryHoldoff', 9) # default 9 sentryIgnoreList = config['general'].get('sentryIgnoreList', '').split(',') + sentry_radius = config['general'].getint('SentryRadius', 100) # default 100 meters config['general'].get('motd', MOTD) urlTimeoutSeconds = config['general'].getint('URL_TIMEOUT', 10) # default 10 seconds forecastDuration = config['general'].getint('NOAAforecastDuration', 4) # NOAA forcast days diff --git a/modules/system.py b/modules/system.py index c610df8..402a341 100644 --- a/modules/system.py +++ b/modules/system.py @@ -307,7 +307,7 @@ def get_closest_nodes(nodeInt=1,returnCount=3): # set radius around BOT position distance = round(geopy.distance.geodesic((latitudeValue, longitudeValue), (latitude, longitude)).m, 2) - if (distance < radius): + if (distance < sentry_radius): if nodeID != myNodeNum1 and myNodeNum2 and str(nodeID) not in sentryIgnoreList: node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude, 'distance': distance}) # calculate distance to node and report @@ -342,7 +342,7 @@ def get_closest_nodes(nodeInt=1,returnCount=3): # set radius around BOT position distance = geopy.distance.geodesic((latitudeValue, longitudeValue), (latitude, longitude)).m - if (distance < radius): + if (distance < sentry_radius): if nodeID != myNodeNum1 and myNodeNum2 and str(nodeID) not in sentryIgnoreList: node_list.append({'id': nodeID, 'latitude': latitude, 'longitude': longitude, 'distance': distance}) # calculate distance to node and report From d8e5cb7893b943a4fd05c9be0a19fe419c8aa03e Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sun, 11 Aug 2024 23:03:48 -0700 Subject: [PATCH 22/22] Update config.template --- config.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.template b/config.template index a8476cd..85d4bcd 100644 --- a/config.template +++ b/config.template @@ -98,4 +98,4 @@ signalDetectionThreshold = -10 signalHoldTime = 10 # the following are combined to reset the monitor signalCooldown = 5 -signalCycleLimit = 5 \ No newline at end of file +signalCycleLimit = 5