Eine Frage die ich mir die letzten Wochen aufgrund der doch nicht geringen Temperaturen ein paar Mal gestellt habe – und die Antwort ist in der Tat ziemlich simpel…

Man nehme dafür:

  • einen Raspberry Pi (Version 4 oder 3 – ist egal)
  • einen Radioempfänger der softwareseitig zu programmieren ist
  • eine handvoll Temperatursender (ich nutze einen von Dostmann )
  • eine bisschen MQTT
  • etwas Python
  • und eine Datenbank

Auf gehts!

Installation der Software auf dem Pi

Mosquitto MQTT

sudo apt-get install mosquitto mosquitto-clients 

testen ob das ganze funktioniert: mosquitto_sub -t rtl_433

MariaDB

sudo apt-get install mariadb-server 

rtl_433

git clone  https://github.com/merbanan/rtl_433.git 

https://github.com/merbanan/rtl_433/blob/master/BUILDING.md 

Python Logger

#!/usr/bin/env python3
import datetime
import json
import logging
import multiprocessing as mp
import sys
import time
import hashlib

import mysql.connector
from mysql.connector import Error
from mysql.connector import errorcode

import paho.mqtt.client as mqtt

MQTT_SERVER = "temperaturestation"
MQTT_TOPIC_PREFIX = "rtl_433"
TIMEOUT_STALE_SENSOR = 600  # Seconds before showing a timeout indicator

MYSQL_host = 'localhost'
MYSQL_port = '3306'
MYSQL_user = 'user'
MYSQL_pass = 'pass'
MYSQL_db = 'db'
MYSQL_table = 'mqtt'
MYSQL_table2 = 'temperatures'

# log = logging.getLogger()  # Single process logger
log = mp.log_to_stderr()  # Multiprocessing capable logger
mqtt_client = mqtt.Client("RTL_433_Test")

sensor_state = dict()  # Dictionary containing accumulated sensor state


def print_sensor_state():
    """ Print accumulated sensor state """
    time_now = datetime.datetime.utcnow().replace(microsecond=0)
    print("\nUpdate per {} UTC".format(time_now.isoformat(sep=' ')))
    for model in sensor_state:
        print(model)
        for ID in sensor_state[model]:
            data = sensor_state[model][ID]['data'].copy()
            timestamp = data.pop('time')
            timedelta = (time_now - timestamp).total_seconds()
            # Indicator for new and stale data
            indicator = "*" if (timedelta < 2) else "~" if (timedelta >
                                                            TIMEOUT_STALE_SENSOR) else " "
            print("  ID {:5} {}{} {}".format(
                ID, timestamp.isoformat(sep=' '), indicator, data))
    sys.stdout.flush()  # Print in real-time


def on_connect(client, userdata, flags, rc):
    """ Callback for when the client receives a CONNACK response from the server. """
    log.info("MQTT Connection: " + mqtt.connack_string(rc))
    if rc != 0:
        log.error("Could not connect. RC: " + str(rc))
        exit()
    # Subscribing in on_connect() means that if we lose the connection and reconnect then subscriptions will be renewed.
    client.subscribe(MQTT_TOPIC_PREFIX)


def on_disconnect(client, userdata, rc):
    if rc != 0:
        log.error("Unexpected disconnection. RC: " + str(rc))


def on_message(client, userdata, msg):
	""" Callback for when a PUBLISH message is received from the server. """

	log.info("Message recieved: " + msg.topic)

	try:
		d = json.loads(msg.payload.decode())
	except json.decoder.JSONDecodeError:
		log.warning("JSON decode error: " + msg.payload.decode())

	time_str = d.get('time', "0000-00-00 00:00:00")
	ts = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")

	hash_object = hashlib.md5(msg.payload.decode().encode())
	hash = hash_object.hexdigest()

	temp = 0

	try:
		temp = d.get('temperature_F')
		temp = (temp - 32)  * (5.0/9.0)
	except e2:
		log.warning('no temp F found...')

	if temp == None or temp == 0:
		try:
			temp = d.get('temperature_C')
		except e:
			log.warning('no temp C found...')

	if msg.payload != '':
		active = ', active=1'
	else:
		active = ''

	query = """
		INSERT INTO `{}`
		SET
			`hash` = '{}',
			`ts`='{}',
			`topic`='{}',
			`value`='{}',
			`qos`='{}',
			`retain`='{}'
			{}
		ON DUPLICATE KEY UPDATE
			`hash` = '{}',
			`ts`='{}',
			`value`='{}',
			`qos`='{}',
			`retain`='{}'
			{}
	""".format(MYSQL_table, hash, ts, msg.topic, msg.payload.decode(), msg.qos, msg.retain, active,
		hash, ts, msg.payload.decode(), msg.qos, msg.retain, active)

	query_2 = """
		INSERT INTO `{}`
		SET
			`hash` = '{}',
			`created` = '{}',
			`model` = '{}',
			`device` = '{}',
			`channel` = '{}',
			`battery` = '{}',
			`temperature` = '{}',
			`humidity` = '{}'
		""".format(MYSQL_table2, hash, ts, d.get('model'), d.get('device'), d.get('channel'), d.get('battery'), temp, d.get('humidity'))
	print(query_2)

	db = mysql.connector.connect(host=MYSQL_host,
                             database=MYSQL_db,
                             user=MYSQL_user,
                             password=MYSQL_pass)
	log.info("connected!")

	if db.is_connected():
		cursor = db.cursor()
		print("\nWrite to db...")
		try:
			print("ready to execute")
			result  = cursor.execute(query)
			print(result)
			db.commit()

			result  = cursor.execute(query_2)
			print(result)
			db.commit()
			print(result)
			print (cursor.rowcount, "Record inserted successfully into {} table".format(MYSQL_table))
			print("\nWrite to db... done!")
		except mysql.connector.Error as error :
			db.rollback()
			print("Failed to insert into MySQL table {}".format(error))

	cursor.close()
	db.close()

	log.info("done!")

# Setup MQTT client
mqtt_client.on_connect = on_connect
mqtt_client.on_disconnect = on_disconnect
mqtt_client.on_message = on_message
mqtt_client.connect(MQTT_SERVER)
mqtt_client.loop_start()


def main():
    """MQTT Test Client"""
    log.setLevel(logging.INFO)
    log.info("MQTT RTL_433 Test Client")

    while True:
        time.sleep(1)


if __name__ == "__main__":
    main()

Empfangen der Temperaturdaten und weiterleiten an MQTT Queue

rtl_433 -F json -M utc | mosquitto_pub -t rtl_433 -l

Systemd für den Mqtt zu Datenbank Logger

Systemd service

[Unit]
Description=start python logger for temperatures sensors

[Service]
ExecStart=/home/pi/mqtt_logger/start_sensors_logger.sh
RestartSec=5
StartLimitInterval=10
StartLimitBurst=10
RuntimeMaxSec=3600
Restart=always

[Install]
WantedBy=multi-user.target

start_sensors_logger.sh

#!/bin/sh
python3 /home/pi/mqtt_logger/logger.py 

Systemd für den MQTT Server

[Unit]
Description=start mqtt reciever for temperatures sensors

[Service]
ExecStart=/home/pi/mqtt_logger/start_sensors_reciever.sh
RestartSec=5
StartLimitInterval=10
StartLimitBurst=10

[Install]
WantedBy=multi-user.target
 #!/bin/sh
/usr/local/bin/rtl_433 -F json -M utc | /usr/bin/mosquitto_pub -t rtl_433 -l 

Schreibe einen Kommentar

Wie zeichne ich die Temperaturen meiner Funksensoren auf? - Christian Zepter