136 lines
4.5 KiB
Python
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()
|