diff --git a/README.md b/README.md index 7bfcd26..9e2ba06 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,9 @@ How to use: -python main.py -d -j from@server.com -t to@server.com -m "test" -p supersecretpass - +```bash +python3 -m venv venv +source venv/bin/activate +pip install -r requirements.txt +python main.py +``` diff --git a/main.py b/main.py index 25a3995..0753716 100644 --- a/main.py +++ b/main.py @@ -1,102 +1,77 @@ -#!/usr/bin/env python3 +import time +import os +import meshtastic +import meshtastic.tcp_interface +from pubsub import pub +from send_to_irc import SendMsgBot -import logging -from getpass import getpass -from argparse import ArgumentParser +MESSAGE_FILE = "message.txt" -import slixmpp -# Mostly a carbon copy of https://slixmpp.readthedocs.io/en/latest/getting_started/sendlogout.html but will have other options. +def send_message_from_mesh(): + if os.path.exists(MESSAGE_FILE): + with open(MESSAGE_FILE, 'r') as file: + message = file.read().strip() + + if message: + # If you dont have irc...then you can just print/hook into your service here. + xmpp = SendMsgBot('mesh_bot@website.com', 'totallyrealpassword', 'accounttosend@website.com', message) + xmpp.register_plugin('xep_0030') # Service Discovery + xmpp.register_plugin('xep_0199') # XMPP Ping + + # Connect to the XMPP server and start processing XMPP stanzas. + xmpp.connect() + xmpp.process(forever=False) + + # Clear the file after sending the message + open(MESSAGE_FILE, 'w').close() + +def onReceive(packet, interface): + # called when a packet arrives + if 'decoded' in packet: + print('decoded') + decoded = packet['decoded'] + + if 'TEXT_MESSAGE_APP' in packet['decoded']: + print('TEXT_MESSAGE_APP') + + if 'TELEMTRY_APP' in packet['decoded']: + print('Telemetry found. Ignore') + + if 'decoded' in packet and 'text' in packet['decoded']: + print(packet) + message = packet['decoded']['text'] + + # Write message to file + with open(MESSAGE_FILE, 'w') as file: + file.write(message) + + # Notify send_message function + # pub.sendMessage('send_to_irc') + + print(f"text message here: {message}") + else: + print('Not the text message') + print(packet) -class SendMsgBot(slixmpp.ClientXMPP): - """ - A basic Slixmpp bot that will log in, send a message, - and then log out. - """ +# Subscribe send_message function to the send_to_irc topic +# pub.subscribe(send_message, 'send_to_irc') +# This does not work ATM, so doing a quick workaround. - def __init__(self, jid, password, recipient, message): - slixmpp.ClientXMPP.__init__(self, jid, password) +# Initialize the meshtastic interface +interface = meshtastic.tcp_interface.TCPInterface(hostname='192.168.1.102') # repeater +# send message from client ip to repeater. - # The message we wish to send, and the JID that - # will receive it. - self.recipient = recipient - self.msg = message +# Subscribe onReceive function to the meshtastic.receive topic +pub.subscribe(onReceive, "meshtastic.receive") - # The session_start event will be triggered when - # the bot establishes its connection with the server - # and the XML streams are ready for use. We want to - # listen for this event so that we we can initialize - # our roster. - self.add_event_handler("session_start", self.start) - - async def start(self, event): - """ - Process the session_start event. - - Typical actions for the session_start event are - requesting the roster and broadcasting an initial - presence stanza. - - Arguments: - event -- An empty dictionary. The session_start - event does not provide any additional - data. - """ - self.send_presence() - await self.get_roster() - - self.send_message(mto=self.recipient, - mbody=self.msg, - mtype='chat') - - self.disconnect() - - -if __name__ == '__main__': - # Setup the command line arguments. - parser = ArgumentParser(description=SendMsgBot.__doc__) - - # Output verbosity options. - parser.add_argument("-q", "--quiet", help="set logging to ERROR", - action="store_const", dest="loglevel", - const=logging.ERROR, default=logging.INFO) - parser.add_argument("-d", "--debug", help="set logging to DEBUG", - action="store_const", dest="loglevel", - const=logging.DEBUG, default=logging.INFO) - - # JID and password options. - parser.add_argument("-j", "--jid", dest="jid", - help="JID to use") - parser.add_argument("-p", "--password", dest="password", - help="password to use") - parser.add_argument("-t", "--to", dest="to", - help="JID to send the message to") - parser.add_argument("-m", "--message", dest="message", - help="message to send") - - args = parser.parse_args() - - # Setup logging. - logging.basicConfig(level=args.loglevel, - format='%(levelname)-8s %(message)s') - - if args.jid is None: - args.jid = input("Username: ") - if args.password is None: - args.password = getpass("Password: ") - if args.to is None: - args.to = input("Send To: ") - if args.message is None: - args.message = input("Message: ") - - # Setup the EchoBot and register plugins. Note that while plugins may - # have interdependencies, the order in which you register them does - # not matter. - xmpp = SendMsgBot(args.jid, args.password, args.to, args.message) - xmpp.register_plugin('xep_0030') # Service Discovery - xmpp.register_plugin('xep_0199') # XMPP Ping - - # Connect to the XMPP server and start processing XMPP stanzas. - xmpp.connect() - xmpp.process(forever=False) \ No newline at end of file +# Keep the script running to process incoming messages +try: + while True: + time.sleep(1) + send_message_from_mesh() +except KeyboardInterrupt: + pass +finally: + interface.close() diff --git a/message.txt b/message.txt new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt index d83173f..8bb0c14 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,7 @@ pyasn1==0.6.0 pyasn1_modules==0.4.0 pycares==4.4.0 pycparser==2.22 -slixmpp==1.8.5 \ No newline at end of file +slixmpp==1.8.5 +requests==2.32.3 +protobuf==5.27.1 +meshtastic==2.3.10 \ No newline at end of file diff --git a/send_to_irc.py b/send_to_irc.py new file mode 100644 index 0000000..25a3995 --- /dev/null +++ b/send_to_irc.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +import logging +from getpass import getpass +from argparse import ArgumentParser + +import slixmpp +# Mostly a carbon copy of https://slixmpp.readthedocs.io/en/latest/getting_started/sendlogout.html but will have other options. + + +class SendMsgBot(slixmpp.ClientXMPP): + + """ + A basic Slixmpp bot that will log in, send a message, + and then log out. + """ + + def __init__(self, jid, password, recipient, message): + slixmpp.ClientXMPP.__init__(self, jid, password) + + # The message we wish to send, and the JID that + # will receive it. + self.recipient = recipient + self.msg = message + + # The session_start event will be triggered when + # the bot establishes its connection with the server + # and the XML streams are ready for use. We want to + # listen for this event so that we we can initialize + # our roster. + self.add_event_handler("session_start", self.start) + + async def start(self, event): + """ + Process the session_start event. + + Typical actions for the session_start event are + requesting the roster and broadcasting an initial + presence stanza. + + Arguments: + event -- An empty dictionary. The session_start + event does not provide any additional + data. + """ + self.send_presence() + await self.get_roster() + + self.send_message(mto=self.recipient, + mbody=self.msg, + mtype='chat') + + self.disconnect() + + +if __name__ == '__main__': + # Setup the command line arguments. + parser = ArgumentParser(description=SendMsgBot.__doc__) + + # Output verbosity options. + parser.add_argument("-q", "--quiet", help="set logging to ERROR", + action="store_const", dest="loglevel", + const=logging.ERROR, default=logging.INFO) + parser.add_argument("-d", "--debug", help="set logging to DEBUG", + action="store_const", dest="loglevel", + const=logging.DEBUG, default=logging.INFO) + + # JID and password options. + parser.add_argument("-j", "--jid", dest="jid", + help="JID to use") + parser.add_argument("-p", "--password", dest="password", + help="password to use") + parser.add_argument("-t", "--to", dest="to", + help="JID to send the message to") + parser.add_argument("-m", "--message", dest="message", + help="message to send") + + args = parser.parse_args() + + # Setup logging. + logging.basicConfig(level=args.loglevel, + format='%(levelname)-8s %(message)s') + + if args.jid is None: + args.jid = input("Username: ") + if args.password is None: + args.password = getpass("Password: ") + if args.to is None: + args.to = input("Send To: ") + if args.message is None: + args.message = input("Message: ") + + # Setup the EchoBot and register plugins. Note that while plugins may + # have interdependencies, the order in which you register them does + # not matter. + xmpp = SendMsgBot(args.jid, args.password, args.to, args.message) + xmpp.register_plugin('xep_0030') # Service Discovery + xmpp.register_plugin('xep_0199') # XMPP Ping + + # Connect to the XMPP server and start processing XMPP stanzas. + xmpp.connect() + xmpp.process(forever=False) \ No newline at end of file diff --git a/sub_to_tcp.py b/sub_to_tcp.py new file mode 100644 index 0000000..d397439 --- /dev/null +++ b/sub_to_tcp.py @@ -0,0 +1,34 @@ +import time +import meshtastic +import meshtastic.tcp_interface +from pubsub import pub + +def onReceive(packet, interface): + # called when a packet arrives + if 'decoded' in packet: + print('decoded') + decoded = packet['decoded'] + + if 'TEXT_MESSAGE_APP' in packet['decoded']: + print('TEXT_MESSAGE_APP') + + if 'TELEMTRY_APP' in packet['decoded']: + print('Telementy found. Ignore') + + if 'decoded' in packet and 'text' in packet['decoded']: + print(f"text message here: {packet['decoded']['text']}") + else: + print('Not the text message') + + # print(f"Received: {packet}") + +def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio + # defaults to broadcast, specify a destination ID if you wish + interface.sendText("hello mesh") + +pub.subscribe(onReceive, "meshtastic.receive") +# pub.subscribe(onConnection, "meshtastic.connection.established") +interface = meshtastic.tcp_interface.TCPInterface(hostname='192.168.1.102') +while True: + time.sleep(1000) +interface.close() \ No newline at end of file