2020-04-01 21:15:04 +02:00
|
|
|
import os
|
|
|
|
import time
|
|
|
|
from datetime import datetime
|
|
|
|
import paho.mqtt.client as paho
|
|
|
|
import miio
|
2020-04-02 20:57:28 +02:00
|
|
|
import socket
|
2020-04-01 21:15:04 +02:00
|
|
|
|
|
|
|
|
|
|
|
## Logging to con
|
|
|
|
def log(level, msg):
|
|
|
|
if ( level <= loglevel ):
|
|
|
|
now = datetime.now()
|
|
|
|
print(now.strftime("%Y-%m-%dT%H:%M:%S") + " " + str(level) + " " + msg)
|
|
|
|
|
|
|
|
|
|
|
|
## Receive the airpurifiers status and write it to mqtt
|
|
|
|
def updateMqttStateTopic():
|
|
|
|
log(3, "Starting update of state-topic.")
|
|
|
|
apStatus = ap.status()
|
|
|
|
now = datetime.now()
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "TIMESTAMP", now.strftime("%Y-%m-%dT%H:%M:%S"))
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "airQualityIndex", apStatus.aqi)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "airQualityIndexAvg", apStatus.average_aqi)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "airTemperatureC", apStatus.temperature)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "airRelHumidityPercent", apStatus.humidity)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "fanMotorSpeed", apStatus.motor_speed)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "fanLevel", apStatus.fan_level)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "fanFavoriteSetLevel", apStatus.favorite_level)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "filterUsedHours", apStatus.filter_hours_used)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "filterRemainingPercent", apStatus.filter_life_remaining)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "filterRfidProductId", apStatus.filter_rfid_product_id)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "filterRfidTag", apStatus.filter_rfid_tag)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "filterType", apStatus.filter_type.name)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "deviceBuzzerEnabled", apStatus.buzzer)
|
2021-02-12 22:49:47 +01:00
|
|
|
mqttClient.publish(mqtt_stateTopic + "deviceLedBrightness", apStatus.led_brightness.name)
|
2020-04-01 21:15:04 +02:00
|
|
|
mqttClient.publish(mqtt_stateTopic + "deviceChildLockActive", apStatus.child_lock)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "devicePowerOn", apStatus.is_on)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "devicePower", apStatus.power)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "deviceMode", apStatus.mode.name)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "statPurifiedVolumeM3", apStatus.purify_volume)
|
|
|
|
mqttClient.publish(mqtt_stateTopic + "statTimeActive", apStatus.use_time)
|
|
|
|
# mqttClient.publish(mqtt_stateTopic + "deviceBuzzerSetVolume", apStatus.buzzer_volume)
|
|
|
|
# mqttClient.publish(mqtt_stateTopic + "deviceLedEnabled", apStatus.led)
|
|
|
|
log(3, "Update of state-topic finished.")
|
|
|
|
|
|
|
|
|
|
|
|
## MQTT broker disconnected
|
|
|
|
def on_mqttDisconnect(client, userdata, rc):
|
|
|
|
log(1, "MQTT broker disconnected")
|
|
|
|
|
|
|
|
|
|
|
|
## MQTT broker connected
|
|
|
|
def on_mqttConnect(client, userdata, flags, rc):
|
|
|
|
log(1, "MQTT broker connected")
|
|
|
|
|
2020-04-02 20:39:56 +02:00
|
|
|
## Log unknown MQTT Message Data Values
|
|
|
|
def msgDataUnknown():
|
|
|
|
log(2, "The data inside the MQTT topic is invalid")
|
2020-04-01 21:15:04 +02:00
|
|
|
|
|
|
|
## MQTT Subscription Loop Callback Function
|
|
|
|
def on_mqttMessage(client, userdata, message):
|
|
|
|
mqttMsgData = message.payload.decode("utf-8")
|
|
|
|
mqttMsgTopic = message.topic
|
|
|
|
log(2, "RECEIVED: " + mqttMsgTopic + ":" + mqttMsgData)
|
2020-04-02 18:03:06 +02:00
|
|
|
if ( mqttMsgTopic == mqtt_cmdTopic+"devicePower" ):
|
2020-04-01 21:15:04 +02:00
|
|
|
if (mqttMsgData == "on"):
|
2020-04-02 20:39:56 +02:00
|
|
|
log(2, "ACTION: Power on")
|
2020-04-01 21:15:04 +02:00
|
|
|
ap.on()
|
|
|
|
elif (mqttMsgData == "off"):
|
2020-04-02 20:39:56 +02:00
|
|
|
log(2, "ACTION: Power off")
|
2020-04-01 21:15:04 +02:00
|
|
|
ap.off()
|
2020-04-02 20:39:56 +02:00
|
|
|
else:
|
|
|
|
msgDataUnknown()
|
|
|
|
elif ( mqttMsgTopic == mqtt_cmdTopic+"fanLevel" ):
|
|
|
|
if ( mqttMsgData == "1" ):
|
|
|
|
log(2, "ACTION: Set fanLevel 1")
|
|
|
|
ap.set_fan_level(1)
|
|
|
|
elif ( mqttMsgData == "2" ):
|
|
|
|
log(2, "ACTION: Set fanLevel 2")
|
|
|
|
ap.set_fan_level(2)
|
|
|
|
elif ( mqttMsgData == "3" ):
|
|
|
|
log(2, "ACTION: Set fanLevel 3")
|
|
|
|
ap.set_fan_level(3)
|
|
|
|
else:
|
|
|
|
msgDataUnknown()
|
|
|
|
elif ( mqttMsgTopic == mqtt_cmdTopic+"deviceMode" ):
|
|
|
|
if ( mqttMsgData == "Auto" ):
|
|
|
|
log(2, "ACTION: Set deviceMode Auto")
|
|
|
|
ap.set_mode(miio.airpurifier_miot.OperationMode.Auto)
|
|
|
|
elif ( mqttMsgData == "Fan" ):
|
|
|
|
log(2, "ACTION: Set deviceMode Fan")
|
|
|
|
ap.set_mode(miio.airpurifier_miot.OperationMode.Fan)
|
|
|
|
elif ( mqttMsgData == "Favorite" ):
|
|
|
|
log(2, "ACTION: Set deviceMode Favorite")
|
|
|
|
ap.set_mode(miio.airpurifier_miot.OperationMode.Favorite)
|
|
|
|
elif ( mqttMsgData == "Silent" ):
|
|
|
|
log(2, "ACTION: Set deviceMode Silent")
|
|
|
|
ap.set_mode(miio.airpurifier_miot.OperationMode.Silent)
|
|
|
|
else:
|
|
|
|
msgDataUnknown()
|
2021-02-12 22:49:47 +01:00
|
|
|
elif ( mqttMsgTopic == mqtt_cmdTopic+"deviceLedBrightness" ):
|
|
|
|
if ( mqttMsgData == "Bright" ):
|
|
|
|
log(2, "ACTION: Set LED brightness Bright")
|
|
|
|
ap.set_led_brightness(miio.airpurifier_miot.LedBrightness.Bright)
|
|
|
|
elif ( mqttMsgData == "Dim" ):
|
|
|
|
log(2, "ACTION: Set LED brightness Dim")
|
|
|
|
ap.set_led_brightness(miio.airpurifier_miot.LedBrightness.Dim)
|
|
|
|
elif ( mqttMsgData == "Off" ):
|
|
|
|
log(2, "ACTION: Set LED brightness Off")
|
|
|
|
ap.set_led_brightness(miio.airpurifier_miot.LedBrightness.Off)
|
|
|
|
else:
|
|
|
|
msgDataUnknown()
|
2020-04-02 20:39:56 +02:00
|
|
|
else:
|
|
|
|
log(2, "The MQTT topic is invalid")
|
|
|
|
|
2020-04-01 21:15:04 +02:00
|
|
|
## Force update of STATE after switching things
|
|
|
|
time.sleep(5)
|
|
|
|
updateMqttStateTopic()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## --------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Get confiuration
|
|
|
|
configfile = os.getenv('airpurifierConfigFile', 'airpurifier.conf')
|
|
|
|
exec(open(configfile).read())
|
|
|
|
|
|
|
|
|
|
|
|
log(1, "---------------- Starting Air Purifier Bridge ----------------")
|
|
|
|
log(1, "Loaded confguration file: " + configfile)
|
|
|
|
|
|
|
|
|
|
|
|
## The airpurifier object
|
|
|
|
ap = miio.airpurifier_miot.AirPurifierMiot(ip=miot_ip, token=miot_token)
|
|
|
|
|
|
|
|
|
|
|
|
## The MQTT Client object
|
2020-04-02 20:57:28 +02:00
|
|
|
mqtt_clientId = "apBridge_" + socket.gethostname() + "_" + configfile
|
2020-11-12 18:41:41 +01:00
|
|
|
log(1, "Connecting to MQTT broker " + mqtt_ip + ":" + str(mqtt_port) + " as " + mqtt_clientId)
|
2020-04-02 20:57:28 +02:00
|
|
|
mqttClient = paho.Client(mqtt_clientId)
|
2020-11-12 18:41:41 +01:00
|
|
|
mqttClient.connect(mqtt_ip, port=mqtt_port)
|
2020-04-01 21:15:04 +02:00
|
|
|
time.sleep(5)
|
|
|
|
|
|
|
|
|
|
|
|
## Subscribe to mqtt command topics and start the loop
|
|
|
|
mqtt_cmdTopic = mqtt_topic + "/CMD/"
|
2020-04-02 20:39:56 +02:00
|
|
|
mqttClient.subscribe(mqtt_cmdTopic+"#")
|
2020-04-01 21:15:04 +02:00
|
|
|
mqttClient.on_message = on_mqttMessage
|
|
|
|
mqttClient.on_connect = on_mqttConnect
|
|
|
|
mqttClient.on_disconnect = on_mqttDisconnect
|
|
|
|
log(1, "Starting the subscription loop on " + mqtt_cmdTopic)
|
|
|
|
mqttClient.loop_start()
|
|
|
|
|
|
|
|
|
|
|
|
## State Update Loop
|
|
|
|
mqtt_stateTopic = mqtt_topic + "/STATE/"
|
|
|
|
log(1, "Starting the state update loop on " + mqtt_stateTopic)
|
|
|
|
while True:
|
|
|
|
updateMqttStateTopic()
|
|
|
|
time.sleep(update_interval)
|