From 4d8d33967e572caf28599799b487c249ffac200a Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:27:25 -0700 Subject: [PATCH 1/9] adding tests --- .vscode/settings.json | 11 +++ locationdata.py | 182 ++++++++++++++++++++----------------- locationdata_test.py | 44 +++++++++ mesh-bot.service | 8 +- mesh-bot.py => mesh_bot.py | 0 pong-bot.py => pong_bot.py | 0 requirements.txt | 1 + 7 files changed, 159 insertions(+), 87 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 locationdata_test.py rename mesh-bot.py => mesh_bot.py (100%) mode change 100755 => 100644 rename pong-bot.py => pong_bot.py (100%) mode change 100755 => 100644 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bcbf671 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "python.testing.unittestArgs": [ + "-v", + "-s", + ".", + "-p", + "*test.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} \ No newline at end of file diff --git a/locationdata.py b/locationdata.py index 7919c71..cde633b 100644 --- a/locationdata.py +++ b/locationdata.py @@ -1,6 +1,7 @@ # helper functions to use location data # K7MHI Kelly Keeton 2024 +import json from geopy.geocoders import Nominatim # pip install geopy import maidenhead as mh # pip install maidenhead import requests # pip install requests @@ -8,11 +9,14 @@ import bs4 as bs # pip install beautifulsoup4 URL_TIMEOUT = 10 # wait time for URL requests DAYS_OF_WEATHER = 4 # weather forecast days, the first two rows are today and tonight +# unified error messages to be able to test them from tests +NO_DATA_NOGPS = "no location data: does your device have GPS?" +ERROR_FETCHING_DATA = "error fetching data" def where_am_i(lat=0, lon=0): whereIam = "" if float(lat) == 0 and float(lon) == 0: - return "no location data: does your device have GPS?" + return NO_DATA_NOGPS # initialize Nominatim API geolocator = Nominatim(user_agent="mesh-bot") @@ -28,100 +32,108 @@ def where_am_i(lat=0, lon=0): def get_tide(lat=0, lon=0): station_id = "" if float(lat) == 0 and float(lon) == 0: - return "no location data: does your device have GPS?" + return NO_DATA_NOGPS station_lookup_url = "https://api.tidesandcurrents.noaa.gov/mdapi/prod/webapi/tidepredstations.json?lat=" + str(lat) + "&lon=" + str(lon) + "&radius=50" - station_data = requests.get(station_lookup_url, timeout=URL_TIMEOUT) - if(station_data.ok): - station_json = station_data.json() - # get first station id in 50 mile radius - station_id = station_json['stationList'][0]['stationId'] - else: - return "error fetching station data" + try: + station_data = requests.get(station_lookup_url, timeout=URL_TIMEOUT) + if station_data.ok: + station_json = station_data.json() + else: + return ERROR_FETCHING_DATA + except (requests.exceptions.RequestException, json.JSONDecodeError): + return ERROR_FETCHING_DATA + + station_id = station_json['stationList'][0]['stationId'] station_url = "https://tidesandcurrents.noaa.gov/noaatidepredictions.html?id=" + station_id - station_data = requests.get(station_url, timeout=URL_TIMEOUT) - if(station_data.ok): - # extract table class="table table-condensed" - soup = bs.BeautifulSoup(station_data.text, 'html.parser') - table = soup.find('table', class_='table table-condensed') - # extract rows - rows = table.find_all('tr') - # extract data from rows - tide_data = [] - for row in rows: - row_text = "" - cols = row.find_all('td') - for col in cols: - row_text += col.text + " " - tide_data.append(row_text) - # format tide data into a string - tide_string = "" - for data in tide_data: - tide_string += data + "\n" - # trim off last newline - tide_string = tide_string[:-1] - return tide_string - - else: - return "error fetching tide data" + try: + station_data = requests.get(station_url, timeout=URL_TIMEOUT) + if not station_data.ok: + return ERROR_FETCHING_DATA + except (requests.exceptions.RequestException): + return ERROR_FETCHING_DATA + + # extract table class="table table-condensed" + soup = bs.BeautifulSoup(station_data.text, 'html.parser') + table = soup.find('table', class_='table table-condensed') + + # extract rows + rows = table.find_all('tr') + # extract data from rows + tide_data = [] + for row in rows: + row_text = "" + cols = row.find_all('td') + for col in cols: + row_text += col.text + " " + tide_data.append(row_text) + # format tide data into a string + tide_string = "" + for data in tide_data: + tide_string += data + "\n" + # trim off last newline + tide_string = tide_string[:-1] + return tide_string def get_weather(lat=0, lon=0): weather = "" if float(lat) == 0 and float(lon) == 0: - return "no location data: does your device have GPS?" + return NO_DATA_NOGPS weather_url = "https://forecast.weather.gov/MapClick.php?FcstType=text&lat=" + str(lat) + "&lon=" + str(lon) - weather_data = requests.get(weather_url, timeout=URL_TIMEOUT) - if(weather_data.ok): - soup = bs.BeautifulSoup(weather_data.text, 'html.parser') - table = soup.find('div', id="detailed-forecast-body") - - if table is None: - return "no weather data found on NOAA for your location" - else: - # get rows - rows = table.find_all('div', class_="row") - - # extract data from rows - for row in rows: - # shrink the text - line = row.text.replace("Monday", "Mon ") \ - .replace("Tuesday", "Tue ") \ - .replace("Wednesday", "Wed ") \ - .replace("Thursday", "Thu ") \ - .replace("Friday", "Fri ") \ - .replace("Saturday", "Sat ") \ - .replace("Today", "Today ") \ - .replace("Tonight", "Tonight ") \ - .replace("Tomorrow", "Tomorrow ") \ - .replace("This Afternoon", "Afternoon ") \ - .replace("northwest", "NW") \ - .replace("northeast", "NE") \ - .replace("southwest", "SW") \ - .replace("southeast", "SE") \ - .replace("north", "N") \ - .replace("south", "S") \ - .replace("east", "E") \ - .replace("west", "W") \ - .replace("Northwest", "NW") \ - .replace("Northeast", "NE") \ - .replace("Southwest", "SW") \ - .replace("Southeast", "SE") \ - .replace("North", "N") \ - .replace("South", "S") \ - .replace("East", "E") \ - .replace("West", "W") \ - .replace("precipitation", "precip") \ - .replace("showers", "shwrs") \ - .replace("thunderstorms", "t-storms") - # only grab a few days of weather - if len(weather.split("\n")) < DAYS_OF_WEATHER: - weather += line + "\n" - # trim off last newline - weather = weather[:-1] + try: + weather_data = requests.get(weather_url, timeout=TIMEOUT_DURATION) + if not weather_data.ok: + return ERROR_FETCHING_DATA + except (requests.exceptions.RequestException): + return ERROR_FETCHING_DATA - return weather + soup = bs.BeautifulSoup(weather_data.text, 'html.parser') + table = soup.find('div', id="detailed-forecast-body") + + if table is None: + return "no weather data found on NOAA for your location" else: - return "error fetching weather data" + # get rows + rows = table.find_all('div', class_="row") + # extract data from rows + for row in rows: + # shrink the text + line = row.text.replace("Monday", "Mon ") \ + .replace("Tuesday", "Tue ") \ + .replace("Wednesday", "Wed ") \ + .replace("Thursday", "Thu ") \ + .replace("Friday", "Fri ") \ + .replace("Saturday", "Sat ") \ + .replace("Today", "Today ") \ + .replace("Tonight", "Tonight ") \ + .replace("Tomorrow", "Tomorrow ") \ + .replace("This Afternoon", "Afternoon ") \ + .replace("northwest", "NW") \ + .replace("northeast", "NE") \ + .replace("southwest", "SW") \ + .replace("southeast", "SE") \ + .replace("north", "N") \ + .replace("south", "S") \ + .replace("east", "E") \ + .replace("west", "W") \ + .replace("Northwest", "NW") \ + .replace("Northeast", "NE") \ + .replace("Southwest", "SW") \ + .replace("Southeast", "SE") \ + .replace("North", "N") \ + .replace("South", "S") \ + .replace("East", "E") \ + .replace("West", "W") \ + .replace("precipitation", "precip") \ + .replace("showers", "shwrs") \ + .replace("thunderstorms", "t-storms") + # only grab a few days of weather + if len(weather.split("\n")) < DAYS_OF_WEATHER: + weather += line + "\n" + # trim off last newline + weather = weather[:-1] + + return weather diff --git a/locationdata_test.py b/locationdata_test.py new file mode 100644 index 0000000..6cfa9f7 --- /dev/null +++ b/locationdata_test.py @@ -0,0 +1,44 @@ +import unittest +from locationdata import * + +class TestGetWeather(unittest.TestCase): + + def test_get_weather_with_valid_coordinates(self): + # Test with valid coordinates + lat = "37.7749" + lon = "-122.4194" + weather = get_weather(lat, lon) + print(f"weather: {weather}") + self.assertNotEqual(weather, NO_DATA_NOGPS) + self.assertNotEqual(weather, ERROR_FETCHING_DATA) + + def test_get_weather_with_invalid_coordinates(self): + # Test with invalid coordinates + lat = 0 + lon = 0 + weather = get_weather(lat, lon) + print(f"weather: {weather}") + self.assertEqual(weather, NO_DATA_NOGPS) + + def test_where_am_i_with_valid_coordinates(self): + # Test with invalid coordinates + lat = "37.7749" + lon = "-122.4194" + location = where_am_i(lat, lon) + print(f"location: {location}") + self.assertEqual(location, "South Van Ness Avenue San Francisco California 94103 United States Grid: CM87ss") + self.assertNotEqual(location, NO_DATA_NOGPS) + self.assertNotEqual(location, ERROR_FETCHING_DATA) + + def test_get_tide_with_valid_coordinates(self): + # Test with valid coordinates + lat = "37.7749" + lon = "-122.4194" + tide = get_tide(lat, lon) + print(f"tide: {tide}") + self.assertNotEqual(tide, NO_DATA_NOGPS) + self.assertNotEqual(tide, ERROR_FETCHING_DATA) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/mesh-bot.service b/mesh-bot.service index 6586de6..1c3229f 100644 --- a/mesh-bot.service +++ b/mesh-bot.service @@ -1,16 +1,20 @@ +# /etc/systemd/system/meshbot.service +# sudo systemctl daemon-reload +# sudo systemctl start meshbot.service [Unit] Description=MESH-BOT +After=network.target [Service] -ExecStart=/usr/bin/python /usr/local/meshing-around/mesh-bot.py +ExecStart=/usr/bin/python /usr/local/meshing-around/mesh_bot.py # Disable Python's buffering of STDOUT and STDERR, so that output from the # service shows up immediately in systemd's logs Environment=PYTHONUNBUFFERED=1 Restart=on-failure -Type=notify +Type=notify #try simple if any problems [Install] WantedBy=default.target diff --git a/mesh-bot.py b/mesh_bot.py old mode 100755 new mode 100644 similarity index 100% rename from mesh-bot.py rename to mesh_bot.py diff --git a/pong-bot.py b/pong_bot.py old mode 100755 new mode 100644 similarity index 100% rename from pong-bot.py rename to pong_bot.py diff --git a/requirements.txt b/requirements.txt index 370a21d..52fff42 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ geopy maidenhead beautifulsoup4 dadjokes +mock \ No newline at end of file From 152220b8ed11b13826f2a469af52284050e3e169 Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:38:10 -0700 Subject: [PATCH 2/9] merging from upstream --- locationdata.py | 6 +++--- mesh_bot.py | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/locationdata.py b/locationdata.py index cde633b..93aef9f 100644 --- a/locationdata.py +++ b/locationdata.py @@ -76,13 +76,13 @@ def get_tide(lat=0, lon=0): tide_string = tide_string[:-1] return tide_string -def get_weather(lat=0, lon=0): +def get_weather(lat=0, lon=0, unit=0): weather = "" if float(lat) == 0 and float(lon) == 0: return NO_DATA_NOGPS - weather_url = "https://forecast.weather.gov/MapClick.php?FcstType=text&lat=" + str(lat) + "&lon=" + str(lon) + weather_url = "https://forecast.weather.gov/MapClick.php?FcstType=text&lat=" + str(lat) + "&lon=" + str(lon) + "&unit=" + str(unit) try: - weather_data = requests.get(weather_url, timeout=TIMEOUT_DURATION) + weather_data = requests.get(weather_url, timeout=URL_TIMEOUT) if not weather_data.ok: return ERROR_FETCHING_DATA except (requests.exceptions.RequestException): diff --git a/mesh_bot.py b/mesh_bot.py index 2de83c9..17c1187 100644 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -19,8 +19,8 @@ interface = meshtastic.serial_interface.SerialInterface() #serial interface #interface=meshtastic.ble_interface.BLEInterface("AA:BB:CC:DD:EE:FF") # BLE interface #A list of strings to trap and respond to -trap_list = ("ping","ack","testing","pong","motd","help","sun","solar","hfcond","lheard","sitrep", \ - "whereami","tide","moon","wx","joke","bbslist","bbspost","bbsread","bbsdelete","bbshelp") +trap_list = ("ping", "ack", "testing", "pong", "motd", "help", "sun", "solar", "hfcond", "lheard", "sitrep", \ + "whereami", "tide", "moon", "wx", "wxc", "joke", "bbslist", "bbspost", "bbsread", "bbsdelete", "bbshelp") welcome_message = "MeshBot, here for you like a friend who is not. Try sending: ping @foo or, help" help_message = "Commands are: ack, hfcond, joke, Lheard, moon, motd, ping, solar, sun, tide, whereami, wx, bbshelp" @@ -92,6 +92,10 @@ def auto_response(message, snr, rssi, hop, message_from_id): location = get_node_location(message_from_id) moon = get_moon(str(location[0]),str(location[1])) bot_response = moon + elif "wxc" in message.lower(): + location = get_node_location(message_from_id) + weather = get_weather(str(location[0]),str(location[1]),1) + bot_response = weather elif "wx" in message.lower(): location = get_node_location(message_from_id) weather = get_weather(str(location[0]),str(location[1])) From 3fbc294c8685688317dc58286d7e892a6d5f9745 Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 12:44:47 -0700 Subject: [PATCH 3/9] testing weather replacement funciton so it can be re-worked --- locationdata.py | 21 +++++++++++++-------- locationdata_test.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/locationdata.py b/locationdata.py index 93aef9f..eb667fd 100644 --- a/locationdata.py +++ b/locationdata.py @@ -101,7 +101,17 @@ def get_weather(lat=0, lon=0, unit=0): # extract data from rows for row in rows: # shrink the text - line = row.text.replace("Monday", "Mon ") \ + line = replace_weather(row.text) + # only grab a few days of weather + if len(weather.split("\n")) < DAYS_OF_WEATHER: + weather += line + "\n" + # trim off last newline + weather = weather[:-1] + + return weather + +def replace_weather(row): + line = row.replace("Monday", "Mon ") \ .replace("Tuesday", "Tue ") \ .replace("Wednesday", "Wed ") \ .replace("Thursday", "Thu ") \ @@ -130,10 +140,5 @@ def get_weather(lat=0, lon=0, unit=0): .replace("precipitation", "precip") \ .replace("showers", "shwrs") \ .replace("thunderstorms", "t-storms") - # only grab a few days of weather - if len(weather.split("\n")) < DAYS_OF_WEATHER: - weather += line + "\n" - # trim off last newline - weather = weather[:-1] - - return weather + + return line diff --git a/locationdata_test.py b/locationdata_test.py index 6cfa9f7..ad61735 100644 --- a/locationdata_test.py +++ b/locationdata_test.py @@ -38,7 +38,45 @@ class TestGetWeather(unittest.TestCase): print(f"tide: {tide}") self.assertNotEqual(tide, NO_DATA_NOGPS) self.assertNotEqual(tide, ERROR_FETCHING_DATA) + + def test_replace_weather(self): + # Test replacing days of the week + self.assertEqual(replace_weather("Monday"), "Mon ") + self.assertEqual(replace_weather("Tuesday"), "Tue ") + self.assertEqual(replace_weather("Wednesday"), "Wed ") + self.assertEqual(replace_weather("Thursday"), "Thu ") + self.assertEqual(replace_weather("Friday"), "Fri ") + self.assertEqual(replace_weather("Saturday"), "Sat ") + # Test replacing time periods + self.assertEqual(replace_weather("Today"), "Today ") + self.assertEqual(replace_weather("Tonight"), "Tonight ") + self.assertEqual(replace_weather("Tomorrow"), "Tomorrow ") + self.assertEqual(replace_weather("This Afternoon"), "Afternoon ") + + # Test replacing directions + self.assertEqual(replace_weather("northwest"), "NW") + self.assertEqual(replace_weather("northeast"), "NE") + self.assertEqual(replace_weather("southwest"), "SW") + self.assertEqual(replace_weather("southeast"), "SE") + self.assertEqual(replace_weather("north"), "N") + self.assertEqual(replace_weather("south"), "S") + self.assertEqual(replace_weather("east"), "E") + self.assertEqual(replace_weather("west"), "W") + self.assertEqual(replace_weather("Northwest"), "NW") + self.assertEqual(replace_weather("Northeast"), "NE") + self.assertEqual(replace_weather("Southwest"), "SW") + self.assertEqual(replace_weather("Southeast"), "SE") + self.assertEqual(replace_weather("North"), "N") + self.assertEqual(replace_weather("South"), "S") + self.assertEqual(replace_weather("East"), "E") + self.assertEqual(replace_weather("West"), "W") + + # Test replacing weather terms + self.assertEqual(replace_weather("precipitation"), "precip") + self.assertEqual(replace_weather("showers"), "shwrs") + self.assertEqual(replace_weather("thunderstorms"), "t-storms") + if __name__ == '__main__': unittest.main() \ No newline at end of file From 8ae03b7a09ae0dc18336667e4f343f2c9b2aeeb9 Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 12:47:26 -0700 Subject: [PATCH 4/9] rework replacements --- locationdata.py | 64 +++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/locationdata.py b/locationdata.py index eb667fd..cfba686 100644 --- a/locationdata.py +++ b/locationdata.py @@ -111,34 +111,40 @@ def get_weather(lat=0, lon=0, unit=0): return weather def replace_weather(row): - line = row.replace("Monday", "Mon ") \ - .replace("Tuesday", "Tue ") \ - .replace("Wednesday", "Wed ") \ - .replace("Thursday", "Thu ") \ - .replace("Friday", "Fri ") \ - .replace("Saturday", "Sat ") \ - .replace("Today", "Today ") \ - .replace("Tonight", "Tonight ") \ - .replace("Tomorrow", "Tomorrow ") \ - .replace("This Afternoon", "Afternoon ") \ - .replace("northwest", "NW") \ - .replace("northeast", "NE") \ - .replace("southwest", "SW") \ - .replace("southeast", "SE") \ - .replace("north", "N") \ - .replace("south", "S") \ - .replace("east", "E") \ - .replace("west", "W") \ - .replace("Northwest", "NW") \ - .replace("Northeast", "NE") \ - .replace("Southwest", "SW") \ - .replace("Southeast", "SE") \ - .replace("North", "N") \ - .replace("South", "S") \ - .replace("East", "E") \ - .replace("West", "W") \ - .replace("precipitation", "precip") \ - .replace("showers", "shwrs") \ - .replace("thunderstorms", "t-storms") + replacements = { + "Monday": "Mon ", + "Tuesday": "Tue ", + "Wednesday": "Wed ", + "Thursday": "Thu ", + "Friday": "Fri ", + "Saturday": "Sat ", + "Today": "Today ", + "Tonight": "Tonight ", + "Tomorrow": "Tomorrow ", + "This Afternoon": "Afternoon ", + "northwest": "NW", + "northeast": "NE", + "southwest": "SW", + "southeast": "SE", + "north": "N", + "south": "S", + "east": "E", + "west": "W", + "Northwest": "NW", + "Northeast": "NE", + "Southwest": "SW", + "Southeast": "SE", + "North": "N", + "South": "S", + "East": "E", + "West": "W", + "precipitation": "precip", + "showers": "shwrs", + "thunderstorms": "t-storms" + } + + line = row + for key, value in replacements.items(): + line = line.replace(key, value) return line From d684fb344148c37f8863ddab0e7e82a40b18b6b9 Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 12:51:13 -0700 Subject: [PATCH 5/9] test replacements as part of get_wether --- locationdata_test.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/locationdata_test.py b/locationdata_test.py index ad61735..108372f 100644 --- a/locationdata_test.py +++ b/locationdata_test.py @@ -11,7 +11,26 @@ class TestGetWeather(unittest.TestCase): print(f"weather: {weather}") self.assertNotEqual(weather, NO_DATA_NOGPS) self.assertNotEqual(weather, ERROR_FETCHING_DATA) - + # test replacement works + self.assertNotIn(weather, "Sunday") + self.assertNotIn(weather, "Monday") + self.assertNotIn(weather, "Tuesday") + self.assertNotIn(weather, "Wednesday") + self.assertNotIn(weather, "Thursday") + self.assertNotIn(weather, "Friday") + self.assertNotIn(weather, "Saturday") + self.assertNotIn(weather, "northwest") + self.assertNotIn(weather, "northeast") + self.assertNotIn(weather, "southwest") + self.assertNotIn(weather, "southeast") + self.assertNotIn(weather, "north") + self.assertNotIn(weather, "south") + self.assertNotIn(weather, "east") + self.assertNotIn(weather, "west") + self.assertNotIn(weather, "precipitation") + self.assertNotIn(weather, "showers") + self.assertNotIn(weather, "thunderstorms") + def test_get_weather_with_invalid_coordinates(self): # Test with invalid coordinates lat = 0 From f5692882b404d3bc4c36120ebb2fa656ab0262e8 Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 12:54:43 -0700 Subject: [PATCH 6/9] performance --- mesh_bot.py | 56 +++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/mesh_bot.py b/mesh_bot.py index 17c1187..71da920 100644 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -18,7 +18,7 @@ interface = meshtastic.serial_interface.SerialInterface() #serial interface #interface=meshtastic.tcp_interface.TCPInterface(hostname="192.168.0.1") # IP of your device #interface=meshtastic.ble_interface.BLEInterface("AA:BB:CC:DD:EE:FF") # BLE interface -#A list of strings to trap and respond to +# A list of strings to trap and respond to trap_list = ("ping", "ack", "testing", "pong", "motd", "help", "sun", "solar", "hfcond", "lheard", "sitrep", \ "whereami", "tide", "moon", "wx", "wxc", "joke", "bbslist", "bbspost", "bbsread", "bbsdelete", "bbshelp") @@ -27,7 +27,7 @@ help_message = "Commands are: ack, hfcond, joke, Lheard, moon, motd, ping, solar MOTD = "Thanks for using PongBOT! Have a good day!" # Message of the Day RESPOND_BY_DM_ONLY = True # Set to True to respond messages via DM only (keeps the channel clean) -#Get the node number of the device, check if the device is connected +# Get the node number of the device, check if the device is connected try: myinfo = interface.getMyNodeInfo() myNodeNum = myinfo['num'] @@ -36,9 +36,11 @@ except Exception as e: exit() def auto_response(message, snr, rssi, hop, message_from_id): - #Auto response to messages - if "ping" in message.lower(): - #Check if the user added @foo to the message + # Auto response to messages + # to lower is expensive do it once + message = message.lower() + if "ping" in message: + # Check if the user added @foo to the message if "@" in message: if hop == "Direct": bot_response = "PONG, " + f"SNR:{snr} RSSI:{rssi}" + " and copy: " + message.split("@")[1] @@ -49,17 +51,17 @@ def auto_response(message, snr, rssi, hop, message_from_id): bot_response = "PONG, " + f"SNR:{snr} RSSI:{rssi}" else: bot_response = "PONG, " + hop - elif "ack" in message.lower(): + elif "ack" in message: if hop == "Direct": bot_response = "ACK-ACK! " + f"SNR:{snr} RSSI:{rssi}" else: bot_response = "ACK-ACK! " + hop - elif "testing" in message.lower(): + elif "testing" in message: bot_response = "Testing 1,2,3" - elif "pong" in message.lower(): + elif "pong" in message: bot_response = "PING!!" - elif "motd" in message.lower(): - #check if the user wants to set the motd by using $ + elif "motd" in message: + # check if the user wants to set the motd by using $ if "$" in message: motd = message.split("$")[1] global MOTD @@ -67,44 +69,44 @@ def auto_response(message, snr, rssi, hop, message_from_id): bot_response = "MOTD Set to: " + MOTD else: bot_response = MOTD - elif "bbshelp" in message.lower(): + elif "bbshelp" in message: bot_response = bbs_help() - elif "help" in message.lower(): + elif "help" in message: bot_response = help_message - elif "sun" in message.lower(): + elif "sun" in message: location = get_node_location(message_from_id) bot_response = get_sun(str(location[0]),str(location[1])) - elif "hfcond" in message.lower(): + elif "hfcond" in message: bot_response = hf_band_conditions() - elif "solar" in message.lower(): + elif "solar" in message: bot_response = drap_xray_conditions() + "\n" + solar_conditions() - elif "lheard" in message.lower() or "sitrep" in message.lower(): + elif "lheard" in message or "sitrep" in message: bot_response = "Last 5 nodes heard:\n" + str(get_node_list()) - elif "whereami" in message.lower(): + elif "whereami" in message: location = get_node_location(message_from_id) where = where_am_i(str(location[0]),str(location[1])) bot_response = where - elif "tide" in message.lower(): + elif "tide" in message: location = get_node_location(message_from_id) tide = get_tide(str(location[0]),str(location[1])) bot_response = tide - elif "moon" in message.lower(): + elif "moon" in message: location = get_node_location(message_from_id) moon = get_moon(str(location[0]),str(location[1])) bot_response = moon - elif "wxc" in message.lower(): + elif "wxc" in message: location = get_node_location(message_from_id) weather = get_weather(str(location[0]),str(location[1]),1) bot_response = weather - elif "wx" in message.lower(): + elif "wx" in message: location = get_node_location(message_from_id) weather = get_weather(str(location[0]),str(location[1])) bot_response = weather - elif "joke" in message.lower(): + elif "joke" in message: bot_response = tell_joke() - elif "bbslist" in message.lower(): + elif "bbslist" in message: bot_response = bbs_list_messages() - elif "bbspost" in message.lower(): + elif "bbspost" in message: # Check if the user added a subject to the message if "$" in message: subject = message.split("$")[1].split("#")[0] @@ -113,19 +115,19 @@ def auto_response(message, snr, rssi, hop, message_from_id): message = message.split("#")[1] message = message.rstrip() - bot_response = bbs_post_message(subject,message) + bot_response = bbs_post_message(subject, message) else: bot_response = "example: bbspost $subject #message" else: bot_response = "Please add a subject to the message. ex: bbspost $subject #message" - elif "bbsread" in message.lower(): + elif "bbsread" in message: # Check if the user added a message number to the message if "#" in message: messageID = int(message.split("#")[1]) bot_response = bbs_read_message(messageID) else: bot_response = "Please add a message number ex: bbsread #14" - elif "bbsdelete" in message.lower(): + elif "bbsdelete" in message: # Check if the user added a message number to the message if "#" in message: messageID = int(message.split("#")[1]) From 436d42a72f2fd82b687dc6bcf7aaabf956fc8cbe Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:00:04 -0700 Subject: [PATCH 7/9] performance - not splitting again and again with new line --- locationdata.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/locationdata.py b/locationdata.py index cfba686..38d64cb 100644 --- a/locationdata.py +++ b/locationdata.py @@ -99,12 +99,14 @@ def get_weather(lat=0, lon=0, unit=0): rows = table.find_all('div', class_="row") # extract data from rows - for row in rows: + for index, row in enumerate(rows): # shrink the text line = replace_weather(row.text) # only grab a few days of weather - if len(weather.split("\n")) < DAYS_OF_WEATHER: - weather += line + "\n" + print(f"weather: {index}") + weather += line + "\n" + if index >= DAYS_OF_WEATHER-1: + break # trim off last newline weather = weather[:-1] From 4d92cf83a75d661f98a3c3fe3b8abade06bb9e2a Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:00:38 -0700 Subject: [PATCH 8/9] performance - not splitting again and again with new line --- locationdata.py | 1 - 1 file changed, 1 deletion(-) diff --git a/locationdata.py b/locationdata.py index 38d64cb..44595e7 100644 --- a/locationdata.py +++ b/locationdata.py @@ -103,7 +103,6 @@ def get_weather(lat=0, lon=0, unit=0): # shrink the text line = replace_weather(row.text) # only grab a few days of weather - print(f"weather: {index}") weather += line + "\n" if index >= DAYS_OF_WEATHER-1: break From ea87b035d22a6c59e94f1180e806cea15309908c Mon Sep 17 00:00:00 2001 From: David Bures <12524436+PiDiBi@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:11:56 -0700 Subject: [PATCH 9/9] Revert "performance - not splitting again and again with new line" This reverts commit 4d92cf83a75d661f98a3c3fe3b8abade06bb9e2a. Revert "performance - not splitting again and again with new line" This reverts commit 436d42a72f2fd82b687dc6bcf7aaabf956fc8cbe. Revert "performance" This reverts commit f5692882b404d3bc4c36120ebb2fa656ab0262e8. --- locationdata.py | 7 +++---- mesh_bot.py | 56 ++++++++++++++++++++++++------------------------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/locationdata.py b/locationdata.py index 44595e7..cfba686 100644 --- a/locationdata.py +++ b/locationdata.py @@ -99,13 +99,12 @@ def get_weather(lat=0, lon=0, unit=0): rows = table.find_all('div', class_="row") # extract data from rows - for index, row in enumerate(rows): + for row in rows: # shrink the text line = replace_weather(row.text) # only grab a few days of weather - weather += line + "\n" - if index >= DAYS_OF_WEATHER-1: - break + if len(weather.split("\n")) < DAYS_OF_WEATHER: + weather += line + "\n" # trim off last newline weather = weather[:-1] diff --git a/mesh_bot.py b/mesh_bot.py index 71da920..17c1187 100644 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -18,7 +18,7 @@ interface = meshtastic.serial_interface.SerialInterface() #serial interface #interface=meshtastic.tcp_interface.TCPInterface(hostname="192.168.0.1") # IP of your device #interface=meshtastic.ble_interface.BLEInterface("AA:BB:CC:DD:EE:FF") # BLE interface -# A list of strings to trap and respond to +#A list of strings to trap and respond to trap_list = ("ping", "ack", "testing", "pong", "motd", "help", "sun", "solar", "hfcond", "lheard", "sitrep", \ "whereami", "tide", "moon", "wx", "wxc", "joke", "bbslist", "bbspost", "bbsread", "bbsdelete", "bbshelp") @@ -27,7 +27,7 @@ help_message = "Commands are: ack, hfcond, joke, Lheard, moon, motd, ping, solar MOTD = "Thanks for using PongBOT! Have a good day!" # Message of the Day RESPOND_BY_DM_ONLY = True # Set to True to respond messages via DM only (keeps the channel clean) -# Get the node number of the device, check if the device is connected +#Get the node number of the device, check if the device is connected try: myinfo = interface.getMyNodeInfo() myNodeNum = myinfo['num'] @@ -36,11 +36,9 @@ except Exception as e: exit() def auto_response(message, snr, rssi, hop, message_from_id): - # Auto response to messages - # to lower is expensive do it once - message = message.lower() - if "ping" in message: - # Check if the user added @foo to the message + #Auto response to messages + if "ping" in message.lower(): + #Check if the user added @foo to the message if "@" in message: if hop == "Direct": bot_response = "PONG, " + f"SNR:{snr} RSSI:{rssi}" + " and copy: " + message.split("@")[1] @@ -51,17 +49,17 @@ def auto_response(message, snr, rssi, hop, message_from_id): bot_response = "PONG, " + f"SNR:{snr} RSSI:{rssi}" else: bot_response = "PONG, " + hop - elif "ack" in message: + elif "ack" in message.lower(): if hop == "Direct": bot_response = "ACK-ACK! " + f"SNR:{snr} RSSI:{rssi}" else: bot_response = "ACK-ACK! " + hop - elif "testing" in message: + elif "testing" in message.lower(): bot_response = "Testing 1,2,3" - elif "pong" in message: + elif "pong" in message.lower(): bot_response = "PING!!" - elif "motd" in message: - # check if the user wants to set the motd by using $ + elif "motd" in message.lower(): + #check if the user wants to set the motd by using $ if "$" in message: motd = message.split("$")[1] global MOTD @@ -69,44 +67,44 @@ def auto_response(message, snr, rssi, hop, message_from_id): bot_response = "MOTD Set to: " + MOTD else: bot_response = MOTD - elif "bbshelp" in message: + elif "bbshelp" in message.lower(): bot_response = bbs_help() - elif "help" in message: + elif "help" in message.lower(): bot_response = help_message - elif "sun" in message: + elif "sun" in message.lower(): location = get_node_location(message_from_id) bot_response = get_sun(str(location[0]),str(location[1])) - elif "hfcond" in message: + elif "hfcond" in message.lower(): bot_response = hf_band_conditions() - elif "solar" in message: + elif "solar" in message.lower(): bot_response = drap_xray_conditions() + "\n" + solar_conditions() - elif "lheard" in message or "sitrep" in message: + elif "lheard" in message.lower() or "sitrep" in message.lower(): bot_response = "Last 5 nodes heard:\n" + str(get_node_list()) - elif "whereami" in message: + elif "whereami" in message.lower(): location = get_node_location(message_from_id) where = where_am_i(str(location[0]),str(location[1])) bot_response = where - elif "tide" in message: + elif "tide" in message.lower(): location = get_node_location(message_from_id) tide = get_tide(str(location[0]),str(location[1])) bot_response = tide - elif "moon" in message: + elif "moon" in message.lower(): location = get_node_location(message_from_id) moon = get_moon(str(location[0]),str(location[1])) bot_response = moon - elif "wxc" in message: + elif "wxc" in message.lower(): location = get_node_location(message_from_id) weather = get_weather(str(location[0]),str(location[1]),1) bot_response = weather - elif "wx" in message: + elif "wx" in message.lower(): location = get_node_location(message_from_id) weather = get_weather(str(location[0]),str(location[1])) bot_response = weather - elif "joke" in message: + elif "joke" in message.lower(): bot_response = tell_joke() - elif "bbslist" in message: + elif "bbslist" in message.lower(): bot_response = bbs_list_messages() - elif "bbspost" in message: + elif "bbspost" in message.lower(): # Check if the user added a subject to the message if "$" in message: subject = message.split("$")[1].split("#")[0] @@ -115,19 +113,19 @@ def auto_response(message, snr, rssi, hop, message_from_id): message = message.split("#")[1] message = message.rstrip() - bot_response = bbs_post_message(subject, message) + bot_response = bbs_post_message(subject,message) else: bot_response = "example: bbspost $subject #message" else: bot_response = "Please add a subject to the message. ex: bbspost $subject #message" - elif "bbsread" in message: + elif "bbsread" in message.lower(): # Check if the user added a message number to the message if "#" in message: messageID = int(message.split("#")[1]) bot_response = bbs_read_message(messageID) else: bot_response = "Please add a message number ex: bbsread #14" - elif "bbsdelete" in message: + elif "bbsdelete" in message.lower(): # Check if the user added a message number to the message if "#" in message: messageID = int(message.split("#")[1])