Simplify logging, formatted with black

feature/plugins-parameters
Geoff Whittington 2023-04-22 20:25:37 -04:00
rodzic 11a2338332
commit 3dc1ad6119
1 zmienionych plików z 72 dodań i 34 usunięć

102
main.py
Wyświetl plik

@ -12,12 +12,20 @@ import certifi
import ssl import ssl
import meshtastic.tcp_interface import meshtastic.tcp_interface
import meshtastic.serial_interface import meshtastic.serial_interface
from nio import AsyncClient, AsyncClientConfig, MatrixRoom, RoomMessageText, RoomAliasEvent, RoomMessageNotice from nio import (
AsyncClient,
AsyncClientConfig,
MatrixRoom,
RoomMessageText,
RoomAliasEvent,
RoomMessageNotice,
)
from pubsub import pub from pubsub import pub
from yaml.loader import SafeLoader from yaml.loader import SafeLoader
from typing import List, Union from typing import List, Union
from datetime import datetime from datetime import datetime
class CustomFormatter(logging.Formatter): class CustomFormatter(logging.Formatter):
def __init__(self, fmt=None, datefmt=None, style="%", converter=None): def __init__(self, fmt=None, datefmt=None, style="%", converter=None):
super().__init__(fmt, datefmt, style) super().__init__(fmt, datefmt, style)
@ -37,31 +45,32 @@ def utc_converter(timestamp, _):
return time.gmtime(timestamp) return time.gmtime(timestamp)
bot_start_time = int(time.time() * 1000) # Timestamp when the bot starts, used to filter out old messages bot_start_time = int(
time.time() * 1000
) # Timestamp when the bot starts, used to filter out old messages
# Load configuration # Load configuration
with open("config.yaml", "r") as f: with open("config.yaml", "r") as f:
relay_config = yaml.load(f, Loader=SafeLoader) relay_config = yaml.load(f, Loader=SafeLoader)
# Configure logging # Configure logging
logger = logging.getLogger(name="MMRELAY") logger = logging.getLogger(name="M<>M Relay")
log_level = getattr(logging, relay_config["logging"]["level"].upper()) log_level = getattr(logging, relay_config["logging"]["level"].upper())
show_timestamps = relay_config["logging"]["show_timestamps"]
timestamp_format = relay_config["logging"]["timestamp_format"]
if show_timestamps:
log_format = f"%(asctime)s %(levelname)s:%(name)s:%(message)s"
else:
log_format = "%(levelname)s:%(name)s:%(message)s"
logger.setLevel(getattr(logging, relay_config["logging"]["level"].upper())) logger.setLevel(log_level)
logger.propagate = False # Add this line to prevent double logging logger.propagate = False # Add this line to prevent double logging
formatter = CustomFormatter(log_format, datefmt=timestamp_format, converter=utc_converter) formatter = CustomFormatter(
fmt=f"%(asctime)s %(levelname)s:%(name)s:%(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
converter=utc_converter,
)
handler = logging.StreamHandler() handler = logging.StreamHandler()
handler.setFormatter(formatter) handler.setFormatter(formatter)
logger.addHandler(handler) logger.addHandler(handler)
# Initialize SQLite database # Initialize SQLite database
def initialize_database(): def initialize_database():
with sqlite3.connect("meshtastic.sqlite") as conn: with sqlite3.connect("meshtastic.sqlite") as conn:
@ -109,7 +118,9 @@ async def join_matrix_room(matrix_client, room_id_or_alias: str) -> None:
if room_id_or_alias.startswith("#"): if room_id_or_alias.startswith("#"):
response = await matrix_client.resolve_room_alias(room_id_or_alias) response = await matrix_client.resolve_room_alias(room_id_or_alias)
if not response.room_id: if not response.room_id:
logger.error(f"Failed to resolve room alias '{room_id_or_alias}': {response.message}") logger.error(
f"Failed to resolve room alias '{room_id_or_alias}': {response.message}"
)
return return
room_id = response.room_id room_id = response.room_id
else: else:
@ -117,15 +128,18 @@ async def join_matrix_room(matrix_client, room_id_or_alias: str) -> None:
if room_id not in matrix_client.rooms: if room_id not in matrix_client.rooms:
response = await matrix_client.join(room_id) response = await matrix_client.join(room_id)
if response and hasattr(response, 'room_id'): if response and hasattr(response, "room_id"):
logger.info(f"Joined room '{room_id_or_alias}' successfully") logger.info(f"Joined room '{room_id_or_alias}' successfully")
else: else:
logger.error(f"Failed to join room '{room_id_or_alias}': {response.message}") logger.error(
f"Failed to join room '{room_id_or_alias}': {response.message}"
)
else: else:
logger.debug(f"Bot is already in room '{room_id_or_alias}'") logger.debug(f"Bot is already in room '{room_id_or_alias}'")
except Exception as e: except Exception as e:
logger.error(f"Error joining room '{room_id_or_alias}': {e}") logger.error(f"Error joining room '{room_id_or_alias}': {e}")
# Initialize Meshtastic interface # Initialize Meshtastic interface
connection_type = relay_config["meshtastic"]["connection_type"] connection_type = relay_config["meshtastic"]["connection_type"]
if connection_type == "serial": if connection_type == "serial":
@ -145,6 +159,7 @@ matrix_access_token = relay_config["matrix"]["access_token"]
bot_user_id = relay_config["matrix"]["bot_user_id"] bot_user_id = relay_config["matrix"]["bot_user_id"]
matrix_rooms: List[dict] = relay_config["matrix_rooms"] matrix_rooms: List[dict] = relay_config["matrix_rooms"]
# Send message to the Matrix room # Send message to the Matrix room
async def matrix_relay(matrix_client, room_id, message, longname, meshnet_name): async def matrix_relay(matrix_client, room_id, message, longname, meshnet_name):
try: try:
@ -197,18 +212,28 @@ def on_meshtastic_message(packet, loop=None):
logger.debug(f"Skipping message from unmapped channel {channel}") logger.debug(f"Skipping message from unmapped channel {channel}")
return return
logger.info(f"Processing inbound radio message from {sender} on channel {channel}") logger.info(
f"Processing inbound radio message from {sender} on channel {channel}"
)
longname = get_longname(sender) or sender longname = get_longname(sender) or sender
meshnet_name = relay_config["meshtastic"]["meshnet_name"] meshnet_name = relay_config["meshtastic"]["meshnet_name"]
formatted_message = f"[{longname}/{meshnet_name}]: {text}" formatted_message = f"[{longname}/{meshnet_name}]: {text}"
logger.info(f"Relaying Meshtastic message from {longname} to Matrix: {formatted_message}") logger.info(
f"Relaying Meshtastic message from {longname} to Matrix: {formatted_message}"
)
for room in matrix_rooms: for room in matrix_rooms:
if room["meshtastic_channel"] == channel: if room["meshtastic_channel"] == channel:
asyncio.run_coroutine_threadsafe( asyncio.run_coroutine_threadsafe(
matrix_relay(matrix_client, room["id"], formatted_message, longname, meshnet_name), matrix_relay(
matrix_client,
room["id"],
formatted_message,
longname,
meshnet_name,
),
loop=loop, loop=loop,
) )
else: else:
@ -223,8 +248,9 @@ def on_meshtastic_message(packet, loop=None):
logger.debug(f"Ignoring Unknown packet") logger.debug(f"Ignoring Unknown packet")
def truncate_message(
def truncate_message(text, max_bytes=234): #234 is the maximum that we can run without an error. Trying it for awhile, otherwise lower this to 230 or less. text, max_bytes=234
): # 234 is the maximum that we can run without an error. Trying it for awhile, otherwise lower this to 230 or less.
""" """
Truncate the given text to fit within the specified byte size. Truncate the given text to fit within the specified byte size.
@ -232,14 +258,14 @@ def truncate_message(text, max_bytes=234): #234 is the maximum that we can run
:param max_bytes: The maximum allowed byte size for the truncated text. :param max_bytes: The maximum allowed byte size for the truncated text.
:return: The truncated text. :return: The truncated text.
""" """
truncated_text = text.encode('utf-8')[:max_bytes].decode('utf-8', 'ignore') truncated_text = text.encode("utf-8")[:max_bytes].decode("utf-8", "ignore")
return truncated_text return truncated_text
# Callback for new messages in Matrix room # Callback for new messages in Matrix room
async def on_room_message(room: MatrixRoom, event: Union[RoomMessageText, RoomMessageNotice]) -> None: async def on_room_message(
room: MatrixRoom, event: Union[RoomMessageText, RoomMessageNotice]
) -> None:
full_display_name = "Unknown user" full_display_name = "Unknown user"
if event.sender != bot_user_id: if event.sender != bot_user_id:
message_timestamp = event.server_timestamp message_timestamp = event.server_timestamp
@ -247,8 +273,8 @@ async def on_room_message(room: MatrixRoom, event: Union[RoomMessageText, RoomMe
if message_timestamp > bot_start_time: if message_timestamp > bot_start_time:
text = event.body.strip() text = event.body.strip()
longname = event.source['content'].get("meshtastic_longname") longname = event.source["content"].get("meshtastic_longname")
meshnet_name = event.source['content'].get("meshtastic_meshnet") meshnet_name = event.source["content"].get("meshtastic_meshnet")
local_meshnet_name = relay_config["meshtastic"]["meshnet_name"] local_meshnet_name = relay_config["meshtastic"]["meshnet_name"]
if longname and meshnet_name: if longname and meshnet_name:
@ -262,11 +288,15 @@ async def on_room_message(room: MatrixRoom, event: Union[RoomMessageText, RoomMe
logger.info(f"Processing message from local meshnet: {text}") logger.info(f"Processing message from local meshnet: {text}")
return return
else: else:
display_name_response = await matrix_client.get_displayname(event.sender) display_name_response = await matrix_client.get_displayname(
event.sender
)
full_display_name = display_name_response.displayname or event.sender full_display_name = display_name_response.displayname or event.sender
short_display_name = full_display_name[:5] short_display_name = full_display_name[:5]
prefix = f"{short_display_name}[M]: " prefix = f"{short_display_name}[M]: "
logger.info(f"Processing matrix message from [{full_display_name}]: {text}") logger.info(
f"Processing matrix message from [{full_display_name}]: {text}"
)
text = truncate_message(text) text = truncate_message(text)
full_message = f"{prefix}{text}" full_message = f"{prefix}{text}"
@ -281,13 +311,16 @@ async def on_room_message(room: MatrixRoom, event: Union[RoomMessageText, RoomMe
meshtastic_channel = room_config["meshtastic_channel"] meshtastic_channel = room_config["meshtastic_channel"]
if relay_config["meshtastic"]["broadcast_enabled"]: if relay_config["meshtastic"]["broadcast_enabled"]:
logger.info(f"Sending radio message from {full_display_name} to radio broadcast") logger.info(
f"Sending radio message from {full_display_name} to radio broadcast"
)
meshtastic_interface.sendText( meshtastic_interface.sendText(
text=full_message, channelIndex=meshtastic_channel text=full_message, channelIndex=meshtastic_channel
) )
else: else:
logger.debug(f"Broadcast not supported: Message from {full_display_name} dropped.") logger.debug(
f"Broadcast not supported: Message from {full_display_name} dropped."
)
async def main(): async def main():
@ -301,7 +334,9 @@ async def main():
# Initialize the Matrix client with custom SSL context # Initialize the Matrix client with custom SSL context
config = AsyncClientConfig(encryption_enabled=False) config = AsyncClientConfig(encryption_enabled=False)
matrix_client = AsyncClient(matrix_homeserver, bot_user_id, config=config, ssl=ssl_context) matrix_client = AsyncClient(
matrix_homeserver, bot_user_id, config=config, ssl=ssl_context
)
matrix_client.access_token = matrix_access_token matrix_client.access_token = matrix_access_token
logger.info("Connecting to Matrix server...") logger.info("Connecting to Matrix server...")
@ -324,7 +359,9 @@ async def main():
# Register the message callback # Register the message callback
logger.info(f"Listening for inbound matrix messages ...") logger.info(f"Listening for inbound matrix messages ...")
matrix_client.add_event_callback(on_room_message, (RoomMessageText, RoomMessageNotice)) matrix_client.add_event_callback(
on_room_message, (RoomMessageText, RoomMessageNotice)
)
# Start the Matrix client # Start the Matrix client
while True: while True:
@ -340,4 +377,5 @@ async def main():
await asyncio.sleep(60) # Update longnames every 60 seconds await asyncio.sleep(60) # Update longnames every 60 seconds
asyncio.run(main()) asyncio.run(main())