Hello everyone!
I wanna share some code i made tonight using python…
Sure it could be written better but it works for me
It checks the state of my tv and receiver using a ping / wget to webinterface of device and getstatus_tv.sh or getstatus_receiver.sh returns ON or OFF to python script. wget response is fast!
I also use lircd to turn these devices on or off etc…
Timeout is 10sec but can be adjusted to what you want.
So every 10secs it checks devices and if state changed publishes using mqtt
Example of getstatus_receiver.sh:
#!/bin/bash
wget -O /dev/null -o /dev/null -t 1 -T 1 http://192.168.1.225
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "OFF"
else
echo "ON"
fi
The python mqtt-client.py script:
#!/usr/bin/python3
import paho.mqtt.client as paho
import paho.mqtt.publish as publish
import RPi.GPIO as GPIO
import datetime
import time
import json
import sys
import os
log = open("mqtt-client.log","a")
# redirect print to logfile...
# comment this line below to print to std instead of logfile
sys.stdout = log
from datetime import datetime
from threading import Thread
auth = {
'username':"user",
'password':"password"
}
topics = {
"home/receiver" : { "topic" : "home/receiver" , "function" : "stateReceiver" },
"home/receiver/state" : { "topic" : "home/receiver/state" , "status" : "OFF" },
"home/tv" : { "topic" : "home/tv" , "function" : "stateTV" },
"home/tv/state" : { "topic" : "home/tv/state" , "status" : "OFF" },
"home/testled1" : { "topic" : "home/testled1" , "function" : "gpioLight" },
"home/testled1/state" : { "topic" : "home/testled1/state" , "status" : "OFF" }
}
# key = topics item, switch = do turn on or off device
def stateTV(key, switch):
import subprocess
if switch is not None:
out = topics[key + "/state"]["status"]
else:
# get state of device (using ping or wget...)
# script returns ON or OFF
proc = subprocess.Popen(["sudo", "sh", "/home/pi/getstatus_tv.sh", "> /dev/null 2>&1"], stdout=subprocess.PIPE)
out, err = proc.communicate()
out.decode('ascii')
if "OFF" in str(out):
if switch == None:
client.publish(key + "/state", "OFF")
topics[key + "/state"]["status"] = "OFF"
elif switch is not None:
topics[key + "/state"]["status"] = "ON"
subprocess.call(["irsend", "SEND_ONCE", "TV", "KEY_POWER"])
else:
if switch == None:
client.publish(key + "/state", "ON")
topics[key + "/state"]["status"] = "ON"
elif switch is not None:
topics[key + "/state"]["status"] = "OFF"
subprocess.call(["irsend", "SEND_ONCE", "TV", "KEY_POWER"])
return topics[key+"/state"]["status"]
# key = topics item, switch = do turn on or off device
def stateReceiver(key, switch):
import subprocess
if switch is not None:
out = topics[key + "/state"]["status"]
else:
# get state of device (using ping or wget...)
# script returns ON or OFF
proc = subprocess.Popen(["sudo", "sh", "/home/pi/getstatus_receiver.sh", "> /dev/null 2>&1"], stdout=subprocess.PIPE)
out, err = proc.communicate()
out.decode('ascii')
if "OFF" in str(out):
if switch == None:
client.publish(key + "/state", "OFF")
topics[key + "/state"]["status"] = "OFF"
elif switch is not None:
topics[key + "/state"]["status"] = "ON"
subprocess.call(["irsend", "SEND_ONCE", "Receiver", "KEY_POWER"])
else:
if switch == None:
client.publish(key + "/state", "ON")
topics[key + "/state"]["status"] = "ON"
elif switch is not None:
topics[key + "/state"]["status"] = "OFF"
subprocess.call(["irsend", "SEND_ONCE", "Receiver", "KEY_POWER"])
return topics[key+"/state"]["status"]
# key = topics item, switch = do turn on or off device
def gpioLight(key, switch):
# read state of GPIO pin
state = "ON" if GPIO.input(23) == 1 else "OFF"
if "OFF" in state:
if switch == None:
client.publish(key + "/state", "OFF")
topics[key + "/state"]["status"] = "OFF"
else:
GPIO.setup(23, GPIO.OUT)
GPIO.output(23, GPIO.HIGH)
topics[key + "/state"]["status"] = "ON"
else:
if switch == None:
client.publish(key + "/state", "ON")
topics[key + "/state"]["status"] = "ON"
else:
GPIO.setup(23, GPIO.OUT)
GPIO.output(23, GPIO.LOW)
topics[key + "/state"]["status"] = "OFF"
return(topics[key + "/state"]["status"])
def on_subscribe(client, userdata, mid, granted_qos):
print (datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " - " + "Subscribed: " + str(mid) + " " + str(granted_qos))
def on_message(client, userdata, msg):
import subprocess
print (datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " - " + "Received message: " + msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
print (
datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " -",
"State changed:",
msg.topic,
eval(topics[msg.topic].get("function") + "('"+msg.topic+"', " + ("1" if "OFF" in str(msg.payload) else "0") + ")")
)
def on_connect(client, userdata, flags, rc):
if rc == 0:
print (datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " - " + "Connected to broker")
# loop thru topics dictionary and subscribe to topics...
for key, val in topics.items():
if (topics[key].get("function") is not None):
print (datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " - " + "Subscribed to topic: " + topics[key].get("topic"))
client.subscribe(topics[key].get("topic"))
else:
print (datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " - " + "Connection failed")
client = paho.Client()
client.on_subscribe = on_subscribe
client.on_message = on_message
client.on_connect = on_connect
client.username_pw_set("user", "password")
client.connect("192.168.1.2", 1883)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(23, GPIO.OUT)
client.loop_start()
try:
# loop thru devices and execute functions to check if online / offline or whatever...
while True:
for key, val in topics.items():
if (topics[key].get("function") is not None):
print (
datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " -",
"Device state: " + topics[key].get("topic"),
eval(topics[key].get("function") + "('" + topics[key].get("topic") + "', None)")
)
# keep logfile filesize at max 1MB (1024(1KB) * 1024) = 1MB...
if os.stat('mqtt-client.log').st_size >= (1024 * 1024):
log.close()
log = open('mqtt-client.log', 'w')
sys.stdout = log
sys.stdout.flush()
time.sleep(10)
except KeyboardInterrupt:
print (datetime.now().strftime('%d-%m-%Y %H:%M:%S') + " - " + "Exiting")
client.disconnect()
client.loop_stop()
switches in configuration.yaml:
- platform: mqtt
name: tv
state_topic: "home/tv/state"
command_topic: "home/tv"
payload_on: "ON"
payload_off: "OFF"
- platform: mqtt
name: receiver
state_topic: "home/receiver/state"
command_topic: "home/receiver"
payload_on: "ON"
payload_off: "OFF"
- platform: mqtt
name: testled1
state_topic: "home/testled1/state"
command_topic: "home/testled1"
payload_on: "ON"
payload_off: "OFF"
To make things complete make a .service file /etc/systemd/system/mqtt-client.service and enable it systemctl daemon etc.:
[Unit]
Description=MQTT-Client
After=multi-user.target
[Service]
Type=simple
ExecStart=/home/pi/mqtt-client.py
User=pi
WorkingDirectory=/home/pi/
Restart=on-failure
StandardOutput=journal
[Install]
WantedBy=multi-user.target
Questions suggestions? Let me know!
Ciao!
Sicco