Skip to content

Instantly share code, notes, and snippets.

@lassem
Last active April 1, 2020 19:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lassem/7b6612d325976802c19e8e519f26ced4 to your computer and use it in GitHub Desktop.
Save lassem/7b6612d325976802c19e8e519f26ced4 to your computer and use it in GitHub Desktop.
ABB Free@Home getall.xml parser
#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import json
f = open('mastermessage.xml', 'r', encoding="utf-8")
root = ET.parse(f)
functions = {}
strings = {}
devices = {}
channelDescriptions = {}
def findName(nameId):
sid = int(nameId, 16)
return strings[sid] if sid in strings else None
def findFunction(functionId):
fid = int(functionId, 16)
return functions[fid] if fid in functions else None
def findFunctions(elm):
functions = []
for f in elm.findall('functions/function') or []:
function = findFunction(f.attrib['functionId'])
functions.append(function)
return functions
def decorateInputDataPoints(cid, dataPoints):
description = channelDescriptions[cid]
for index, dp in enumerate(description.findall('inputs/dataPoint')):
i = f"idp{index:04x}"
dataPoint = dataPoints.get(i, {})
dataPoint['pairingId'] = int(dp.attrib['pairingId'], 16)
dataPoint['name'] = findName(dp.attrib.get('nameId', '0'))
dataPoints[i] = dataPoint
def decorateOutputDataPoints(cid, dataPoints):
description = channelDescriptions[cid]
for index, dp in enumerate(description.findall('outputs/dataPoint')):
i = f"odp{index:04x}"
dataPoint = dataPoints.get(i, {})
dataPoint['pairingId'] = int(dp.attrib['pairingId'], 16)
dataPoint['name'] = findName(dp.attrib.get('nameId', '0'))
dataPoints[i] = dataPoint
### MAIN
for string in root.find('strings'):
sid = int(string.attrib['nameId'], 16)
strings[sid] = string.text
for function in root.find('definitions/functions'):
fid = int(function.attrib['functionId'], 16)
functions[fid] = {}
functions[fid]['functionId'] = fid
functions[fid]['description'] = findName(function.attrib['nameId'])
if ('name' in function.attrib):
functions[fid]['name'] = function.attrib['name']
for elm in root.iterfind('descriptions/channel'):
cid = elm.attrib['cid']
channelDescriptions[cid] = elm
for device in root.find('devices'):
serial = device.attrib['serialNumber']
devices[serial] = {}
devices[serial]['serial'] = serial
devices[serial]['description'] = findName(device.attrib['nameId'])
devices[serial]['function'] = functions[int(device.attrib['functionId'], 16)]
devices[serial]['channels'] = {}
for channel in device.find('channels') or []:
def findFunctionId(elm):
for child in elm.findall('attribute'):
if 'name' in child.attrib and child.attrib['name'] == 'functionId':
return int(child.text, 16)
return None
def findFunctionForId(elm):
for child in elm.findall('attribute'):
if 'name' in child.attrib and child.attrib['name'] == 'functionId':
return findFunction(child.text)
return None
i = channel.attrib['i']
cid = channel.attrib['cid']
devices[serial]['channels'][i] = {}
devices[serial]['channels'][i]['cid'] = cid
devices[serial]['channels'][i]['function'] = findFunctionForId(channel)
devices[serial]['channels'][i]['input'] = {}
devices[serial]['channels'][i]['output'] = {}
for dataPoint in channel.findall('inputs/dataPoint'):
dp = {}
dpi = dataPoint.attrib['i']
dp['value'] = dataPoint.find('value').text
devices[serial]['channels'][i]['input'][dpi] = dp
decorateInputDataPoints(cid, devices[serial]['channels'][i]['input'])
for dataPoint in channel.findall('outputs/dataPoint'):
dp = {}
dpi = dataPoint.attrib['i']
dp['value'] = dataPoint.find('value').text
devices[serial]['channels'][i]['output'][dpi] = dp
decorateOutputDataPoints(cid, devices[serial]['channels'][i]['output'])
for device in devices:
print(json.dumps(devices[device], sort_keys=False, indent=4))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment