Home Assistant y The Things Network (TTN)

La integración de Home Assistant para The Things Network (TTN) utiliza su función de almacenamiento para obtener los datos del sensor. La forma más sencilla de observar los sensores TTN sería MQTT, ya que no requiere ninguna configuración adicional.

Por el momento, Home Assistant solo admite un corredor MQTT. Esto significa que no puede suscribirse a temas que se encuentran en diferentes corredores.

Suscríbete al bróker de TTN

Para comprobar lo que envían sus dispositivos, suscríbase al tema +/devices/+/up con una herramienta de línea de comandos como mosquitto_sub. El <Region> es el sufijo de la entrada del controlador en la descripción general de la aplicación. <AppID> es el ID de la aplicación y <AppKey> es su clave de acceso.

€ mosquitto_sub -v -h <Region>.thethings.network -t '+/devices/+/up' -u '<AppID>' -P '<AppKey>'
{
    "app_id": "ha-demo",
    "dev_id": "device01",
    "hardware_serial": "AJDJENDNHRBFBBT",
    "port": 1,
    [...]

La carga útil contiene detalles sobre el propio dispositivo y los datos del sensor. Los datos del sensor se almacenan en payload_fields. Según la configuración del dispositivo, puede contener un solo valor o varios valores.

el relevo

Para poder trabajar localmente con los datos MQTT que se reciben de los dispositivos conectados a TTN, necesitamos transferirlos al broker local. Con este simple script a continuación, todos los mensajes de un dispositivo determinado se vuelven a publicar en su agente MQTT local después de recibirlos. Modifique el script con sus datos como se describe en la sección anterior.

"""Relay MQTT messages from The Things Network to a local MQTT broker."""
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish

DEVICE_NAME = '<DeviceID>'

TTN_BROKER = '<Region>.thethings.network'
TTN_USERNAME = '<AppID>'
TTN_PASSWORD = '<AppKey>'
TTN_TOPIC = '+/devices/{}/up'.format(DEVICE_NAME)

LOCAL_BROKER = '192.168.0.2'
LOCAL_TOPIC = 'home/ttn/garden_temp'


def on_connect(client, userdata, flags, rc):
    """Subscribe to topic after connection to broker is made."""
    print("Connected with result code", str(rc))
    client.subscribe(TTN_TOPIC)


def on_message(client, userdata, msg):
    """Relay message to a different broker."""
    publish.single(
        LOCAL_TOPIC, payload=msg.payload, qos=0, retain=False,
        hostname=LOCAL_BROKER, port=1883, client_id='ttn-local',
        keepalive=60, will=None, auth=None, tls=None, protocol=mqtt.MQTTv311)


client = mqtt.Client()
client.username_pw_set(TTN_USERNAME, password=TTN_PASSWORD)
client.on_connect = on_connect
client.on_message = on_message
client.connect(TTN_BROKER, 1883, 60)

client.loop_forever()

Guárdalo y ejecútalo. Tan pronto como se reciba un mensaje MQTT desde su dispositivo, debería verlo en su corredor local (aquí 192.168.0.2) si se suscribe a # o el tema dado en el guión anterior home/ttn/garden_temp.

mosquitto_sub -h 192.168.0.2 -t "https://www.tecnobestias.com/blog/2017/11/10/ttn-with-mqtt/#" -d

el sensor

Todo lo que necesitaríamos ahora es un mqtt detector con un value_template. Con un sensor personalizado sofisticado, sería posible mostrar un poco más que solo el estado. El dispositivo solo está enviando la temperatura. {"temperature": 7.5} pero hay otros detalles disponibles que el sensor debería mostrar.

"""Support for The Things Network MQTT sensors."""
import asyncio
from datetime import timedelta
import json
import logging

import voluptuous as vol

import homeassistant.components.mqtt as mqtt
from homeassistant.components.mqtt import CONF_STATE_TOPIC
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity

_LOGGER = logging.getLogger(__name__)

DEFAULT_NAME = 'MQTT TTN Sensor'
DEFAULT_FORCE_UPDATE = False
DEPENDENCIES = ['mqtt']

PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
    vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,

})


@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the TTN MQTT Sensor."""
    async_add_devices([MqttTtnSensor(
        config.get(CONF_NAME), config.get(CONF_STATE_TOPIC),
        config.get(CONF_UNIT_OF_MEASUREMENT))
    ])


class MqttTtnSensor(Entity):
    """Representation of a sensor."""

    def __init__(self, name, state_topic, unit_of_measurement):
        """Initialize the sensor."""
        self._state = None
        self._name = name
        self._unit_of_measurement = unit_of_measurement
        self._attributes = {}
        self._state_topic = state_topic

    def async_added_to_hass(self):
        """Subscribe to MQTT events."""
        @callback
        def message_received(topic, payload, qos):
            """Handle new MQTT messages."""

            try:
                data = json.loads(payload)
            except json.JSONDecodeError:
                _LOGGER.error("Invalid JSON data received: %s", data)

            self._state = data['payload_fields'][next(
                iter(data['payload_fields']))]
            self._attributes = data
            del self._attributes['payload_fields']
            del self._attributes['metadata']
            self.async_schedule_update_ha_state()

        return mqtt.async_subscribe(
            self.hass, self._state_topic, message_received, 0)

    @property
    def should_poll(self):
        """No polling needed."""
        return False

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def unit_of_measurement(self):
        """Return the unit this state is expressed in."""
        return self._unit_of_measurement

    @property
    def state_attributes(self):
        """Return the attributes of the entity."""
        return self._attributes

    @property
    def state(self):
        """Return the state of the entity."""
        return self._state

Guárdalo en <config_dir>/custom_components/sensor/mqtt_ttn.py y manejará los mensajes.

La configuración

Ahora crea el mqtt_ttn entrada de sensor para su dispositivo.

sensor:
  - platform: mqtt_ttn
    name: TTN Sensor
    state_topic: "home/ttn/garden_temp"

Esta solución no está lista para la producción, es escalable o estable, pero podría llenar el vacío hasta que Home Assistant pueda conectarse a múltiples corredores MQTT. Si tiene varios dispositivos, transmita todos los mensajes a su agente local y agregue una variable de configuración a mqtt_ttn sensor que le permite seleccionar el dispositivo.