*: reformat
parent
65431de9c3
commit
621a1b908d
80
vortex.py
80
vortex.py
|
@ -7,20 +7,21 @@ import time
|
|||
|
||||
DEFAULT_TIMEOUT = 0.5
|
||||
|
||||
class TimeoutException(Exception): pass
|
||||
|
||||
class TimeoutException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class VortexConnection(object):
|
||||
def __init__(self, ip, port):
|
||||
self.logger = logging.getLogger(self.__class__.__name__)
|
||||
self.handlers = [
|
||||
self.on_message
|
||||
]
|
||||
self.handlers = [self.on_message]
|
||||
|
||||
self.queues = []
|
||||
|
||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.socket.connect((ip, port))
|
||||
self.fd = self.socket.makefile('rw')
|
||||
self.fd = self.socket.makefile("rw")
|
||||
|
||||
def loop_start(self):
|
||||
self.th = threading.Thread(target=self.loop)
|
||||
|
@ -28,37 +29,36 @@ class VortexConnection(object):
|
|||
self.th.start()
|
||||
|
||||
def loop(self):
|
||||
print('Looping...')
|
||||
print("Looping...")
|
||||
|
||||
for line in self.readlines():
|
||||
for h in self.handlers:
|
||||
h(line.strip())
|
||||
|
||||
def send(self, cmd):
|
||||
self.logger.debug('>> %r', cmd)
|
||||
self.fd.write(cmd + '\r')
|
||||
self.logger.debug(">> %r", cmd)
|
||||
self.fd.write(cmd + "\r")
|
||||
self.fd.flush()
|
||||
|
||||
def readlines(self):
|
||||
buf = ''
|
||||
buf = b""
|
||||
data = True
|
||||
|
||||
while data:
|
||||
try:
|
||||
data = self.socket.recv(512).decode()
|
||||
data = self.socket.recv(512)
|
||||
except:
|
||||
time.sleep(0.1)
|
||||
self.logger.warning('Recv failed')
|
||||
self.logger.warning("Recv failed")
|
||||
continue
|
||||
buf += data
|
||||
|
||||
while buf.find('\r') != -1:
|
||||
line, buf = buf.split('\r', 1)
|
||||
while buf.find(b"\r") != -1:
|
||||
line, buf = buf.split(b"\r", 1)
|
||||
yield line
|
||||
|
||||
|
||||
def on_message(self, msg):
|
||||
self.logger.debug('<< %r', msg)
|
||||
self.logger.debug("<< %r", msg)
|
||||
for q in self.queues:
|
||||
q.put_nowait(msg)
|
||||
|
||||
|
@ -66,9 +66,11 @@ class VortexConnection(object):
|
|||
def client(self):
|
||||
q = queue.Queue()
|
||||
self.queues.append(q)
|
||||
self.logger.debug("Adding queue...")
|
||||
try:
|
||||
yield q
|
||||
finally:
|
||||
self.logger.debug("Removing queue...")
|
||||
self.queues.remove(q)
|
||||
|
||||
def call(self, cmd, timeout=DEFAULT_TIMEOUT, wait=True):
|
||||
|
@ -78,59 +80,71 @@ class VortexConnection(object):
|
|||
return
|
||||
|
||||
start = time.time()
|
||||
while time.time()-start < timeout:
|
||||
while time.time() - start < timeout:
|
||||
try:
|
||||
m = q.get(timeout=timeout-(time.time()-start))
|
||||
m = q.get(timeout=timeout - (time.time() - start))
|
||||
except queue.Empty:
|
||||
self.logger.debug("Request timeout")
|
||||
return
|
||||
|
||||
yield m
|
||||
|
||||
def discover(self, timeout=DEFAULT_TIMEOUT):
|
||||
return {
|
||||
resp[:3]: VortexDevice(self, resp[:3])
|
||||
for resp in self.call('***PING', timeout=timeout)
|
||||
if resp[3:] == 'PONG'
|
||||
}
|
||||
resp[:3].decode(): VortexDevice(self, resp[:3].decode())
|
||||
for resp in self.call("***PING", timeout=timeout)
|
||||
if resp[3:].decode() == "PONG"
|
||||
}
|
||||
|
||||
def __getitem__(self, key):
|
||||
return VortexDevice(self, key)
|
||||
|
||||
|
||||
class VortexDevice(object):
|
||||
def __init__(self, connection, device_id):
|
||||
self.conn = connection
|
||||
self.device_id = device_id
|
||||
self.logger = logging.getLogger("vortex.%s" % (self.device_id,))
|
||||
|
||||
def __repr__(self):
|
||||
return '<VortexDevice {}>'.format(self.device_id)
|
||||
return "<VortexDevice {}>".format(self.device_id)
|
||||
|
||||
def mute(self):
|
||||
self.call_single('GMUTEO1')
|
||||
self.call_single("GMUTEO1")
|
||||
|
||||
def unmute(self):
|
||||
self.call_single('GMUTEO0')
|
||||
self.call_single("GMUTEO0")
|
||||
|
||||
def call_single(self, *args, **kwargs):
|
||||
return next(self.call(*args, **kwargs), None)
|
||||
|
||||
def call(self, cmd, expect=None, *args, **kwargs):
|
||||
if expect is None:
|
||||
expect = cmd.replace('?', '')
|
||||
expect = cmd.replace("?", "")
|
||||
|
||||
for resp in self.conn.call(self.device_id + cmd, *args, **kwargs):
|
||||
if not resp.startswith(self.device_id):
|
||||
self.logger.debug("Received: %r (%r)", resp, self.device_id)
|
||||
if resp[: len(self.device_id)] != self.device_id.encode():
|
||||
continue
|
||||
|
||||
resp = resp[len(self.device_id):]
|
||||
resp = resp[len(self.device_id) :]
|
||||
|
||||
if expect is None or resp.startswith(expect):
|
||||
if expect is None or resp[: len(expect)] == expect.encode():
|
||||
yield resp
|
||||
|
||||
if __name__ == "__main__":
|
||||
c = VortexConnection('127.0.0.1', 10001)
|
||||
c.loop_start()
|
||||
print(c.discover())
|
||||
|
||||
#for n in range(1000):
|
||||
if __name__ == "__main__":
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
c = VortexConnection("127.0.0.1", 10001)
|
||||
c.loop_start()
|
||||
d = c.discover()
|
||||
print(d)
|
||||
|
||||
d["F00"].call_single("PING", "PONG")
|
||||
|
||||
# for n in range(1000):
|
||||
# c['T00'].call_single('SSTEXT0,1,XD {}'.format(n), expect=False, timeout=0)
|
||||
# time.sleep(0.1)
|
||||
|
|
102
vortexiot.py
102
vortexiot.py
|
@ -7,23 +7,24 @@ import config
|
|||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
class VortexSpejsIOTClient(mqtt.Client):
|
||||
topic_prefix = 'iot/polycom/'
|
||||
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 = vortex.VortexConnection("localhost", 10001)
|
||||
self.vortex.handlers.append(self.on_vortex_message)
|
||||
self.device_id = ''
|
||||
self.device_id = ""
|
||||
|
||||
def on_connect(self, client, userdata, flags, rc):
|
||||
self.subscribe(self.topic_prefix + '+/+/set')
|
||||
self.logger.info('Connected')
|
||||
self.subscribe(self.topic_prefix + "+/+/set")
|
||||
self.logger.info("Connected")
|
||||
self.device_id = list(self.vortex.discover().keys())[0]
|
||||
self.vortex[self.device_id].call_single('BLAUTO0')
|
||||
self.vortex[self.device_id].call_single("BLAUTO0")
|
||||
|
||||
def run(self):
|
||||
self.loop_start()
|
||||
|
@ -31,15 +32,15 @@ class VortexSpejsIOTClient(mqtt.Client):
|
|||
|
||||
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)
|
||||
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)
|
||||
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):
|
||||
|
@ -47,33 +48,39 @@ class VortexSpejsIOTClient(mqtt.Client):
|
|||
else:
|
||||
value = str(value)
|
||||
|
||||
self.publish('%s%s/%s' % (self.topic_prefix, node, attribute), 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)
|
||||
topic = msg.topic[len(self.topic_prefix) :]
|
||||
self.logger.info("mqtt -> %r %r", topic, msg.payload)
|
||||
|
||||
node, attrib, _ = topic.split('/')
|
||||
msg.payload = msg.payload.decode('utf-8')
|
||||
node, attrib, _ = topic.split("/")
|
||||
msg.payload = msg.payload.decode("utf-8")
|
||||
|
||||
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 attrib == 'mode':
|
||||
self.multi_call('MIC', config.INPUTS[node], '1' if msg.payload == 'mic' else '0')
|
||||
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 attrib == "mode":
|
||||
self.multi_call(
|
||||
"MIC", config.INPUTS[node], "1" if msg.payload == "mic" 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:
|
||||
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(':')
|
||||
inp, _, out = node.partition(":")
|
||||
|
||||
if inp not in config.INPUTS or out not in config.OUTPUTS:
|
||||
self.logger.warning('Invalid route: %r', node)
|
||||
self.logger.warning("Invalid route: %r", node)
|
||||
return
|
||||
|
||||
inp_chs = config.INPUTS[inp]
|
||||
|
@ -81,40 +88,40 @@ class VortexSpejsIOTClient(mqtt.Client):
|
|||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
self.logger.debug("%r/%r: Invalid device id", device_id, self.device_id)
|
||||
return
|
||||
|
||||
if msg.startswith('MMUTE'):
|
||||
inp, out, muted = msg[5:].split(',')
|
||||
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')
|
||||
self.notify("%s:%s" % (inp_label, out_label), "mute", muted == "1")
|
||||
|
||||
elif msg.startswith('MGAIN'):
|
||||
inp, out, gain = msg[5:].split(',')
|
||||
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)
|
||||
self.notify("%s:%s" % (inp_label, out_label), "gain", gain)
|
||||
|
||||
elif msg.startswith('GAINI'):
|
||||
elif msg.startswith("GAINI"):
|
||||
channel_id, gain = msg[5], msg[6:]
|
||||
label = self.input_from_channel(channel_id)
|
||||
self.notify(label, 'gain', gain)
|
||||
self.notify(label, "gain", gain)
|
||||
|
||||
elif msg.startswith('MUTEI'):
|
||||
elif msg.startswith("MUTEI"):
|
||||
channel_id, muted = msg[5], msg[6:]
|
||||
label = self.input_from_channel(channel_id)
|
||||
self.notify(label, 'mute', muted == '1')
|
||||
self.notify(label, "mute", muted == "1")
|
||||
|
||||
def input_from_channel(self, channel):
|
||||
return self.find_label(config.INPUTS, channel)
|
||||
|
@ -132,8 +139,9 @@ class VortexSpejsIOTClient(mqtt.Client):
|
|||
|
||||
def main():
|
||||
client = VortexSpejsIOTClient()
|
||||
client.connect('localhost')
|
||||
client.connect("localhost")
|
||||
client.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue