def cleanupFeedback(): '''Removes KNXItems which are known feedback group addresses ''' def isAssignedFeedback(item1, item2): '''Returns true if group address of a device is already used as a feedback address at the same device ''' result = ( item1 != item2 and # not the same item item1.device_address == item2.device_address and # same device item1.ohItem is None and # item1 not assigned in OH item file item2.ohItem is not None and # item2 is assigned in OH item file item1.address == item2.ohItem.feedback ) # item1 used as feedback of item2 return result before = len(KNXItem.items()) # remove already assigned feedback GAs at the same device for item in filter(lambda x: x.ohItem is not None and x.ohItem.feedback, KNXItem.items()): for foundItem in [ x for x in KNXItem.items() if isAssignedFeedback(x, item) ]: KNXItem.remove(foundItem)
def createGenericControls(): '''Creates a generic control entry for any control that is used in an item file ''' allControls = list(od.fromkeys(filter(lambda x: x.ohItem is not None and x.isControl and x.isWantedControl(), KNXItem.items())).keys()) for item in allControls: entry = KNXItem.createGeneric(ohItem=item.ohItem, isControl=True) item.ignore = True
def writeFiles(): '''Link OpenHABitems and KNXItems and writes ITEMS_FILES, THINGS_FILE, ITEMS_UNUSED_FILE, THINGS_UNUSED_FILE files in knx2 format. ''' writeItemFiles() # print left over KNXItems to ITEMS_UNUSED_FILE devc = None devu = None with open(config.ITEMS_UNUSED_FILE, 'w', encoding=config.OUT_ENCODING) as unusedfile, \ open(config.ITEMS_UNUSED_CONTROLS_FILE, 'w', encoding=config.OUT_ENCODING) as controlfile: print( '// These control switches should be added to get event from wall switches', file=controlfile) print( '// These group addresses are available in your ETS ' 'but are not configured/used in any of your item files', file=unusedfile) for item in sorted( list( filter(lambda x: not x.exported and not x.ignore, KNXItem.items()))): if item.ohItem is None: file = unusedfile if devu != item.getDeviceName(): devu = item.getDeviceName() print('', file=file) else: file = controlfile if devc != item.getDeviceName(): devc = item.getDeviceName() print('', file=file) print(item.getItemRepresentation(), file=file) print(f"written: {config.ITEMS_UNUSED_CONTROLS_FILE}") print(f"written: {config.ITEMS_UNUSED_FILE}") # write thing files writeThingFile( filter( lambda x: x.ohItem is not None and not x.ignore and (x.isGeneric or not x.isControl), KNXItem.items()), config.THINGS_FILE) writeThingFile( filter(lambda x: not x.exported and not x.ignore, KNXItem.items()), config.THINGS_UNUSED_FILE, '// These things are available in your ETS but are not configured/used in any of your item files\n' )
def readDevice(root, ref, building): device = root.findall(getNsURL(root) + config.FIND_DEVICE + "[@Id='" + ref + "']")[0] for comobj in device.findall(getNsURL(root) + config.FIND_COMREF): if 'DatapointType' not in comobj.attrib.keys(): continue dpt = comobj.attrib['DatapointType'] # FIXME: need some mapping here to dtps for connector in comobj.findall(getNsURL(root) + config.FIND_CONNECTOR): for send in (connector.findall(getNsURL(root) + config.FIND_SEND) + connector.findall(getNsURL(root) + config.FIND_RECEIVE)): if 'GroupAddressRefId' in send.keys(): ga_ref = send.attrib['GroupAddressRefId'] ga = root.findall(getNsURL(root) + config.FIND_GA + "[@Id='" + ga_ref + "']")[0] ga_str = ga2str(int(ga.attrib['Address'])) if len(ga_str) > 0: ga = KNXItem(name=ga.attrib['Name'], address=ga_str, refid=ga_ref, device_address=f"{config.ETS_LINE_PREFIX}{device.attrib['Address']}", device_id=device.attrib['ProductRefId'], # dpt=dpt, building=building)
def write_item_files(): '''Write openhab item files. See config.ITEMS_FILES. ''' try: config.ITEMS_FILES except (NameError, AttributeError): config.ITEMS_FILES = None print( 'ITEMS_FILES are not defined (see config.py), so we proceed w/o OpenHAB item files.' ) # create path to outfiles if it doesn't existant if not path.exists(config.ITEM_RESULT_DIR) and config.ITEM_RESULT_DIR: os.makedirs(config.ITEM_RESULT_DIR) if config.ITEMS_FILES is not None: for myfile in map(str.strip, config.ITEMS_FILES.split(',')): outfilename = os.path.join(config.ITEM_RESULT_DIR, path.basename(myfile)) myfile = myfile.strip('\\\r\n').strip() with open(myfile, 'r', encoding=config.IN_ENCODING) as infile, \ open(outfilename, 'w', encoding=config.OUT_ENCODING) as outfile: # read original item file and replace knx2 values for line in infile.readlines(): if not (line.startswith(config.CHANNELS) and re.match( r'.*knx[ ]*=.*', re.sub(r'//.*', '', line))): # non knx items and comments print(line, file=outfile, end='') else: # knx item temp = re.search(r'{.*(knx[ \t]*=.*)[ \t]*}', line).group(1) knx = re.search(r'([0-9]*/[0-9]*/[0-9]*).*', temp).group(1) if knx is None: print("ERROR: GA address not found in:") print(line) sys.exit(1) # find according ETS Actor by GroupAddress items = [ x for x in KNXItem.items() if x.address == knx and not x.isControl and not x.exported ] if len(items) == 0: # seems like we're running w/o ETS project file so create a generic entry name = line.split()[1:2][0] search = [ x for x in OpenHABItem.all_items if x.address == knx and x.name == name ] if len(search) == 1: item = KNXItem.create_generic(ohItem=search[0]) else: # we're lost now so we give up print( f"ERROR: OH entry {name} w/ Group Address {knx} not found." ) sys.exit(1) elif len(items) > 1: # multiple entries found print( f"INFO: Multiple item file entries w/ Group Address {knx} found." f"\tusing: {config.DEVICE_GENERIC}") for item in items: item.ignore = True # "remove others" item.exported = True # Use 1st one hit = next(obj for obj in items if obj.ohItem is not None) item = KNXItem.create_generic(ohItem=hit.ohItem) else: # exactly one item entry found item = items[0] print(item.get_item_representation(line), file=outfile, end='') item.exported = True # add generic control item if aplicable items = [ x for x in KNXItem.items() if x.get_id() == item.get_id() and x.is_generic and x.isControl and item.is_wanted_control() ] if len(items) > 1: # should not happen there should be only one generic item print( f"ERROR: Multiple generic controls w/ Group Address {knx} found." ) sys.exit(1) if len(items) == 1: print(items[0].get_item_representation(), file=outfile) items[0].exported = True print(f"written: {outfilename}")
# check minimum ptyhon version 1st check_python_version() # read ets & openhab files read_ets_file() read_oh_files() # remove already assigned feedback addresses cleanup_feedback() # create generic controls for used items create_generic_controls() # debug output try: with open(config.DEBUG_KNX, 'w') as file: for item in sorted(KNXItem.items()): print(item, file=file) except (NameError, AttributeError): pass try: with open(config.DEBUG_OH, 'w') as file: for item in sorted(OpenHABItem.items()): print(item, file=file) except (NameError, AttributeError): pass write_files()