Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detailed instructions for Home Assistant #14

Open
Nibb31 opened this issue Feb 18, 2022 · 52 comments
Open

Detailed instructions for Home Assistant #14

Nibb31 opened this issue Feb 18, 2022 · 52 comments

Comments

@Nibb31
Copy link

Nibb31 commented Feb 18, 2022

Hi,
Could you give some more precise instructions on how to use this with Home Assistant (and AppDaemon). Do all the scripts need to be in AppDaemon or only the main meshtastic-mqtt.py? What to put in apps.yaml? What exactly does "on appdaemon remove the argument here" mean ? How do you get a device/entities that you can interact with in Home Assistant ?

@joshpirihi
Copy link
Owner

All Ive been using app daemon for is a place to leave this script running. It doesn't actually interact with home assistant at all. I'd love to make a proper integration for home assistant sometime, that would probably use this script as a major component

Here's what my apps folder looks like. This repo has diverged from the script I've got in there at the moment, I might have a look to see if there's a way to run a script from pip in home assistant somehow.

Screen Shot 2022-02-19 at 6 51 04 AM

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

Hi, I put this files in appdaemon but how can runit ?

@joshpirihi
Copy link
Owner

Edit the meshtastic_mqtt.py script, and import the hassapi stuff and change the class definition:

#uncomment for AppDaemon
import hassapi as hass

#swap for AppDaemon
class MeshtasticMQTT(hass.Hass=None):
#class MeshtasticMQTT():

Then down the bottom comment out this bit:

#in appdaemon comment this block out
#if __name__ == '__main__':
#    main()

Finally, restart AppDaemon and watch the Log tab as it starts up, you should eventually see a message saying meshtastic-mqtt has started:

2022-02-18 19:52:38.561113 INFO AppDaemon: Initializing app meshtastic-mqtt using class MeshtasticMQTT from module meshtastic-mqtt

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

image
Looks promising
I have to do something else ?

@joshpirihi
Copy link
Owner

joshpirihi commented Feb 18, 2022

EDIT THIS IS WRONG... SE BELOW

Oops yea you need to add this to apps.yaml:

meshtastic-mqtt:
  module: "meshtastic-mqtt"
  class: MeshtasticMQTT

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

image

@joshpirihi
Copy link
Owner

I got that wrong. Sorry the version mismatch has me behind a little. Your apps.yaml should be

meshtastic_mqtt:
  module: "meshtastic_mqtt"
  class: MeshtasticMQTT

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

image
image
image

@joshpirihi
Copy link
Owner

Getting there! Remove the =None so the class definition looks like
class MeshtasticMQTT(hass.Hass):

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

Aright...
image
image
image

@joshpirihi
Copy link
Owner

Ok I really need to do some work here I guess. Below is my entire script that is running on my AppDaemon. It's a bit different to what is in this repo but it is working on my one:

# python3.6

from portnums_pb2 import ENVIRONMENTAL_MEASUREMENT_APP, POSITION_APP
import random
import json

import mesh_pb2 as mesh_pb2
import mqtt_pb2 as mqtt_pb2
import environmental_measurement_pb2

from paho.mqtt import client as mqtt_client

import requests

import hassapi as hass

class MeshtasticMQTT(hass.Hass):

    broker = '10.147.253.250'
    port = 1883
    topic = "msh/1/c/#"
    # generate client ID with pub prefix randomly
    client_id = f'python-mqtt-{random.randint(0, 100)}'
    # username = 'emqx'
    # password = 'public'

    traccarHost = '10.147.253.250'


    def connect_mqtt(self) -> mqtt_client:
        def on_connect(client, userdata, flags, rc):
            if rc == 0:
                print("Connected to MQTT Broker!")
            else:
                print("Failed to connect, return code %d\n", rc)

        client = mqtt_client.Client(self.client_id)
        client.username_pw_set("user", "pass")
        client.on_connect = on_connect
        client.connect(self.broker, self.port)
        return client


    def subscribe(self, client: mqtt_client):
        def on_message(client, userdata, msg):
            #print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
            se = mqtt_pb2.ServiceEnvelope()
            se.ParseFromString(msg.payload)
            
            print(se)
            mp = se.packet
            if mp.decoded.portnum == POSITION_APP:
                pos = mesh_pb2.Position()
                pos.ParseFromString(mp.decoded.payload)
                print(getattr(mp, "from"))
                print(pos)
                owntracks_payload = {
                    "_type": "location",
                    "lat": pos.latitude_i * 1e-7,
                    "lon": pos.longitude_i * 1e-7,
                    "tst": pos.time,
                    "batt": pos.battery_level,
                    "alt": pos.altitude
                }
                if owntracks_payload["lat"] != 0 and owntracks_payload["lon"] != 0:
                    #client.publish("owntracks/"+str(getattr(mp, "from"))+"/meshtastic_node", json.dumps(owntracks_payload))
                    if len(self.traccarHost) > 0:
                        traccarURL = "http://"+self.traccarHost+":5055?id="+str(getattr(mp, "from"))+"&lat="+str(pos.latitude_i * 1e-7)+"&lon="+str(pos.longitude_i * 1e-7)+"&altitude="+str(pos.altitude)+"&battery_level="+str(pos.battery_level)+"&hdop="+str(pos.PDOP)+"&accuracy="+str(pos.PDOP*0.03)
                        print(traccarURL)
                        submitted = requests.get(traccarURL)
                        print(submitted)
                #lets also publish the battery directly
                if pos.battery_level > 0:
                    client.publish("/mesh/"+str(getattr(mp, "from"))+"/battery", pos.battery_level)
            elif mp.decoded.portnum == ENVIRONMENTAL_MEASUREMENT_APP:
                env = environmental_measurement_pb2.EnvironmentalMeasurement()
                env.ParseFromString(mp.decoded.payload)
                print(env)
                client.publish("/mesh/"+str(getattr(mp, "from"))+"/temperature", env.temperature)
                client.publish("/mesh/"+str(getattr(mp, "from"))+"/relative_humidity", env.relative_humidity)
                
        client.subscribe(self.topic)
        client.on_message = on_message


    def run(self):
        client = self.connect_mqtt()
        self.subscribe(client)
        client.loop_forever()

    def initialize(self):
        self.run()

#if __name__ == '__main__':
#    mm = MeshtasticMQTT()
#    mm.run()

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

I had to uncomment mqtt password
image
image
image

@joshpirihi
Copy link
Owner

Oh yea the protobufs have changed too.. I will create a seperate repo for this and push up my current working files. Its diverged too much. Stand by...

@joshpirihi
Copy link
Owner

@gfzmake
Copy link

gfzmake commented Feb 18, 2022

Great work!

@gfzmake
Copy link

gfzmake commented Feb 19, 2022

image
image
Still need some tweaks

@joshpirihi
Copy link
Owner

That's working! You can ignore all the warnings there, it's just ignoring the protobufs as it should. If you connect a node to your mqtt you should now get some data out of it

@gfzmake
Copy link

gfzmake commented Feb 19, 2022

image
Where should it appear ?

@joshpirihi
Copy link
Owner

it should create a meshtastic/ topic tree. What do you see on the AppDaemon Log tab now? Is the broker and username and password set properly?

I've just tweaked the main script on the repo to make the mqtt credentials a bit easier to set, they were hard coded.

@gfzmake
Copy link

gfzmake commented Feb 19, 2022

image
image
image
In config of username and password username said "usename"
image

@joshpirihi
Copy link
Owner

Should be fixed now

@gfzmake
Copy link

gfzmake commented Feb 19, 2022

image
image

@joshpirihi
Copy link
Owner

Does your mqtt broker require credentials? If it doesn't, you'll need to comment out the line client.username_pw_set()

@gfzmake
Copy link

gfzmake commented Feb 19, 2022

Yes my mqtt require credentials.

@gfzmake
Copy link

gfzmake commented Feb 19, 2022

image
Yeah, same error...
image
I have these packages installed

@joshpirihi
Copy link
Owner

What does your whole script look like? Are you defining username and password? It looks like it may be an issue with them

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

This script?
image
image
image

@joshpirihi
Copy link
Owner

Ohh sorry man my python is not great. Change the username_pw_set to

        client.username_pw_set(self.username, self.password)

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Success! connected to the mqtt but still not decode the message.
image

@joshpirihi
Copy link
Owner

As packets are published by your gateway node, meshtastic-mqtt will translate them. That Log page should start showing some traffic if the mqtt is connected up properly

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

image

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

This ?

@joshpirihi
Copy link
Owner

Yep that's it! That is showing that the packets are still encrypted. Most likely you'll need to upgrade the firmware on your gateway node to at least 1.2.54. Support for on-device decryption was added part way through 1.2.53

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

I have two nodes, one encrypted and the other free.
image

@joshpirihi
Copy link
Owner

joshpirihi commented Feb 20, 2022

Which one is connected to mqtt? And what firmware version is it running? Setting a blank encryption key isn't enough for this particular task

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Is 1.2.55

@joshpirihi
Copy link
Owner

What is the output of meshtastic --info for that node?

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Now the node is at the top of the roof... I had configured it with this example.
image

@joshpirihi
Copy link
Owner

Where is that documentation from? It's the wrong way around... that needs to be false. You can configure it with the cli via the network mestastic --host 192.168.1.2 --set mqtt_encryption_enabled false

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Really great! I need to reboot the node after change settings ?

@joshpirihi
Copy link
Owner

I don't think so, but it won't hurt to reboot

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

i'm restarting Home Assistant

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Looks like it's working! But only when I reboot or stop AppDaemon.
image

In mqtt the topic "meshtastic" still does not appear.

@joshpirihi
Copy link
Owner

try subscribing to /mesh/# instead

@joshpirihi
Copy link
Owner

There isn't currently support for text messages. Ill add it now

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Ok great!

@joshpirihi
Copy link
Owner

I've updated the script here. That should work a bit better

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

image
image
Stil decode messages does not appear in mqtt

@joshpirihi
Copy link
Owner

Just tweaked the script again, could you give it another go?

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

Sure

@gfzmake
Copy link

gfzmake commented Feb 20, 2022

image

i had to change this
image

@JbbDE
Copy link

JbbDE commented Sep 16, 2022

Hi, could you do a step by step instruction starting from the very beginning? Following all steps you've done so far is kind of hard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants