spejsiot-polycom/vortexiot.py

136 lines
4.5 KiB
Python

import paho.mqtt.client as mqtt
import vortex
import logging
import itertools
import config
logging.basicConfig(level=logging.INFO)
class VortexSpejsIOTClient(mqtt.Client):
topic_prefix = 'iot/polycom/'
def __init__(self, *args, **kwargs):
super(VortexSpejsIOTClient, self).__init__(*args, **kwargs)
self.logger = logging.getLogger(self.__class__.__name__)
self.vortex = vortex.VortexConnection('localhost', 10001)
self.vortex.handlers.append(self.on_vortex_message)
self.device_id = ''
def on_connect(self, client, userdata, flags, rc):
self.subscribe(self.topic_prefix + '+/+/set')
self.logger.info('Connected')
self.device_id = self.vortex.discover().keys()[0]
def run(self):
self.loop_start()
self.vortex.loop()
def multi_call(self, cmd, channels, args):
for ch in channels:
self.vortex[self.device_id].call_single('%s%s%s' % (
cmd, ch, args
), wait=False)
def matrix_call(self, cmd, pairs, args):
for s, t in pairs:
self.vortex[self.device_id].call_single('%s%s,%s,%s' % (
cmd, s, t, args
), wait=False)
def notify(self, node, attribute, value):
if isinstance(value, bool):
value = str(value).lower()
else:
value = str(value)
self.publish('%s%s/%s' % (self.topic_prefix, node, attribute), value)
def on_message(self, client, userdata, msg):
topic = msg.topic[len(self.topic_prefix):]
self.logger.info('mqtt -> %r %r', topic, msg.payload)
node, attrib, _ = topic.split('/')
if node in config.INPUTS:
if attrib == 'gain':
self.multi_call('GAINI', config.INPUTS[node], msg.payload)
elif attrib == 'mute':
self.multi_call('MUTEI', config.INPUTS[node], '1' if msg.payload == 'true' else '0')
elif node in config.OUTPUTS:
if attrib == 'gain':
self.multi_call('GAINO', config.OUTPUTS[node], msg.payload)
elif attrib == 'mute':
self.multi_call('MUTEO', config.OUTPUTS[node], '1' if msg.payload == 'true' else '0')
elif ':' in node:
# This is matrix operation...
inp, _, out = node.partition(':')
if inp not in config.INPUTS or out not in config.OUTPUTS:
self.logger.warning('Invalid route: %r', node)
return
inp_chs = config.INPUTS[inp]
out_chs = config.OUTPUTS[out]
pairs = zip(itertools.cycle(inp_chs), out_chs)
if attrib == 'mute':
self.matrix_call('MMUTE', pairs, '1' if msg.payload == 'true' else '0')
elif attrib == 'gain':
self.matrix_call('MGAIN', pairs, msg.payload)
def on_vortex_message(self, msg):
self.logger.info('vortex -> %r', msg)
device_id, msg = msg[:3], msg[3:]
if self.device_id != device_id:
self.logger.debug('%r/%r: Invalid device id', device_id, self.device_id)
return
if msg.startswith('MMUTE'):
inp, out, muted = msg[5:].split(',')
inp_label = self.input_from_channel(inp)
out_label = self.output_from_channel(out)
self.notify('%s:%s' % (inp_label, out_label), 'mute', muted == '1')
elif msg.startswith('MGAIN'):
inp, out, gain = msg[5:].split(',')
inp_label = self.input_from_channel(inp)
out_label = self.output_from_channel(out)
self.notify('%s:%s' % (inp_label, out_label), 'gain', gain)
elif msg.startswith('GAINI'):
channel_id, gain = msg[5], msg[6:]
label = self.input_from_channel(channel_id)
self.notify(label, 'gain', gain)
elif msg.startswith('MUTEI'):
channel_id, muted = msg[5], msg[6:]
label = self.input_from_channel(channel_id)
self.notify(label, 'mute', muted == '1')
def input_from_channel(self, channel):
return self.find_label(config.INPUTS, channel)
def output_from_channel(self, channel):
return self.find_label(config.OUTPUTS, channel)
def find_label(self, labels, channel):
for label, channels in labels.items():
if channel in map(str, channels):
return label
return None
def main():
client = VortexSpejsIOTClient()
client.connect('localhost')
client.run()
if __name__ == "__main__":
main()