Add files via upload

This commit is contained in:
LukeSpad 2023-11-13 20:00:48 +00:00 committed by GitHub
parent 41430a76c3
commit 566ebbeeda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 65 deletions

View file

@ -1,5 +1,8 @@
#!/usr/bin/python #!/usr/bin/python
try:
import indigo import indigo
except ImportError:
pass
import logging import logging
import os import os
import unicodedata import unicodedata
@ -30,7 +33,6 @@ class MusicController(object):
def __init__(self): def __init__(self):
self.app = SBApplication.applicationWithBundleIdentifier_("com.apple.Music") self.app = SBApplication.applicationWithBundleIdentifier_("com.apple.Music")
# ######################################################################################## # ########################################################################################
# Player information # Player information
def get_current_track_info(self): def get_current_track_info(self):
@ -134,9 +136,11 @@ class MusicController(object):
self.app.currentTrack().setValue_forKey_('true', 'loved') self.app.currentTrack().setValue_forKey_('true', 'loved')
self.app.currentTrack().setValue_forKey_('true', 'enabled') self.app.currentTrack().setValue_forKey_('true', 'enabled')
elif int(rate) == 0: elif int(rate) == 0:
# If rated 0% then set to disliked and disable the track so it will not be played in shuffle # If rated 0% then set to disliked and disable the track, so it will not be played in shuffle
self.app.currentTrack().setValue_forKey_('true', 'disliked') self.app.currentTrack().setValue_forKey_('true', 'disliked')
self.app.currentTrack().setValue_forKey_('false', 'enabled') self.app.currentTrack().setValue_forKey_('false', 'enabled')
# It's obviously a stinker, so let's skip to the next track
self.app.nextTrack()
else: else:
# else remove disliked/loved flags and check the track is enabled for playback # else remove disliked/loved flags and check the track is enabled for playback
self.app.currentTrack().setValue_forKey_('false', 'disliked') self.app.currentTrack().setValue_forKey_('false', 'disliked')

View file

