Made a python script to create posts via meshtastic messages. If you can see this, the test worked! Posting from the park with no mobile data _

  • SalamanderMA
    link
    fedilink
    arrow-up
    16
    ·
    7 hours ago

    It took 3 walks to the park due to bugs and unhandled exceptions but it worked!

    The python script connects to a node that is left at home. The bot can detect and process a message with the following format:

    PST
    Com: Meshtastic
    Sub: Posting via Meshtastic
    Bod: Made a python script to create posts via meshtastic messages. If you can see this, the test worked! Posting from the park with no mobile data ^_^
    
    

    It will parse the message and create a post. So, as long as I can reach my home’s node I am able to create a post.

    • mesamune@lemmy.world
      link
      fedilink
      English
      arrow-up
      3
      ·
      6 hours ago

      Nice! When you get a chance, I would love to see that code! We have a system right now that does local weather and events once a day.

      • SalamanderMA
        link
        fedilink
        arrow-up
        4
        ·
        5 hours ago

        For sure. It is quite basic and I am not proud of the hacky method I used to “parse” the message, but it might be useful for someone looking for a simple way to interface with a meshtastic device over TCP (onReceive) and the Lemmy API (createPost).

        import json
        import re
        import meshtastic
        import meshtastic.tcp_interface
        from pubsub import pub
        import time
        import os
        import requests
        
        
        INSTANCE_API = "https://mander.xyz/api/v3"
        MESHTEST_LEMMY_JWT = 'Cookie retrieved from browser'
        
        
        
        def createPost(community_name, subject, body):
            url = f"{INSTANCE_API}/post"
            getCommunity = requests.get(f"{INSTANCE_API}/community?name={community_name}").json()
            communityId = getCommunity['community_view']['community']['id']
            data = {
                "community_id": communityId,
                "name": subject,
                "body": body}
            headers = {
                "Authorization": f"Bearer {MESHTEST_LEMMY_JWT}",
                "Content-Type": "application/json"
            }
            response = requests.post(url, headers=headers, json=data)
            return response
        
        
        MESHTASTIC_NODE_IP = "Local IP of the base node connected to WiFi"
        
        def sstrip(text):
         return re.sub(r'(?:\s|,)*(sub|SUB|Sub|COM|com|Com|Bod|bod|BOD)(?:\s|,)*$', '', text.strip())
        
        def processMessage(message):
            blocks = message.split(':')    # Splits the message into blocks, but will also split smiley faces ":)", bad method. 
            try:
                for i in range(0,len(blocks)-1):
                    if blocks[i][-3:].lower() == 'sub':
                        subject = sstrip(blocks[i+1])
                    if blocks[i][-3:].lower() == 'com':
                        community_name = sstrip(blocks[i+1]).lower()
                    if blocks[i][-3:].lower() == 'bod':
                        body = sstrip(blocks[i+1])
                return community_name, subject, body
            except:
                return 'ERR','ERR','ERR'
        
        def onReceive(packet, interface):
            if 'decoded' in packet and 'payload' in packet['decoded']:
                try:
                    message = packet['decoded']['payload'].decode('utf-8')
                    sender = packet['from']
                    if 'Ping' in message:
                        interface.sendText("Pong!", destinationId=sender)
                    if message.split('\n')[0] == 'PST':
                      try:
                        community_name, subject, body = processMessage(message)
                        response = createPost(community_name, subject, body)
                        if response.ok:
                          interface.sendText("Post created succesfully!", destinationId=sender)
                        else:
                          interface.sendText("Unable to create post!", destinationId=sender)
                      except:
                       interface.sendText("Exception triggered", destinationId=sender)
                except Exception as e:
                    pass
        
        interface = meshtastic.tcp_interface.TCPInterface(hostname=MESHTASTIC_NODE_IP)
        pub.subscribe(onReceive, "meshtastic.receive")
        
        while True:
            time.sleep(2) 
        
        • mesamune@lemmy.world
          link
          fedilink
          English
          arrow-up
          4
          ·
          edit-2
          5 hours ago

          On a side note, I love how python looks on lemmy. This is awesome! I really like the way you parse the message, its readable.

                      if 'Ping' in message:
                          interface.sendText("Pong!", destinationId=sender)
          

          Im totally doing that to test out my node(s).

          Great job on this. I may take some of this later.

          Here is the weather code (fat fingered the name, cant be bothered to change): https://yuno.chrisco.me/git/michael/meshtastic_forceast/src/branch/main/main.py

          Heavily influenced by something I found online a while back which I lost the reference to.

          Im guessing you were a C/C# dev based on the function names.

          • SalamanderMA
            link
            fedilink
            arrow-up
            3
            ·
            4 hours ago

            Glad you like it :D

            The ping is very useful. I know that there is a built-in range test, but sometimes I don’t need the test to be on all the time, nor do I want to set the frequency too high. Actually… This give me an idea, I can simply program a command to turn the range test off/on remotely.

            That weather function is nice! The US makes available some nice weather APIs. I have a PinePhone and it has a weather module that relies on a US-based API, but I am not in the US. At least I can find out the weather in Oregon easily. I don’t know if there is some similar API in the Netherlands.

            Im guessing you were a C/C# dev based on the function names.

            I helped re-factor some C+±based micro-controller firmware recently and the original code was not following any convention, so I looked at a list of conventions and decided that ‘lower camel case’ looked like a nice one to pick. So, I have been developing a habit to stick to that. I do scientific r&d and only sometimes need to do a bit of programming, so I’m not sure if I’d call myself a dev!