Compare commits
4 Commits
mqttContro
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
10bbb68dc0 | ||
|
0fd58d07a2 | ||
|
83e3131ccb | ||
|
3ca17eb4cf |
26
ReadMe.md
26
ReadMe.md
@ -38,3 +38,29 @@ Set the following parameter:
|
|||||||
|
|
||||||
|
|
||||||
```docker run -t -i --device=/dev/ttyUSB0 -e SERIAL_DEVICE="/dev/ttyUSB0" -e MQTT_SERVER="192.168.x.y" -e MQTT_TOPIC="testtopic/" sha256:```
|
```docker run -t -i --device=/dev/ttyUSB0 -e SERIAL_DEVICE="/dev/ttyUSB0" -e MQTT_SERVER="192.168.x.y" -e MQTT_TOPIC="testtopic/" sha256:```
|
||||||
|
|
||||||
|
Additional logging can be activated with the variable **PY_LOGGING** possible values are:
|
||||||
|
* DEBUG
|
||||||
|
* INFO
|
||||||
|
* WARNING
|
||||||
|
* ERROR
|
||||||
|
* CRITICAL
|
||||||
|
|
||||||
|
#### Execution via Docker Compose
|
||||||
|
```
|
||||||
|
# template docker-compose.yml
|
||||||
|
services:
|
||||||
|
python_app:
|
||||||
|
attach: false
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
environment:
|
||||||
|
- SERIAL_DEVICE=/dev/ttyUSB0
|
||||||
|
- MQTT_SERVER=192.168.x.y
|
||||||
|
- MQTT_TOPIC=testtopic/
|
||||||
|
devices:
|
||||||
|
- "/dev/ttyUSB0:/dev/ttyUSB0"
|
||||||
|
```
|
||||||
|
build image: **docker-compose up --build**
|
||||||
|
start with **docker-compose up --detach**
|
||||||
|
1
mqttclient/.gitignore
vendored
Normal file
1
mqttclient/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
docker-compose.yml
|
@ -4,6 +4,7 @@ import sys
|
|||||||
from paho.mqtt import client as mqtt_client
|
from paho.mqtt import client as mqtt_client
|
||||||
import os
|
import os
|
||||||
import serial
|
import serial
|
||||||
|
import logging
|
||||||
|
|
||||||
MAXIMUM_COMMUNICATION_FAILURE=1000
|
MAXIMUM_COMMUNICATION_FAILURE=1000
|
||||||
|
|
||||||
@ -11,35 +12,73 @@ TEMPERATUR_MIN_DIFFERENCE = 2
|
|||||||
TARGET_MIN_DIFFERENCE = 1
|
TARGET_MIN_DIFFERENCE = 1
|
||||||
RPM_MIN_DIFFERENCE = 50
|
RPM_MIN_DIFFERENCE = 50
|
||||||
|
|
||||||
|
COMMAND_PREFIX = "ollpe"
|
||||||
|
|
||||||
# MQTT Settings
|
# MQTT Settings
|
||||||
mqtt_server=os.environ['MQTT_SERVER']
|
mqtt_server=os.environ['MQTT_SERVER']
|
||||||
mqtt_topic=os.environ['MQTT_TOPIC']
|
mqtt_topic=os.environ['MQTT_TOPIC']
|
||||||
# SERIAL Port
|
# SERIAL Port
|
||||||
serial_device=os.environ['SERIAL_DEVICE']
|
serial_device=os.environ['SERIAL_DEVICE']
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
try:
|
||||||
|
if (os.environ['PY_LOGGING']):
|
||||||
|
customLevel = os.environ['PY_LOGGING'].upper()
|
||||||
|
except (KeyError):
|
||||||
|
customLevel = 'WARNING'
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=customLevel,
|
||||||
|
filename="/var/log/app.log",
|
||||||
|
filemode="w",
|
||||||
|
format="%(asctime)s - %(levelname)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.debug("Start Serial connect")
|
||||||
# Start Serial communication
|
# Start Serial communication
|
||||||
ser = serial.Serial(serial_device, 115200, timeout=1) # open serial port
|
ser = serial.Serial(serial_device, 115200, timeout=1) # open serial port
|
||||||
|
|
||||||
|
if (ser is None):
|
||||||
|
logging.error("Cannot open device" + str(serial_device))
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
# The callback for when a PUBLISH message is received from the server.
|
# The callback for when a PUBLISH message is received from the server.
|
||||||
def on_message(client, userdata, msg):
|
def on_message(client, userdata, msg):
|
||||||
payload = msg.payload.decode("utf-8")
|
payload = msg.payload.decode("utf-8")
|
||||||
if ((mqtt_topic + "cmd/rpm") == msg.topic):
|
if ((mqtt_topic + "cmd/rpm") == msg.topic):
|
||||||
if (ser.is_open):
|
if (ser.is_open):
|
||||||
command = "ollpef{:02x}".format(int(payload))
|
command = COMMAND_PREFIX+"f{:02x}".format(int(payload))
|
||||||
ser.write(command.encode('utf-8'))
|
ser.write(command.encode('utf-8'))
|
||||||
else:
|
else:
|
||||||
client.publish(mqtt_topic + "cmd/exception", "Serial Connection closed") # clear exception
|
client.publish(mqtt_topic + "cmd/exception", "Serial Connection closed") # clear exception
|
||||||
elif ((mqtt_topic + "cmd/led") == msg.topic):
|
elif ((mqtt_topic + "cmd/led") == msg.topic):
|
||||||
command = "ollpel" + payload
|
# OpenHAB r,g,b payload: 20,0,250
|
||||||
ser.write(command.encode('utf-8'))
|
try:
|
||||||
|
if (',' in payload):
|
||||||
|
red, green, blue = str(payload).split(',')
|
||||||
|
logging.debug("Red=" + str(red) + " Green=" + str(green) + " Blue=" + str(blue))
|
||||||
|
redB= int((int(red)*255)/250)
|
||||||
|
logging.debug("Byte Red=" + str(redB))
|
||||||
|
greenB= int((int(green)*255)/250)
|
||||||
|
logging.debug("Byte Green =" + str(greenB))
|
||||||
|
blueB= int((int(blue)*255)/250)
|
||||||
|
logging.debug("Byte Blue =" + str(blueB))
|
||||||
|
command = COMMAND_PREFIX+"l{:02x}{:02x}{:02x}".format(redB, greenB, blueB)
|
||||||
|
else:
|
||||||
|
command = COMMAND_PREFIX+"l" + payload
|
||||||
|
ser.write(command.encode('utf-8'))
|
||||||
|
except (ValueError):
|
||||||
|
logging.error("Wrong MQTT Command: '" + str(payload) + "'")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(msg.topic+" "+str(msg.payload))
|
logging.warning(msg.topic+" "+str(msg.payload))
|
||||||
|
|
||||||
# Handle MQTT Commands
|
# Handle MQTT Commands
|
||||||
def on_connect(client, obj, flags, reason_code, properties):
|
def on_connect(client, obj, flags, reason_code, properties):
|
||||||
client.subscribe(mqtt_topic + "cmd/led")
|
client.subscribe(mqtt_topic + "cmd/led")
|
||||||
client.subscribe(mqtt_topic + "cmd/rpm")
|
client.subscribe(mqtt_topic + "cmd/rpm")
|
||||||
print("Connected: " + str(reason_code))
|
client.publish(mqtt_topic + "online", payload="true", qos=1, retain=True)
|
||||||
|
logging.debug("Connected: " + str(reason_code))
|
||||||
|
|
||||||
# Start mqtt
|
# Start mqtt
|
||||||
client_id = f'python-fan-ctrl'
|
client_id = f'python-fan-ctrl'
|
||||||
@ -48,12 +87,13 @@ client.on_message = on_message
|
|||||||
client.on_connect = on_connect
|
client.on_connect = on_connect
|
||||||
|
|
||||||
if (not (mqtt_server)):
|
if (not (mqtt_server)):
|
||||||
print("MQTT_SERVER is not set")
|
logging.error("MQTT_SERVER is not set")
|
||||||
|
|
||||||
if (not (mqtt_topic)):
|
if (not (mqtt_topic)):
|
||||||
print("MQTT_TOPIC is not set")
|
logging.error("MQTT_TOPIC is not set")
|
||||||
|
|
||||||
# Start MQTT Client
|
# Start MQTT Client
|
||||||
|
client.will_set(mqtt_topic + "online", payload="false", qos=1, retain=True)
|
||||||
client.connect(mqtt_server, 1883)
|
client.connect(mqtt_server, 1883)
|
||||||
client.loop_start()
|
client.loop_start()
|
||||||
|
|
||||||
@ -70,14 +110,15 @@ lastTarget = -1
|
|||||||
|
|
||||||
# Endless Loop
|
# Endless Loop
|
||||||
try:
|
try:
|
||||||
while True:
|
while ((mqtt_topic is not None) and (mqtt_server is not None)):
|
||||||
try:
|
try:
|
||||||
if (not (ser.is_open)):
|
if (not (ser.is_open)):
|
||||||
ser.open()
|
ser.open()
|
||||||
continue
|
continue
|
||||||
except (serial.SerialException):
|
except (serial.SerialException):
|
||||||
|
logging.error("Could not open serial connection")
|
||||||
client.publish(mqtt_topic + "exception", "serial reopen") # check which port was really used
|
client.publish(mqtt_topic + "exception", "serial reopen") # check which port was really used
|
||||||
time.sleep(1.0)
|
time.sleep(3.0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
line = ser.readline() # read a '\n' terminated line
|
line = ser.readline() # read a '\n' terminated line
|
||||||
@ -88,26 +129,32 @@ try:
|
|||||||
if (SerialCommunicationFailureCounter > MAXIMUM_COMMUNICATION_FAILURE):
|
if (SerialCommunicationFailureCounter > MAXIMUM_COMMUNICATION_FAILURE):
|
||||||
raise serial.SerialException("device reports readiness / device disconnected " + str(MAXIMUM_COMMUNICATION_FAILURE) + " times")
|
raise serial.SerialException("device reports readiness / device disconnected " + str(MAXIMUM_COMMUNICATION_FAILURE) + " times")
|
||||||
|
|
||||||
if (line):
|
if (line) :
|
||||||
client.publish(mqtt_topic + "exception", "") # clear exception
|
client.publish(mqtt_topic + "exception", "") # clear exception
|
||||||
|
# activate debug code, by default
|
||||||
|
temperatur = None
|
||||||
|
percent = None
|
||||||
|
rpm = None
|
||||||
|
|
||||||
# convert byte array to string
|
# convert byte array to string
|
||||||
l = line.decode("utf-8")
|
l = line.decode("utf-8")
|
||||||
|
if (COMMAND_PREFIX in l):
|
||||||
|
logging.debug("Skip '" + str(l) + "', found " + str(COMMAND_PREFIX))
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Parse the controller information
|
# Parse the controller information
|
||||||
# e.g. : 22.00;0%;0RPM
|
# e.g. : 22.00;0%;0RPM
|
||||||
temperatur, percent, rpm = l.split(";")
|
temperatur, percent, rpm = l.split(";")
|
||||||
except (ValueError):
|
except (ValueError):
|
||||||
# activate debug code
|
logging.debug("Unparsable '" + str(l) + "'")
|
||||||
temperatur = None
|
|
||||||
percent = None
|
|
||||||
rpm = None
|
|
||||||
|
|
||||||
if ((temperatur) and (percent) and (rpm)):
|
if ((temperatur) and (percent) and (rpm)):
|
||||||
parseError=False
|
parseError=False
|
||||||
try:
|
try:
|
||||||
currentTemperatur = float(temperatur)
|
currentTemperatur = float(temperatur)
|
||||||
except (ValueError):
|
except (ValueError):
|
||||||
print("Temperatur Error: could not convert string to float:" + temperatur)
|
logging.error("Temperatur Error: could not convert string to float:" + temperatur)
|
||||||
currentTemperatur = lastTemperatur
|
currentTemperatur = lastTemperatur
|
||||||
if (abs(currentTemperatur - lastTemperatur) > TEMPERATUR_MIN_DIFFERENCE):
|
if (abs(currentTemperatur - lastTemperatur) > TEMPERATUR_MIN_DIFFERENCE):
|
||||||
client.publish(mqtt_topic + "temperatur", str(currentTemperatur))
|
client.publish(mqtt_topic + "temperatur", str(currentTemperatur))
|
||||||
@ -117,7 +164,7 @@ try:
|
|||||||
try:
|
try:
|
||||||
currentTarget = int(percent[:-4])
|
currentTarget = int(percent[:-4])
|
||||||
except (ValueError):
|
except (ValueError):
|
||||||
print("Percent Error: could not convert string to int:" + (percent[:-4]))
|
logging.error("Percent Error: could not convert string to int:" + (percent[:-4]))
|
||||||
currentTarget = lastTarget
|
currentTarget = lastTarget
|
||||||
|
|
||||||
if (abs(lastTarget - currentTarget) > TARGET_MIN_DIFFERENCE):
|
if (abs(lastTarget - currentTarget) > TARGET_MIN_DIFFERENCE):
|
||||||
@ -133,7 +180,7 @@ try:
|
|||||||
try:
|
try:
|
||||||
currentRPM = int(rpm[:-3])
|
currentRPM = int(rpm[:-3])
|
||||||
except (ValueError):
|
except (ValueError):
|
||||||
print("RPM Error: could not convert string to int:" + (rpm[:-3]))
|
logging.error("RPM Error: could not convert string to int:" + (rpm[:-3]))
|
||||||
currentRPM = lastRPM
|
currentRPM = lastRPM
|
||||||
|
|
||||||
if (abs(currentRPM-lastRPM) > RPM_MIN_DIFFERENCE):
|
if (abs(currentRPM-lastRPM) > RPM_MIN_DIFFERENCE):
|
||||||
@ -149,12 +196,12 @@ try:
|
|||||||
else:
|
else:
|
||||||
client.publish(mqtt_topic + "debug", line) # line was invalid and could not be parsed
|
client.publish(mqtt_topic + "debug", line) # line was invalid and could not be parsed
|
||||||
else:
|
else:
|
||||||
time.sleep(0.2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
except (KeyboardInterrupt, SystemExit):
|
except (KeyboardInterrupt, SystemExit):
|
||||||
print("User aborted service ...")
|
logging.error("User aborted service ...")
|
||||||
client.publish(mqtt_topic + "debug", "User aborted service")
|
client.publish(mqtt_topic + "debug", "User aborted service")
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
print("service Dead")
|
logging.debug("service Dead")
|
||||||
|
|
||||||
client.loop_stop()
|
client.loop_stop()
|
||||||
|
Loading…
Reference in New Issue
Block a user