@ -1,4 +1,7 @@
try:
import indigo import indigo
except ImportError:
pass
import asynchat import asynchat
import socket import socket
import time import time
@ -48,10 +51,11 @@ class BLHIPClient(asynchat.async_chat):
# ##### Client functions # ##### Client functions
def collect_incoming_data(self, data): def collect_incoming_data(self, data):
self.is_connected = True self.is_connected = True
self._received_data += data self._received_data += str(data)
def found_terminator(self): def found_terminator(self):
# indigo.server.log("Raw Data: " + self._received_data) if self.debug:
indigo.server.log("Raw Data: " + self._received_data)
self.last_received = self._received_data self.last_received = self._received_data
self.last_received_at = time.time() self.last_received_at = time.time()
@ -62,7 +66,7 @@ class BLHIPClient(asynchat.async_chat):
indigo.server.log('\tAuthentication Successful!', level=logging.DEBUG) indigo.server.log('\tAuthentication Successful!', level=logging.DEBUG)
self.query(dev_type="AV renderer") self.query(dev_type="AV renderer")
self._received_data = urllib.unquote(self._received_data) self._received_data = urllib.parse.unquote(self._received_data)
telegram = self._received_data.replace("%201", "") telegram = self._received_data.replace("%201", "")
telegram = telegram.split('/') telegram = telegram.split('/')
header = telegram[0:4] header = telegram[0:4]
@ -73,24 +77,20 @@ class BLHIPClient(asynchat.async_chat):
e_string = str(header[0]) e_string = str(header[0])
if e_string[0] == 'e': if e_string[0] == 'e':
if e_string[2:4] == 'OK' and self.debug: if e_string[2:4] == 'OK' and self.debug:
indigo.server.log('Command Successfully Processed: ' + str(urllib.unquote(self._received_data)), indigo.server.log('Command Successfully Processed: ' + str(self._received_data), level=logging.DEBUG)
level=logging.DEBUG)
elif e_string[2:5] == 'CMD': elif e_string[2:5] == 'CMD':
indigo.server.log('Wrong or Unrecognised Command: ' + str(urllib.unquote(self._received_data)), indigo.server.log('Wrong or Unrecognised Command: ' + str(self._received_data), level=logging.WARNING)
level=logging.WARNING)
elif e_string[2:5] == 'SYN': elif e_string[2:5] == 'SYN':
indigo.server.log('Bad Syntax, or Wrong Character Encoding: ' + indigo.server.log('Bad Syntax, or Wrong Character Encoding: ' + str(self._received_data),
str(urllib.unquote(self._received_data)), level=logging.WARNING) level=logging.WARNING)
elif e_string[2:5] == 'ACC': elif e_string[2:5] == 'ACC':
indigo.server.log('Zone Access Violation: ' + str(urllib.unquote(self._received_data)), indigo.server.log('Zone Access Violation: ' + str(self._received_data), level=logging.WARNING)
level=logging.WARNING)
elif e_string[2:5] == 'LEN': elif e_string[2:5] == 'LEN':
indigo.server.log('Received Message Too Long: ' + str(urllib.unquote(self._received_data)), indigo.server.log('Received Message Too Long: ' + str(self._received_data), level=logging.WARNING)
level=logging.WARNING)
self._received_data = "" self._received_data = ""
return return
@ -190,9 +190,16 @@ class BLHIPClient(asynchat.async_chat):
self.is_connected = False self.is_connected = False
self.close() self.close()
def send_cmd(self, telegram): def send_cmd(self, payload):
payload = payload + "\r\n"
payload = payload.encode('UTF8')
telegram = bytearray()
# append payload
for p in payload:
telegram.append(p)
try: try:
self.push(str(telegram + "\r\n")) self.push(telegram)
except socket.timeout as e: except socket.timeout as e:
indigo.server.log("\tSocket connection timed out: " + str(e), level=logging.ERROR) indigo.server.log("\tSocket connection timed out: " + str(e), level=logging.ERROR)
self.handle_close() self.handle_close()
@ -204,9 +211,9 @@ class BLHIPClient(asynchat.async_chat):
self.last_sent_at = time.time() self.last_sent_at = time.time()
if telegram == 'q Main/global/SYSTEM/BeoLink': if telegram == 'q Main/global/SYSTEM/BeoLink':
if self.debug: if self.debug:
indigo.server.log(self.name + " >>-SENT--> : " + telegram, level=logging.DEBUG) indigo.server.log(self.name + " >>-SENT--> : " + payload.decode('UTF8'), level=logging.DEBUG)
else: else:
indigo.server.log(self.name + " >>-SENT--> : " + telegram, level=logging.INFO) indigo.server.log(self.name + " >>-SENT--> : " + payload.decode('UTF8'), level=logging.INFO)
time.sleep(0.2) time.sleep(0.2)
def query(self, zone='*', room='*', dev_type='*', device='*'): def query(self, zone='*', room='*', dev_type='*', device='*'):

View file

