2021-07-20 15:31:55 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import paho.mqtt.client as mqtt
|
|
|
|
import json
|
|
|
|
from pprint import pprint
|
|
|
|
import printerbox_hardware as hw
|
|
|
|
|
|
|
|
|
|
|
|
def light_cfg(id, name):
|
|
|
|
return {f'light_{id}': {
|
|
|
|
'entity_type': 'light',
|
|
|
|
'name': f"PrusaBox Licht {name}",
|
|
|
|
'unique_id': f'prusa_caselights_{id}',
|
|
|
|
'command_topic': f'prusa_printer/lights_{id}/switch',
|
|
|
|
'state_topic': f'prusa_printer/lights_{id}/switch_state',
|
|
|
|
'brightness_command_topic': f'prusa_printer/lights_{id}/brightness',
|
|
|
|
'brightness_state_topic': f'prusa_printer/lights_{id}/brightness_state',
|
|
|
|
'rgb_command_topic': f'prusa_printer/lights_{id}/rgb',
|
|
|
|
'rgb_state_topic': f'prusa_printer/lights_{id}/rgb_state',
|
|
|
|
'effect_command_topic': f'prusa_printer/lights_{id}/effect',
|
|
|
|
'effect_state_topic': f'prusa_printer/lights_{id}/effect_state',
|
|
|
|
'effect_list': ['color_wipe', 'blink', 'blink_move'],
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
|
|
# ----------------------------------- Config ------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
CONFIG = {
|
|
|
|
'mqtt_server': 'homeassistant',
|
|
|
|
'mqtt_user': 'prusaprinter',
|
|
|
|
'mqtt_password': 'ANchibUdeClEnegue',
|
|
|
|
'mqtt_discovery_prefix': 'homeassistant',
|
|
|
|
|
|
|
|
'devices': {
|
|
|
|
'venting_fan': {
|
|
|
|
'entity_type': 'fan',
|
|
|
|
'unique_id': 'prusa_venting_fan',
|
|
|
|
'name': 'PrusaBox Lüfter draussen',
|
|
|
|
'state_topic': 'prusa_printer/venting_fan',
|
|
|
|
'command_topic': 'prusa_printer/venting_fan/set',
|
|
|
|
'percentage_command_topic': 'prusa_printer/venting_fan/percentage',
|
|
|
|
'percentage_state_topic': 'prusa_printer/venting_fan/percentageState',
|
|
|
|
'min_voltage_percentage': 0.35,
|
|
|
|
'icon': 'mdi:fan',
|
|
|
|
},
|
|
|
|
'filter_fan': {
|
|
|
|
'entity_type': 'fan',
|
|
|
|
'unique_id': 'prusa_filter_fan',
|
|
|
|
'name': 'PrusaBox Filter Lüfter',
|
|
|
|
'state_topic': 'prusa_printer/filter_fan',
|
|
|
|
'command_topic': 'prusa_printer/filter_fan/set',
|
|
|
|
'percentage_command_topic': 'prusa_printer/filter_fan/percentage',
|
|
|
|
'percentage_state_topic': 'prusa_printer/filter_fan/percentageState',
|
|
|
|
'min_voltage_percentage': 0.5,
|
|
|
|
'icon': 'mdi:fan',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for id, name in hw.LED_SUBSET_NAMES.items():
|
|
|
|
CONFIG['devices'].update(light_cfg(id, name))
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def create_discovery_msg(config_entry):
|
|
|
|
cfg = config_entry.copy()
|
|
|
|
topic = "{}/{}/{}/config".format(
|
|
|
|
CONFIG['mqtt_discovery_prefix'], cfg['entity_type'], cfg['unique_id'])
|
|
|
|
del cfg['entity_type']
|
2023-01-03 17:06:09 +01:00
|
|
|
if 'min_voltage_percentage' in cfg:
|
|
|
|
del cfg['min_voltage_percentage']
|
|
|
|
msg = {'topic': topic, 'payload': json.dumps(cfg), 'retain': True}
|
|
|
|
print("sending discovery msg", msg)
|
|
|
|
return msg
|
2021-07-20 15:31:55 +02:00
|
|
|
|
|
|
|
def send_autodiscovery_messages(client):
|
|
|
|
client.publish(**create_discovery_msg(CONFIG['devices']['venting_fan']))
|
|
|
|
client.publish(**create_discovery_msg(CONFIG['devices']['filter_fan']))
|
|
|
|
for id in hw.LED_SUBSET_NAMES.keys():
|
|
|
|
client.publish(
|
|
|
|
**create_discovery_msg(CONFIG['devices']['light_' + id]))
|
|
|
|
|
|
|
|
|
|
|
|
def handle_light_message(client, msg):
|
|
|
|
prefix = 'prusa_printer/lights_'
|
|
|
|
if not msg.topic.startswith(prefix):
|
|
|
|
return False
|
|
|
|
id, cmd = msg.topic[len(prefix):].split("/")
|
|
|
|
payload = msg.payload.decode()
|
|
|
|
cfg = CONFIG['devices']['light_' + id]
|
|
|
|
|
|
|
|
if cmd == "rgb":
|
|
|
|
r, g, b = tuple(int(i) for i in payload.split(","))
|
|
|
|
hw.set_leds_color(r, g, b, subset=id)
|
|
|
|
client.publish(cfg['rgb_state_topic'], payload)
|
|
|
|
elif cmd == "switch":
|
|
|
|
if payload == "ON":
|
|
|
|
hw.set_leds_on(subset=id)
|
|
|
|
elif payload == "OFF":
|
|
|
|
hw.set_leds_off(subset=id)
|
|
|
|
client.publish(cfg['state_topic'], payload)
|
|
|
|
elif cmd == "brightness":
|
|
|
|
hw.set_leds_brightness(int(payload))
|
|
|
|
client.publish(cfg['brightness_state_topic'], payload)
|
|
|
|
elif cmd == "effect":
|
|
|
|
if payload == "color_wipe":
|
|
|
|
hw.effect_color_wipe(0, 0, 255)
|
|
|
|
elif payload == "blink":
|
|
|
|
print("starting blink effect")
|
|
|
|
hw.effect_blink_on_off(255, 0, 0)
|
|
|
|
print("finished starting blink effect")
|
|
|
|
elif payload == "blink_move":
|
|
|
|
hw.effect_move_blink(255, 0, 0)
|
|
|
|
client.publish(cfg['effect_state_topic'], payload)
|
|
|
|
|
|
|
|
def handle_fan_message(client, msg):
|
|
|
|
topic = msg.topic
|
2023-01-03 17:06:09 +01:00
|
|
|
payload = msg.payload
|
2021-07-20 15:31:55 +02:00
|
|
|
|
|
|
|
for cfg, fan in [(CONFIG['devices']['venting_fan'], hw.venting_fan),
|
|
|
|
(CONFIG['devices']['filter_fan'], hw.filter_fan)]:
|
|
|
|
if topic == cfg['command_topic']:
|
|
|
|
fan.value = 1 if payload == b"ON" else 0
|
|
|
|
client.publish(cfg['state_topic'], payload)
|
2023-01-03 17:06:09 +01:00
|
|
|
client.publish(cfg['percentage_state_topic'], 100)
|
2021-07-20 15:31:55 +02:00
|
|
|
return True
|
|
|
|
elif topic == cfg['percentage_command_topic']:
|
2023-01-03 17:06:09 +01:00
|
|
|
fan_percentage = float(payload.decode()) / 100
|
2021-07-20 15:31:55 +02:00
|
|
|
min_perc = cfg['min_voltage_percentage']
|
|
|
|
voltage_percentage = min_perc + (1 - min_perc) * fan_percentage
|
|
|
|
if fan_percentage == 0:
|
|
|
|
voltage_percentage = 0
|
|
|
|
fan.value = voltage_percentage
|
|
|
|
client.publish(cfg['percentage_state_topic'], payload)
|
2023-01-03 17:06:09 +01:00
|
|
|
client.publish(cfg['state_topic'], b"ON" if voltage_percentage > 0 else b"OFF")
|
2021-07-20 15:31:55 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def on_mqtt_message(client, userdata, msg):
|
|
|
|
print(msg.topic, msg.payload)
|
|
|
|
handle_fan_message(client, msg)
|
|
|
|
handle_light_message(client, msg)
|
|
|
|
|
|
|
|
|
|
|
|
def on_mqtt_connect(client, *args, **kwargs):
|
|
|
|
subscriptions = []
|
|
|
|
for device in CONFIG['devices'].values():
|
|
|
|
for key, value in device.items():
|
|
|
|
if key.endswith('_topic'):
|
|
|
|
subscriptions.append((value, 2))
|
|
|
|
client.subscribe(subscriptions)
|
|
|
|
|
|
|
|
|
|
|
|
def run():
|
|
|
|
client = mqtt.Client("prusa-printer-client")
|
|
|
|
client.username_pw_set(CONFIG['mqtt_user'], CONFIG['mqtt_password'])
|
|
|
|
client.on_connect = on_mqtt_connect
|
|
|
|
client.on_message = on_mqtt_message
|
|
|
|
client.connect(CONFIG['mqtt_server'])
|
|
|
|
send_autodiscovery_messages(client)
|
|
|
|
|
|
|
|
client.loop_forever()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
run()
|