Get last message using Meshtastic Python API? (feature request)

Cool ! I’ll try it tonight.

I think I’m ready to setup a permanent solar powered radio on my garage roof. Yes, I could power it from the mains, but it’ll be nice to have a prototype nearby.

I’m still trying to find people to host radios. I’m tempted to print up fliers and post them in neighborhoods.

I had to update my latitude and longitude (and altitude maybe?) and then I had to hard-code the rxtime value, not sure why yet, but it worked then !

print(f"\nMessage from {interface.nodes[sender][‘user’][‘longName’]} ({interface.nodes[sender][‘position’][‘latitude’]}, {interface.nodes[sender][‘position’][‘longitude’]}) to {packet[‘toId’]} at 2021-12-12 12:12:12 :\n{packet[‘decoded’][‘text’]}\n")

I haven’t figured out how to send messages from the locally connected radio while the code is in the pub.subscribe loop. It also seems as if I can’t use the local radio from the android app.

This code works also…

import datetime
import meshtastic
from pubsub import pub
interface = meshtastic.SerialInterface()
def onReceive(packet, interface): print(f"\nMessage {packet[‘decoded’][‘text’]}\n")

*** then the subscribe is a loop in itself…it will keep getting packets from the local radio

pub.subscribe(onReceive, “meshtastic.receive.text”)

Thanks!

1 Like

I hadn’t noticed that but yes I can’t connect via bluetooth to the radio after running the script. Have to reboot the radio in order to. Don’t know if that’s expected behavior or not.

I thought that the subscribe was supposed to stay running, but my script would exit immediately. That’s why I added the loop.

If I run the python interactive shell, I remove the while loop, paste the code and then it works fine. That’s when you can run the sendText command above to send a message, at the >>> prompt. Or, run “python3 -i meshmessage.py” (without the loop). I think it’s the same thing. If I just run “./meshmessage.py” though, it exits immediately with no loop.

I guess I know just enough to be dangerous, but really don’t have a clue, so this is a learning exercise for me. Thanks for the tips!

Edit: Guess I should say too, I’m running this in a terminal on Ubuntu.

If you call close() on the python connection object (usually called interface) it will cleanly shutdown the API port on the device and then bluetooth will work again.

But if your process gets killed without calling close() you’ll have to wait for the device to timeout and decide that your PC is gone before it switches back to bluetooth. I forget how long that is but it is pretty long (like two minutes).

We do it this way because for most of the devices (the ESP32 ones) we have no way of detecting when the PC closes the USB port to the device.

1 Like

Hey Avron, your question inspired me to write a python script to listen for messages or send them.

I hope it does what you want. It was very fun working on this project.

1 Like

@datagod thank you for your project

are you looking at implementing sending messages to a specific destinationId ?

That is a great idea. For now the message is a broadcast to all nodes. I will add your suggestion to the project on Github.

2 Likes

I have been using the python meshtastic API with the code Toby1234 posted, however at some point the program stops receiving the Pubsub updates while i can still see that the messages are being received on the OLED. Anyone have any idea what’s going wrong?

import datetime
import meshtastic
import meshtastic.serial_interface
from pubsub import pub
import time


class meshclass():
    def __init__(self, device):
        self.rec = None
        self.new = False
        self.rect = 0
        self.packet = None
        #print(meshtastic.serial_interface)
        self.meshint = meshtastic.serial_interface.SerialInterface(device)

        myinfo = self.meshint.getMyUser()
        self.id = myinfo['id']
        self.messages = []
        pub.subscribe(self.onReceive, "meshtastic.receive")

    #def onConnection(interface, topic=pub.AUTO_TOPIC):
    #    self.meshint.sendText("Node {} Online".format(self.id))

    def onReceive(self, packet, interface): # called when a packet arrives
        print(f"Received: {packet}")
        if packet['decoded']['portnum']=='TEXT_MESSAGE_APP':
            sender = packet['fromId']
            self.packet = packet
            #print("Meshtastic: New message")
            self.rect = time.time()

            try:
                try:
                    pos = (interface.nodes[sender]['position']['latitude'], interface.nodes[sender]['position']['longitude'])
                except KeyError:
                    #print('Pos error')
                    pos = None
                    
                try:
                    longname = interface.nodes[sender]['user']['longName']
                except KeyError:
                    #print('Sender error')
                    longname = None

                try:
                    t = datetime.datetime.fromtimestamp(packet['rxTime']).strftime('%Y-%m-%d %H:%M:%S')
                except KeyError:
                    #print('Time error')
                    t = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
                    
                self.rec = {
                    'senderid': sender,
                    'sender': longname,
                    'pos': pos,
                    'dest': packet['toId'],
                    'time': t,
                    'text': packet['decoded']['text']
                }
                #print(self.rec)
                self.messages.append(self.rec)
                self.new = True
            
            except Exception as e:
                print('=========================================')
                print('Error')
                print(packet)
                print(e)
                print('=========================================')
        

    def checkMail(self):
        if self.new:
            self.new = False
            msgs = self.messages
            self.messages = []
            return msgs

# https://python.meshtastic.org/mesh_interface.html

client = meshclass('/dev/ttyACM0')

#client.meshint.getMyNodeInfo()
#client.checkMail()
#client.meshint.sendText("Test")
#client.meshint.sendText("DM Test", destinationId='628c')
#client.meshint.sendPosition(latitude=44, longitude=-73)