@ -485,7 +485,7 @@ ml_command_type_dict = dict(
######################################################### #########################################################
# On power up all devices send out a request key telegram. If # On power up all devices send out a request key telegram. If
# no lock manager is allocated the devices send out a key_lost telegram. The Video Master (or Power # no lock manager is allocated the devices send out a key_lost telegram. The Video Master (or Power
# Master in older implementations) then asserts a NEW_LOCKmANAGER telegram and assumes responsibility # Master in older implementations) then asserts a NEW_LOCKMANAGER telegram and assumes responsibility
# for LOCKMANAGER_COMMAND telegrams until a key transfer occurs. # for LOCKMANAGER_COMMAND telegrams until a key transfer occurs.
# reference: https://tidsskrift.dk/daimipb/article/download/7043/6004/0 # reference: https://tidsskrift.dk/daimipb/article/download/7043/6004/0
(0x12, "KEY_LOST"), # ? (0x12, "KEY_LOST"), # ?

View file

@ -1,4 +1,7 @@
try:
import indigo import indigo
except ImportError:
pass
import asynchat import asynchat
import socket import socket
import time import time
@ -26,7 +29,7 @@ class MLCLIClient(asynchat.async_chat):
self._i = 0 self._i = 0
self._header_lines = 6 self._header_lines = 6
self._received_data = "" self._received_data = ''
self.last_sent = '' self.last_sent = ''
self.last_sent_at = time.time() self.last_sent_at = time.time()
self.last_received = '' self.last_received = ''
@ -48,7 +51,7 @@ class MLCLIClient(asynchat.async_chat):
# ######################################################################################## # ########################################################################################
# ##### Client functions # ##### Client functions
def collect_incoming_data(self, data): def collect_incoming_data(self, data):
self._received_data += data self._received_data += str(data)
def found_terminator(self): def found_terminator(self):
self.last_received = self._received_data self.last_received = self._received_data
@ -61,8 +64,10 @@ class MLCLIClient(asynchat.async_chat):
if self._i <= self._header_lines: if self._i <= self._header_lines:
self._i += 1 self._i += 1
if self._i == self._header_lines - 1: if self._i == self._header_lines - 1:
indigo.server.log("\tAuthenticated! Gateway type is " + telegram[0:4] + "\n", level=logging.DEBUG) if "MLGW" in telegram:
if telegram[0:4] != "MLGW": indigo.server.log("\tAuthenticated! Gateway type is MLGW\n", level=logging.DEBUG)
else:
indigo.server.log("\tAuthenticated! Gateway type is BLGW\n", level=logging.DEBUG)
self.isBLGW = True self.isBLGW = True
# Process telegrams and return json data in human readable format # Process telegrams and return json data in human readable format
@ -79,10 +84,15 @@ class MLCLIClient(asynchat.async_chat):
# ML protocol message detected # ML protocol message detected
items = telegram.split()[1:] items = telegram.split()[1:]
if len(items): if len(items):
telegram = bytearray() telegram = []
for item in items: for item in items:
if len(item) == 3:
item = '0x' + item[:-1]
elif len(item) == 4:
item = '0x' + item[:-2]
try: try:
telegram.append(int(item[:-1], base=16)) telegram.append(int(item, base=16))
except (ValueError, TypeError): except (ValueError, TypeError):
# abort if invalid character found # abort if invalid character found
if self.debug: if self.debug:
@ -90,9 +100,8 @@ class MLCLIClient(asynchat.async_chat):
''.join(items) + '\nAborting!', level=logging.ERROR) ''.join(items) + '\nAborting!', level=logging.ERROR)
break break
# Decode any telegram with a valid 9 byte header, excluding typy 0x14 (regular clock sync pings) # Decode any telegram with a valid 9 byte header, excluding type 0x14 (regular clock sync pings)
if len(telegram) >= 9: if len(telegram) > 9:
# Header: To_Device/From_Device/1/Type/To_Source/From_Source/0/Payload_Type/Length
header = telegram[:9] header = telegram[:9]
payload = telegram[9:] payload = telegram[9:]
message = self._decode(telegram) message = self._decode(telegram)
@ -133,9 +142,16 @@ class MLCLIClient(asynchat.async_chat):
self.is_connected = False self.is_connected = False
self.close() self.close()
def send_cmd(self, telegram): def send_cmd(self, payload):
payload = payload + "\r\n"
payload = payload.encode('UTF8')
telegram = bytearray()
# append payload
for p in payload:
telegram.append(p)
try: try:
self.push(str(telegram + "\r\n")) self.push(telegram)
except socket.timeout as e: except socket.timeout as e:
indigo.server.log("\tSocket connection timed out: " + str(e), level=logging.ERROR) indigo.server.log("\tSocket connection timed out: " + str(e), level=logging.ERROR)
self.handle_close() self.handle_close()
@ -145,7 +161,7 @@ class MLCLIClient(asynchat.async_chat):
else: else:
self.last_sent = telegram self.last_sent = telegram
self.last_sent_at = time.time() self.last_sent_at = time.time()
indigo.server.log(self.name + " >>-SENT--> : " + telegram, level=logging.INFO) indigo.server.log(self.name + " >>-SENT--> : " + payload.decode('UTF8'), level=logging.INFO)
time.sleep(0.2) time.sleep(0.2)
def _report(self, header, payload, message): def _report(self, header, payload, message):
@ -156,7 +172,7 @@ class MLCLIClient(asynchat.async_chat):
def ping(self): def ping(self):
if self.debug: if self.debug:
indigo.server.log(self.name + " >>-SENT--> : Ping", level=logging.DEBUG) indigo.server.log(self.name + " >>-SENT--> : Ping", level=logging.DEBUG)
self.push('\n') self.push(b'\n')
# ######################################################################################## # ########################################################################################
# ##### Utility functions # ##### Utility functions

View file

