141 lines
4.6 KiB
Python
141 lines
4.6 KiB
Python
#!/usr/bin/env python
|
|
import time
|
|
import homie
|
|
import logging
|
|
import os
|
|
import re
|
|
import noolite
|
|
import queue
|
|
import threading
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
config = {
|
|
"HOST": os.environ.get('MQTT_SERVER', 'mosquitto'),
|
|
"PORT": os.environ.get('MQTT_PORT', 1883),
|
|
"KEEPALIVE": os.environ.get('KEEPALIVE', 10),
|
|
"USERNAME": os.environ.get('USERNAME', ''),
|
|
"PASSWORD": os.environ.get('PASS', ''),
|
|
"CA_CERTS": os.environ.get('CA_CERTS', ''),
|
|
"DEVICE_ID": os.environ.get('DEVICE_ID', 'noolite'),
|
|
"DEVICE_NAME": os.environ.get('DEVICE_NAME', 'noolite'),
|
|
"TOPIC": os.environ.get('TOPIC', 'homie'),
|
|
"CHANNELS": os.environ.get('CHANNELS', 16)
|
|
}
|
|
|
|
Homie = homie.Homie(config)
|
|
nodes = {}
|
|
q = queue.Queue()
|
|
t = None
|
|
|
|
def queuee_worker():
|
|
n = noolite.NooLite()
|
|
while True:
|
|
item = q.get()
|
|
if item is None:
|
|
break
|
|
command = item.get('command', None)
|
|
channel = item.get('channel', None)
|
|
args = item.get('args', None)
|
|
if command == 'on':
|
|
n.on(channel)
|
|
elif command == 'off':
|
|
n.off(channel)
|
|
elif command == 'set':
|
|
n.set(channel, args)
|
|
elif command == 'bind':
|
|
n.bind(channel)
|
|
elif command == 'quit':
|
|
q.task_done()
|
|
time.sleep(0.3)
|
|
|
|
def brightnessHandler(mqttc, obj, msg):
|
|
try:
|
|
payload = msg.payload.decode("UTF-8").lower()
|
|
topic = msg.topic
|
|
channel = parse_channel(topic)
|
|
logger.info("payload: {}, topic: {}, channel: {}".format(payload, topic, channel))
|
|
if channel not in nodes:
|
|
logger.error("Cannot find channel {}".format(channel))
|
|
return true
|
|
if not payload.isdigit():
|
|
logger.error("Invalid payload {}".format(payload))
|
|
return
|
|
node = nodes[channel]
|
|
brightness = int(payload)
|
|
ch_num = int(channel.replace('ch',''))
|
|
logger.info("[{}] brightness: {}".format(channel, brightness))
|
|
q.put({'command':'set', 'channel':ch_num,'args':brightness})
|
|
node.setProperty("brightness").send(brightness)
|
|
except Exception as e:
|
|
logger.error("Something gone wrong in brightnessHandler: {}!".format(e))
|
|
|
|
def bindHandler(mqttc, obj, msg):
|
|
try:
|
|
payload = msg.payload.decode("UTF-8").lower()
|
|
topic = msg.topic
|
|
channel = parse_channel(topic)
|
|
logger.info("payload: {}, topic: {}, channel: {}".format(payload, topic, channel))
|
|
if channel not in nodes:
|
|
logger.error("Cannot find channel {}".format(channel))
|
|
return true
|
|
node = nodes[channel]
|
|
ch_num = int(channel.replace('ch',''))
|
|
q.put({'command':'bind', 'channel':ch_num})
|
|
except Exception as e:
|
|
logger.error("Something gone wrong in bindHandler: {}!".format(e))
|
|
|
|
def powerHandler(mqttc, obj, msg):
|
|
try:
|
|
payload = msg.payload.decode("UTF-8").lower()
|
|
topic = msg.topic
|
|
channel = parse_channel(topic)
|
|
logger.info("payload: {}, topic: {}, channel: {}".format(payload, topic, channel))
|
|
if channel not in nodes:
|
|
logger.error("Cannot find channel {}".format(channel))
|
|
return true
|
|
node = nodes[channel]
|
|
ch_num = int(channel.replace('ch',''))
|
|
if payload == 'on' or payload == 'true':
|
|
logger.info("[{}] Power: on".format(channel))
|
|
q.put({'command':'on', 'channel':ch_num})
|
|
node.setProperty("power").send("on")
|
|
else:
|
|
logger.info("[{}] Power: off".format(channel))
|
|
q.put({'command':'off', 'channel':ch_num})
|
|
node.setProperty("power").send("off")
|
|
except Exception as e:
|
|
logger.error("Something gone wrong in powerHandler: {}!".format(e))
|
|
|
|
def parse_channel(topic):
|
|
found = re.findall('(ch\d+)', topic)
|
|
if len(found) == 0:
|
|
return "";
|
|
return found[0]
|
|
|
|
def main():
|
|
logger.info("Config: {}".format(config))
|
|
Homie.setFirmware("noolite-gateway", "1.0.0")
|
|
channels = int(config['CHANNELS'])
|
|
for i in range(0, channels):
|
|
nodeName = "ch{}".format(i)
|
|
node = Homie.Node(nodeName, nodeName)
|
|
node.advertise("power").settable(powerHandler)
|
|
node.advertise("brightness").settable(brightnessHandler)
|
|
node.advertise("bind").settable(bindHandler)
|
|
nodes[nodeName]=node
|
|
|
|
Homie.setup()
|
|
t = threading.Thread(target=queuee_worker)
|
|
t.start()
|
|
|
|
while True:
|
|
time.sleep(1)
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
main()
|
|
except (KeyboardInterrupt, SystemExit):
|
|
q.put({'command':'quit'})
|
|
t.join()
|
|
logger.info("Quitting.") |