@ -1,4 +1,7 @@
try:
import indigo import indigo
except ImportError:
pass
import asyncore import asyncore
import json import json
import requests import requests
@ -22,6 +25,8 @@ class MLConfig:
def _download_data(self): def _download_data(self):
try: try:
indigo.debugger()
indigo.server.log('Downloading configuration data from Gateway...', level=logging.WARNING) indigo.server.log('Downloading configuration data from Gateway...', level=logging.WARNING)
url = 'http://' + str(self._host) + '/mlgwpservices.json' url = 'http://' + str(self._host) + '/mlgwpservices.json'
# try Basic Auth next (this is needed for the BLGW) # try Basic Auth next (this is needed for the BLGW)
@ -239,7 +244,7 @@ class MLConfig:
CONST.rooms.append(room) CONST.rooms.append(room)
# Report details of the configuration # Report details of the configuration
n_devices = indigo.devices.len(filter="uk.co.lukes_plugins.BeoGateway.plugin.AVrenderer") - 1 n_devices = indigo.devices.len(filter="uk.co.lukes_plugins.BeoGateway.plugin.AVrenderer")
indigo.server.log('Found ' + str(n_devices) + ' AV Renderers!', level=logging.DEBUG) indigo.server.log('Found ' + str(n_devices) + ' AV Renderers!', level=logging.DEBUG)
for node in indigo.devices.iter('uk.co.lukes_plugins.BeoGateway.plugin.AVrenderer'): for node in indigo.devices.iter('uk.co.lukes_plugins.BeoGateway.plugin.AVrenderer'):
indigo.server.log('\tMLN ' + str(node.address) + ': ' + str(node.name), level=logging.INFO) indigo.server.log('\tMLN ' + str(node.address) + ': ' + str(node.name), level=logging.INFO)
@ -282,7 +287,6 @@ class MLConfig:
test = False test = False
except KeyError: except KeyError:
asyncore.loop(count=1, timeout=0.2) asyncore.loop(count=1, timeout=0.2)
else: else:
# If this is a NetLink product then it has a serial number and no ML_ID # If this is a NetLink product then it has a serial number and no ML_ID
indigo.server.log("\tNetworkLink ID of product " + node.name + " is " + indigo.server.log("\tNetworkLink ID of product " + node.name + " is " +

View file

@ -1,4 +1,7 @@
try:
import indigo import indigo
except ImportError:
pass
import asynchat import asynchat
import socket import socket
import time import time
@ -20,15 +23,15 @@ class MLGWClient(asynchat.async_chat):
self._host = host_address self._host = host_address
self._port = int(port) self._port = int(port)
self._user = user self._user = user.encode('UTF8')
self._pwd = pwd self._pwd = pwd.encode('UTF8')
self.name = name self.name = name
self.is_connected = False self.is_connected = False
self._received_data = bytearray() self._received_data = bytearray()
self.last_sent = '' self.last_sent = bytearray()
self.last_sent_at = time.time() self.last_sent_at = time.time()
self.last_received = '' self.last_received = bytearray()
self.last_received_at = time.time() self.last_received_at = time.time()
self.last_message = {} self.last_message = {}
@ -72,11 +75,11 @@ class MLGWClient(asynchat.async_chat):
self._received_data = "" self._received_data = ""
def found_terminator(self, msg_type, payload): def found_terminator(self, msg_type, payload):
self.last_received = str(list(self._received_data)) self.last_received = self._received_data
self.last_received_at = time.time() self.last_received_at = time.time()
header = self._received_data[0:4] header = self._received_data[0:4]
self._received_data = "" self._received_data = bytearray()
self._decode(msg_type, header, payload) self._decode(msg_type, header, payload)
def _decode(self, msg_type, header, payload): def _decode(self, msg_type, header, payload):
@ -184,6 +187,8 @@ class MLGWClient(asynchat.async_chat):
self._report(header, payload, message) self._report(header, payload, message)
def client_connect(self): def client_connect(self):
indigo.debugger()
indigo.server.log('Connecting to host at ' + self._host + ', port ' + str(self._port), level=logging.WARNING) indigo.server.log('Connecting to host at ' + self._host + ', port ' + str(self._port), level=logging.WARNING)
self.set_terminator(b'\r\n') self.set_terminator(b'\r\n')
# Create the socket # Create the socket
@ -209,7 +214,7 @@ class MLGWClient(asynchat.async_chat):
indigo.server.log("\tConnected to B&O Gateway", level=logging.DEBUG) indigo.server.log("\tConnected to B&O Gateway", level=logging.DEBUG)
def handle_connect(self): def handle_connect(self):
login = [] login = bytearray()
for c in self._user: for c in self._user:
login.append(c) login.append(c)
login.append(0x00) login.append(0x00)
@ -217,6 +222,7 @@ class MLGWClient(asynchat.async_chat):
login.append(c) login.append(c)
indigo.server.log("\tAttempting to Authenticate...", level=logging.WARNING) indigo.server.log("\tAttempting to Authenticate...", level=logging.WARNING)
indigo.server.log("\tLogin: " + str(login), level=logging.DEBUG)
self._send_cmd(CONST.MLGW_PL.get("LOGIN REQUEST"), login) self._send_cmd(CONST.MLGW_PL.get("LOGIN REQUEST"), login)
def handle_close(self): def handle_close(self):
@ -235,21 +241,19 @@ class MLGWClient(asynchat.async_chat):
# send_cmd command to mlgw # send_cmd command to mlgw
def _send_cmd(self, msg_type, payload): def _send_cmd(self, msg_type, payload):
# Construct header # Construct header
telegram = [1, msg_type, len(payload), 0] telegram = bytearray()
telegram.append(1)
telegram.append(msg_type)
telegram.append(len(payload))
telegram.append(0)
indigo.debugger()
# append payload # append payload
for p in payload: for p in payload:
telegram.append(p) telegram.append(p)
# Convert telegram to byte string
# b_telegram = b''
# for t in telegram:
# if type(t) == int:
# b_telegram += (t).to_bytes(1, byteorder='little')
# else:
# b_telegram += bytes(t, 'ascii')
try: try:
self.push(str(bytearray(telegram))) self.push(telegram)
except socket.timeout as e: except socket.timeout as e:
indigo.server.log("\tSocket connection to timed out: " + str(e), level=logging.ERROR) indigo.server.log("\tSocket connection to timed out: " + str(e), level=logging.ERROR)
self.handle_close() self.handle_close()

View file

@ -1,4 +1,7 @@
try:
import indigo import indigo
except ImportError:
pass
import asynchat import asynchat
import socket import socket
import time import time
@ -47,7 +50,7 @@ class MLtnClient(asynchat.async_chat):
# ######################################################################################## # ########################################################################################
# ##### Client functions # ##### Client functions
def collect_incoming_data(self, data): def collect_incoming_data(self, data):
self._received_data += data self._received_data += str(data)
def found_terminator(self): def found_terminator(self):
self.last_received = self._received_data self.last_received = self._received_data
@ -300,17 +303,24 @@ class MLtnClient(asynchat.async_chat):
def handle_connect(self): def handle_connect(self):
indigo.server.log("\tAttempting to Authenticate...", level=logging.WARNING) indigo.server.log("\tAttempting to Authenticate...", level=logging.WARNING)
self._send_cmd(self._pwd) self.send_cmd(self._pwd)
self._send_cmd("MONITOR") self.send_cmd("MONITOR")
def handle_close(self): def handle_close(self):
indigo.server.log(self.name + ": Closing socket", level=logging.ERROR) indigo.server.log(self.name + ": Closing socket", level=logging.ERROR)
self.is_connected = False self.is_connected = False
self.close() self.close()
def _send_cmd(self, telegram): def send_cmd(self, payload):
payload = payload + "\r\n"
payload = payload.encode('UTF8')
telegram = bytearray()
# append payload
for p in payload:
telegram.append(p)
try: try:
self.push(str(telegram + "\r\n")) self.push(telegram)
except socket.timeout as e: except socket.timeout as e:
indigo.server.log("\tSocket connection timed out: " + str(e), level=logging.ERROR) indigo.server.log("\tSocket connection timed out: " + str(e), level=logging.ERROR)
self.handle_close() self.handle_close()
@ -320,7 +330,7 @@ class MLtnClient(asynchat.async_chat):
else: else:
self.last_sent = telegram self.last_sent = telegram
self.last_sent_at = time.time() self.last_sent_at = time.time()
indigo.server.log(self.name + " >>-SENT--> : " + telegram, level=logging.INFO) indigo.server.log(self.name + " >>-SENT--> : " + payload.decode('UTF8'), level=logging.INFO)
time.sleep(0.2) time.sleep(0.2)
def toggle_events(self): def toggle_events(self):
@ -345,7 +355,7 @@ class MLtnClient(asynchat.async_chat):
self.handle_close() self.handle_close()
def ping(self): def ping(self):
self._send_cmd('') self.send_cmd('')
# ######################################################################################## # ########################################################################################
# ##### Utility functions # ##### Utility functions