diff --git a/README.md b/README.md
index de840b40a508b0e6af58eef8e7f708cfca4f3d51..fbb988490a02d0ae44897765877e68996b9e03af 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[PACKAGE]: ../../raw/master/mkp/create_topology_data-0.0.8-20231020.mkp "create_topology_data-0.0.8-20231020.mkp"
+[PACKAGE]: ../../raw/master/mkp/create_topology_data-0.0.9-20231027.mkp "create_topology_data-0.0.9-20231027.mkp"
 # PoC for Network Visualization data creation from inventory data
 
 This script creates the topology data file needed for the [Checkmk Exchange Network visualization](https://exchange.checkmk.com/p/network-visualization) plugin by Andreas Boesl and [schnetz](https://exchange.checkmk.com/u/schnetz).\
diff --git a/bin/topology_data/create_topology_args.py b/bin/topology_data/create_topology_args.py
new file mode 100755
index 0000000000000000000000000000000000000000..0460d885298004eaa7337523a150553434330345
--- /dev/null
+++ b/bin/topology_data/create_topology_args.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2023-10-12
+# File  : create_topology_utils.py
+
+#
+# options used
+# -d --default
+# -o --output-directory
+# -s --seed-devices
+# -u --user-data-file
+# -v --version
+# --check-user-data-only
+# --data-source
+# --debug
+# --dont-compare
+# --inventory-columns
+# --keep-domain
+# --keep
+# --lldp
+# --lowercase
+# --min-age
+# --path-in-inventory
+# --time-format
+# --uppercase
+
+from argparse import (
+    Namespace as arg_Namespace,
+    ArgumentParser,
+    RawTextHelpFormatter,
+)
+from create_topology_utils import(
+    CREATE_TOPOLOGY_VERSION,
+    SCRIPT,
+    SAMPLE_SEEDS,
+    USER_DATA_FILE,
+    LABEL_CDP,
+    COLUMNS_CDP,
+    LABEL_LLDP,
+    PATH_LLDP,
+    COLUMNS_LLDP,
+    PATH_CDP
+)
+
+
+def parse_arguments() -> arg_Namespace:
+    parser = ArgumentParser(
+        prog='create_topology_data.py',
+        description='This script creates the topology data file needed for the Checkmk "network_visualization"\n'
+                    'plugin by Andreas Boesl and schnetz. For more information see\n'
+                    'the announcement from schnetz: https://forum.checkmk.com/t/network-visualization/41680\n'
+                    'and the plugin on the Exchange: https://exchange.checkmk.com/p/network-visualization .\n'
+                    '\n'
+                    'The required inventory data can be created with my inventory plugins:\n'
+                    'CDP: https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_cdp_cache\n'
+                    'LLDP: https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_lldp_cache\n'
+                    '\n'
+                    f'\nVersion: {CREATE_TOPOLOGY_VERSION} | Written by: thl-cmk\n'
+                    f'for more information see: https://thl-cmk.hopto.org',
+        formatter_class=RawTextHelpFormatter,
+        epilog='Usage:\n'
+               'for CDP (the default):\n'
+               f'{SCRIPT} -s {SAMPLE_SEEDS} -d\n'
+               'for LLDP:\n'
+               f'{SCRIPT} -s {SAMPLE_SEEDS} -d --lldp\n',
+    )
+    command_group = parser.add_mutually_exclusive_group()
+
+    parser.add_argument(
+        '-d', '--default', default=False, action='store_const', const=True,
+        help='Set the created topology data as default',
+    )
+    parser.add_argument(
+        '-m', '--merge',
+        nargs=2,
+        choices=['CDP', 'LLDP'],
+        help=f'Merge topologies. This runs the topology creation for CDP and LLDP.\n'
+             f'The topologies are then merged in the specified order.\n'
+             f'I.e. -m CDP LLDP merges the CDP topology into the LLDP topology, overwriting\n'
+             f'the LLDP data in case there are conflicts.\n'
+             f'NOTE: static connection data from the user file will always merged with the\n'
+             f' highest priority',
+    )
+    parser.add_argument(
+        '-o', '--output-directory', type=str,
+        help='Directory name where to save the topology data.\n'
+             'I.e.: my_topology. Default is the actual date/time\n'
+             'in "--time-format" format.\n'
+             'NOTE: the directory is a sub directory under "~/var/topology_data/"',
+    )
+    parser.add_argument(
+        '-s', '--seed-devices', type=str, nargs='+',
+        help=f'List of devices to start the topology discovery from.\n'
+             f'I.e. {SAMPLE_SEEDS}',
+    )
+    parser.add_argument(
+        '-u', '--user-data-file', type=str,
+        help='Set the name uf the user provided data file\n'
+             'Default is ~local/bin/topology_data/create_topology_data.toml\n',
+    )
+    parser.add_argument(
+        '-v', '--version', default=False, action='store_const', const=True,
+        help='Print version of this script and exit',
+    )
+    parser.add_argument(
+        '--check-user-data-only', default=False, action='store_const', const=True,
+        help=f'Only tries to read/parse the user data from {USER_DATA_FILE} and exits.',
+    )
+    parser.add_argument(
+        '--data-source', type=str,
+        help=f'The source from which the topology data originates.\n'
+             f'I.e. {LABEL_CDP} for CDP data from the inventory.\n'
+             'NOTE: right now this only an unused label.',
+    )
+    parser.add_argument(
+        '--debug', default=False, action='store_const', const=True,
+        help='Print debug information',
+    )
+    parser.add_argument(
+        '--dont-compare', default=False, action='store_const', const=True,
+        help='Do not compare the actual topology data with the default topology\n'
+             'data. By default, the actual topology is compared with the default\n'
+             'topology. If the data matches, the actual topology is not saved.\n'
+             'So, if you run this tool in a cron job, a new topology will be\n'
+             'created only if there was a change, unless you use "--dont-compare".'
+    )
+    parser.add_argument(
+        '--inventory-columns', type=str,
+        help=f'Columns used from the inventory data.\n'
+             f'I.e. "{COLUMNS_CDP}"\n'
+             'NOTE: the columns must be in the order: neighbour, local_port,\n'
+             'neighbour_port',
+    )
+    parser.add_argument(
+        '--keep-domain', default=False, action='store_const', const=True,
+        help='Do not remove the domain name from the neighbor name',
+    )
+    parser.add_argument(
+        '--keep', type=int,
+        help=f'Number of topologies to keep. The oldest topologies above keep\n'
+             f'max will be deleted. The minimum value for --keep is 1.\n'
+             f'NOTE: The default topologies will be always kept.\n'
+    )
+    parser.add_argument(
+        '--lldp', default=False, action='store_const', const=True,
+        help=f'Sets data source to {LABEL_LLDP}, inventory path \n'
+             f'to "{PATH_LLDP}" and columns\n'
+             f'to "{COLUMNS_LLDP}"',
+    )
+    command_group.add_argument(
+        '--lowercase', default=False, action='store_const', const=True,
+        help='Change neighbour names to all lower case',
+    )
+    parser.add_argument(
+        '--min-age', type=int,
+        help=f'The minimum number of days before a topology is deleted\n'
+             f'by "--keep".\n'
+             f'NOTE: Topologies that are not older than 1 days are always kept.',
+    )
+    parser.add_argument(
+        '--path-in-inventory', type=str,
+        help=f'Checkmk inventory path to the topology data.\n'
+             f'I.e. "{PATH_CDP}"',
+    )
+    parser.add_argument(
+        '--time-format', type=str,
+        help='Format string to render the time. (default: %%Y-%%m-%%dT%%H:%%M:%%S.%%m)',
+    )
+    command_group.add_argument(
+        '--uppercase', default=False, action='store_const', const=True,
+        help='Change neighbour names to all upper case',
+    )
+    return parser.parse_args()
diff --git a/bin/topology_data/create_topology_classes.py b/bin/topology_data/create_topology_classes.py
index 145a84d72ddcd81092978bbba6319e81e80fdc29..8bf30df90c38504e43297dbdc998233fbb0aa084 100755
--- a/bin/topology_data/create_topology_classes.py
+++ b/bin/topology_data/create_topology_classes.py
@@ -10,17 +10,27 @@
 
 
 from os import environ
+from pathlib import Path
 from time import strftime
 from typing import Dict, List, Any, NamedTuple
 from enum import Enum, unique
 from create_topology_utils import (
-    cdp_path,
-    cdp_columns,
-    cdp_label,
-    lldp_path,
-    lldp_columns,
-    lldp_label,
-    user_data_file,
+    CREATE_TOPOLOGY_VERSION,
+    PATH_CDP,
+    COLUMNS_CDP,
+    LABEL_CDP,
+    PATH_LLDP,
+    COLUMNS_LLDP,
+    LABEL_LLDP,
+    PATH_INTERFACES,
+    USER_DATA_FILE,
+    LQ_INTERFACES,
+    SCRIPT,
+    get_inventory_data,
+    get_table_from_inventory,
+    get_interface_items_from_lq,
+    ExitCodes,
+    get_data_from_toml,
 )
 
 
@@ -32,8 +42,14 @@ class TopologyParams(NamedTuple):
 
 @unique
 class Topologies(Enum):
-    CDP = TopologyParams(path=cdp_path, columns=cdp_columns, label=cdp_label)
-    LLDP = TopologyParams(path=lldp_path, columns=lldp_columns, label=lldp_label)
+    CDP = TopologyParams(path=PATH_CDP, columns=COLUMNS_CDP, label=LABEL_CDP)
+    LLDP = TopologyParams(path=PATH_LLDP, columns=COLUMNS_LLDP, label=LABEL_LLDP)
+
+
+@unique
+class CacheSources(Enum):
+    inventory = 'inventory'
+    lq = 'lq'
 
 
 class InventoryColumns(NamedTuple):
@@ -72,11 +88,11 @@ class Settings:
 
         self.__settings = {
             'seed_devices': None,
-            'path_in_inventory': cdp_path,
-            'inventory_columns': cdp_columns,
-            'data_source': cdp_label,
+            'path_in_inventory': PATH_CDP,
+            'inventory_columns': COLUMNS_CDP,
+            'data_source': LABEL_CDP,
             'time_format': '%Y-%m-%dT%H:%M:%S.%m',
-            'user_data_file': f'{self.__omd_root}/local/bin/topology_data/{user_data_file}',
+            'user_data_file': f'{self.__omd_root}/local/bin/topology_data/{USER_DATA_FILE}',
             'merge': None,
             'output_directory': None,
             'default': False,
@@ -96,16 +112,31 @@ class Settings:
         self.__args = ({k.split(',')[-1].strip(' ').strip('_'): v for k, v in cli_args.items() if v})
         # first set values
         if self.__args.get('lldp'):
-            self.__settings['data_source'] = lldp_label
-            self.__settings['path_in_inventory'] = lldp_path
-            self.__settings['inventory_columns'] = lldp_columns
+            self.__settings['data_source'] = LABEL_LLDP
+            self.__settings['path_in_inventory'] = PATH_LLDP
+            self.__settings['inventory_columns'] = COLUMNS_LLDP
         # Then update values with cli values
         self.__settings.update(self.__args)
-        if not self.merge:
-            if not self.lldp:
-                self.merge = ['CDP']
-            else:
+
+        if self.version:
+            print(f'{Path(SCRIPT).name} version: {CREATE_TOPOLOGY_VERSION}')
+            exit(code=ExitCodes.OK.value)
+
+        if self.check_user_data_only:
+            user_data = get_data_from_toml(file=self.user_data_file)
+            print(f'Could read/parse the user data from {self.user_data_file}')
+            exit(code=ExitCodes.OK.value)
+
+        if self.merge:
+            _merge = list(set(self.merge.copy()))
+            if len(_merge) != len(self.merge):
+                print(f'-m/--merge options must be unique. Use "-m CDP LLDP" oder "-m LLDP CDP"')
+                exit(code=ExitCodes.BAD_OPTION_LIST.value)
+        else:
+            if self.lldp:
                 self.merge = ['LLDP']
+            else:
+                self.merge = ['CDP']
 
     def set_topology_param(self, topology: TopologyParams):
         self.__settings['path_in_inventory'] = topology.path
@@ -199,8 +230,9 @@ class Settings:
 
     @property
     def path_in_inventory(self) -> List[str]:
-        path = ('Nodes,' + ',Nodes,'.join(self.__settings['path_in_inventory'].split(',')) + ',Table,Rows').split(',')
-        return path
+        # path = ('Nodes,' + ',Nodes,'.join(self.__settings['path_in_inventory'].split(',')) + ',Table,Rows').split(',')
+        # return path
+        return self.__settings['path_in_inventory']
 
     @property
     def path_to_if_table(self) -> List[str]:
@@ -233,3 +265,42 @@ class Settings:
             return f'{strftime(self.__settings["time_format"])}'
         else:
             return self.__settings['output_directory']
+
+
+class HostCache:
+    def __init__(self):
+        self.__cache = {}
+        self.__inventory_pre_fetch_list: List[str] = [
+            PATH_CDP,
+            PATH_LLDP,
+            PATH_INTERFACES,
+        ]
+
+    def __fill_cache(self, host: str):
+        # pre fill inventory data
+        inventory = get_inventory_data(host=host)
+        if inventory:
+            self.__cache[host][CacheSources.inventory.value] = {}
+            self.__cache[host][CacheSources.inventory.value].update({
+                entry: get_table_from_inventory(
+                    inventory=inventory,
+                    path=entry
+                ) for entry in self.__inventory_pre_fetch_list
+            })
+        else:
+            self.__cache[host][CacheSources.inventory.value] = None
+        # prefill live status data
+        self.__cache[host][CacheSources.lq.value] = {}
+        self.__cache[host][CacheSources.lq.value][LQ_INTERFACES] = get_interface_items_from_lq(host)
+
+    def get_data(self, host: str, source: CacheSources, path: str):
+        if host not in self.__cache.keys():
+            self.__cache[host]: Dict[str, Any] = {}
+            self.__fill_cache(host=host)
+        try:
+            return self.__cache[host][source.value][path]
+        except (KeyError, TypeError) as e:
+            return None
+
+    def add_inventory_prefetch_path(self, path: str):
+        self.__inventory_pre_fetch_list = list(set(self.__inventory_pre_fetch_list + [path]))
diff --git a/bin/topology_data/create_topology_data.py b/bin/topology_data/create_topology_data.py
index c47adbc4e7737b3f80eb8c6ef0ded4c34bbdea36..cded0835c6a54f4c7178529a4792660090a8400d 100755
--- a/bin/topology_data/create_topology_data.py
+++ b/bin/topology_data/create_topology_data.py
@@ -23,6 +23,8 @@
 #             added option -u, --user-data-file to provide a user specific data file
 # 2023-10-20: changed option -m/--make-default to -d/--default (-m is needed for -m/--merge
 #             added -m/--merge option
+# 2023-10-27: improved matching of port name from CDP/LLDP data to interface (item) name of service
+#             improved internal data handling (HostCache)
 
 #
 # PoC for creating topology_data.json from inventory data
@@ -37,78 +39,39 @@
 # NOTE: the topology_data configuration (layout etc.) is saved under ~/var/check_mk/topology
 #
 # The inventory data could be created with my CDP/LLDP inventory plugins:
-#
 # CDP: https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_cdp_cache\
-# CDP path-in-inventory: 'networking,cdp_cache'
-# CDP inventory-columns: 'device_id,local_port,device_port'
-#
 # LLDP: https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_lldp_cache\
-# LLDP path-in-inventory: 'networking,lldp_cache'
-# LLDP inventory-columns: 'system_name,local_port_num,port_id'
 #
-# USAGE CDP (is the default):
-# ~/local/lib/topology_data/create_topology_data.py -s CORE01 -m
-#
-# USAGE LLDP:
-# ~/local/lib/topology_data/create_topology_data.py -s CORE01 -m --lldp
+# USAGE:
+# ~/local/lib/topology_data/create_topology_data.py --help
 #
 
-from ast import literal_eval
-from pathlib import Path
 from typing import Dict, List, Any
 from time import strftime, time_ns
 
 from create_topology_utils import (
-    parse_arguments,
     remove_old_data,
     get_data_from_toml,
     merge_topologies,
     save_topology,
-    get_data_form_live_status,
-    ExitCodes,
+    LQ_INTERFACES,
+    PATH_INTERFACES,
 )
+from create_topology_args import parse_arguments
 from create_topology_classes import (
     InventoryColumns,
     Settings,
     StaticConnection,
     Topologies,
-    TopologyParams,
+    HostCache,
+    CacheSources,
 )
 
-
-CREATE_TOPOLOGY_VERSION = '0.0.8-202310120'
-
-ITEMS = {}
 HOST_MAP: Dict[str, str] = {}
 DROP_HOSTS: List[str] = []
 STATIC_CONNECTIONS: Dict = {}
 
 
-def get_interface_items_from_lq(host: str, debug: bool = False) -> Dict:
-    query = (
-        'GET services\n'
-        'Columns: host_name description check_command\n'
-        'Filter: description ~ Interface\n'
-        f'Filter: host_name = {host}\n'
-        'OutputFormat: python3\n'
-    )
-    data = get_data_form_live_status(query=query)
-    items = {}
-    for host, description, check_command in data:
-        if host:
-            if host not in items.keys():
-                items[host] = []
-            items[host].append(description[10:])  # remove 'Interface ' from description
-
-    interfaces = 0
-    for host in items.keys():
-        items[host] = list(set(items[host]))
-        items[host].sort()
-        interfaces += len(items[host])
-    # print(f'Interfaces found: {interfaces}')
-    return items
-
-
 def get_list_of_devices(data) -> List[str]:
     devices = []
     for connection in data.values():
@@ -116,66 +79,64 @@ def get_list_of_devices(data) -> List[str]:
     return list(set(devices))
 
 
-def get_service_by_interface(host: str, interface: str, debug: bool = False) -> str | None:
+def get_service_by_interface(host: str, interface: str, debug: bool = False) -> str:
+    # try to find the item for an interface
+    def _match_entry_with_item(_entry: Dict[str, str]):
+        values = [_entry.get('name'), _entry.get('description'), entry.get('alias')]
+        for value in values:
+            if value in items:
+                return value
+
+        index = str(_entry.get('index'))
+        # for index try with padding
+        for i in range(1, 6):
+            index_padded = f'{index:0>{i}}'
+            if index_padded in items:
+                return index_padded
+            # still not found try values + index
+            for value in values:
+                if f'{value} {index_padded}' in items:
+                    return f'{value} {index_padded}'
+
+        return interface
+
     # empty host/neighbour should never happen here
     if not host:
         return interface
-    items = ITEMS.get(host, [])
 
+    # get list of interface items
+    items = HOST_CACHE.get_data(host=host, source=CacheSources.lq, path=LQ_INTERFACES)
+
+    # the easy case
     if interface in items:
         return interface
     else:
-        if_padding = interface
-        if '/' in interface:
-            if_padding = '/'.join(interface.split('/')[:-1]) + f'/{interface.split("/")[-1]:0>2}'
-
-        for item in items:
-            # interface = Gi0/1
-            # item = Gi0/1 - Access port
-            # this might not catch the correct interface (fa0 and fa0/0)
-            item = item.split(' ')[0]
-            if item == interface:
-                return item
-            elif item == if_padding:
-                return item
-
+        # try to find the interface in the host interface inventory list
+        inventory = HOST_CACHE.get_data(host=host, source=CacheSources.inventory, path=PATH_INTERFACES)
+        if inventory:
+            for entry in inventory:
+                if interface in [
+                    entry.get('name'),
+                    entry.get('description'),
+                    entry.get('alias'),
+                    str(entry.get('index')),
+                    entry.get('phys_address'),
+                ]:
+                    return _match_entry_with_item(entry)
         if debug:
-            print(f'Device: {host}: interface ({interface}) not found in services')
+            print(f'Device: {host}: service for interface {interface} not found')
 
         return interface
 
 
-def get_inventory_data_lq(host: str, path: List[str], debug: bool = False, ) -> List[Dict[str, str]]:
-    query = f'GET hosts\nColumns: mk_inventory\nOutputFormat: python3\nFilter: host_name = {host}\n'
-    data = get_data_form_live_status(query=query)
-
-    if data:
-        try:
-            data = literal_eval(data[0][0].decode('utf-8'))
-        except SyntaxError as e:
-            if debug:
-                print(f'data: |{data}|')
-                print(f'type: {type(data)}')
-                print(f'exception: {e}')
-            return []
-        for m in path:
-            try:
-                data = data[m]
-            except KeyError:
-                return []
-        return data
-    return []
-
-
 def create_device_from_inv(
         host: str,
         inv_data: List[Dict[str, str]],
         inv_columns: InventoryColumns,
         data_source: str,
+        debug: bool = False,
 ) -> Dict[str, Any] | None:
     data = {'connections': {}, "interfaces": []}
-    if not host in ITEMS.keys():
-        ITEMS.update(get_interface_items_from_lq(host=host))
     for topo_neighbour in inv_data:
         neighbour = topo_neighbour.get(inv_columns.neighbour)
         if not neighbour:
@@ -194,18 +155,18 @@ def create_device_from_inv(
         if neighbour in HOST_MAP.keys():
             neighbour = HOST_MAP[neighbour]
 
-        # has to be done before checking interfaces
-        if not neighbour in ITEMS.keys():
-            ITEMS.update(get_interface_items_from_lq(host=neighbour))
-
         # getting/checking interfaces
         local_port = topo_neighbour.get(inv_columns.local_port)
-
-        local_port = get_service_by_interface(host, local_port)
+        _local_port = local_port
+        local_port = get_service_by_interface(host, local_port, debug=debug)
+        if debug and local_port != _local_port:
+            print(f'host: {host}, local_port: {local_port}, _local_port: {_local_port}')
 
         neighbour_port = topo_neighbour.get(inv_columns.neighbour_port)
-
-        neighbour_port = get_service_by_interface(neighbour, neighbour_port)
+        _neighbour_port = neighbour_port
+        neighbour_port = get_service_by_interface(neighbour, neighbour_port, debug=debug)
+        if debug and neighbour_port != _neighbour_port:
+            print(f'neighbour: {neighbour}, neighbour_port {neighbour_port}, _neighbour_port {_neighbour_port}')
 
         if neighbour and local_port and neighbour_port:
             data['connections'].update({local_port: [neighbour, neighbour_port, data_source]})
@@ -272,18 +233,20 @@ def create_topology(
             if device in devices_done:
                 continue
 
-        topo_data = get_inventory_data_lq(host=device, path=path_in_inventory, debug=debug)
-        topology_data.update(
-            create_device_from_inv(
-                host=device,
-                inv_data=topo_data,
-                inv_columns=inv_columns,
-                data_source=data_source,
-            ))
-        devices_list = get_list_of_devices(topology_data[device]['connections'])
-        for entry in devices_list:
-            if entry not in devices_done:
-                devices_to_go.append(entry)
+        # topo_data = get_inventory_data_lq(host=device, path=path_in_inventory, debug=debug)
+        topo_data = HOST_CACHE.get_data(host=device, source=CacheSources.inventory, path=path_in_inventory)
+        if topo_data:
+            topology_data.update(
+                create_device_from_inv(
+                    host=device,
+                    inv_data=topo_data,
+                    inv_columns=inv_columns,
+                    data_source=data_source,
+                ))
+            devices_list = get_list_of_devices(topology_data[device]['connections'])
+            for entry in devices_list:
+                if entry not in devices_done:
+                    devices_to_go.append(entry)
 
         devices_to_go = list(set(devices_to_go))
         devices_done.append(device)
@@ -297,26 +260,12 @@ def create_topology(
 
 
 if __name__ == '__main__':
-    SETTINGS = Settings(vars(parse_arguments(CREATE_TOPOLOGY_VERSION)))
-
-    if SETTINGS.version:
-        print(f'{Path(__file__).name} version: {CREATE_TOPOLOGY_VERSION}')
-        exit(code=ExitCodes.ok)
-
-    if SETTINGS.check_user_data_only:
-        user_data = get_data_from_toml(file=SETTINGS.user_data_file)
-        print(f'Could read/parse the user data from {SETTINGS.user_data_file}')
-        exit(code=ExitCodes.OK)
-
-    if SETTINGS.merge:
-        _merge = list(set(SETTINGS.merge.copy()))
-        if len(_merge) != len(SETTINGS.merge):
-            print(f'-m/--merge options must be unique. Use "-m cdp lldp" oder "-m lldp cdp"')
-            exit(code=ExitCodes.BAD_OPTION_LIST)
+    start_time = time_ns()
+    SETTINGS = Settings(vars(parse_arguments()))
+    HOST_CACHE = HostCache()
 
     print()
     print(f'Start time: {strftime(SETTINGS.time_format)}')
-    start_time = time_ns()
 
     user_data = get_data_from_toml(file=SETTINGS.user_data_file)
     HOST_MAP = user_data.get('HOST_MAP', {})
@@ -353,7 +302,7 @@ if __name__ == '__main__':
         remove_old_data(
             keep=SETTINGS.keep,
             min_age=SETTINGS.min_age,
-            path=Path(f'{SETTINGS.omd_root}/{SETTINGS.topology_save_path}'),
+            path=f'{SETTINGS.omd_root}/{SETTINGS.topology_save_path}',
             protected=user_data.get('PROTECTED_TOPOLOGIES', []),
         )
 
diff --git a/bin/topology_data/create_topology_data.toml b/bin/topology_data/create_topology_data.toml
old mode 100755
new mode 100644
index 5e31d3db6e75ea61380aef1877a373424564fa5c..9e1c7c889b60b49a3aa610bde79ee3d2866a0405
--- a/bin/topology_data/create_topology_data.toml
+++ b/bin/topology_data/create_topology_data.toml
@@ -14,33 +14,33 @@
 
 # list of (additional to -s/--seed-devices) seed devices
 SEED_DEVICES = [
-    "CORE01",
-    "LOCATION01",
-    "LOCATION02",
+    # "CORE01",
+    # "LOCATION01",
+    # "LOCATION02",
 ]
 
 # drop neighbours with invalid names
 DROP_HOSTS = [
-    "not advertised",
-     "a nother invalid name",
+    # "not advertised",
+    #  "a nother invalid name",
 ]
 
 # topologies will not be deleted by "--keep"
 PROTECTED_TOPOLOGIES = [
-    "2023-10-17T14:08:05.10",
-    "your_important_topology"
+    # "2023-10-17T14:08:05.10",
+    # "your_important_topology"
 ]
 
 # user defined static connections
 # connections will be added from host to neighbour and in reverese
 # hosts/neighbours in this section will be added to SEED_DEVICES
 STATIC_CONNECTIONS = [
-    ["cmk_host1", "local-port1", "neighbour-port1", "neighbour1", "label"],
-    ["cmk_host1", "local-port2", "neighbour-port2", "neighbour2", "label"],
+    # ["cmk_host1", "local-port1", "neighbour-port1", "neighbour1", "label"],
+    # ["cmk_host1", "local-port2", "neighbour-port2", "neighbour2", "label"],
 ]
 
 # map inventory neighbour name to Checkmk host name
 [HOST_MAP]
-inventory_neighbour1 = "cmk_host1"
-inventory_neighbour2 = "cmk_host2"
-inventory_neighbour3 = "cmk_host3"
+# inventory_neighbour1 = "cmk_host1"
+# inventory_neighbour2 = "cmk_host2"
+# inventory_neighbour3 = "cmk_host3"
diff --git a/bin/topology_data/create_topology_utils.py b/bin/topology_data/create_topology_utils.py
index bf6776fea969bb46e7e688d8f998ccdd950b21d0..ab4bda85f339f9cde288e512731e72ede04e6444 100755
--- a/bin/topology_data/create_topology_utils.py
+++ b/bin/topology_data/create_topology_utils.py
@@ -37,12 +37,7 @@ from tomllib import loads as toml_loads
 from tomllib import TOMLDecodeError
 from re import match as re_match
 from pathlib import Path
-from typing import List, Dict
-from argparse import (
-    Namespace as arg_Namespace,
-    ArgumentParser,
-    RawTextHelpFormatter,
-)
+from typing import List, Dict, Any
 from enum import Enum, unique
 
 
@@ -53,15 +48,19 @@ class ExitCodes(Enum):
     BAD_TOML_FORMAT = 3
 
 
-script = '~/local/bin/network-topology/create_topology_data.py'
-sample_seeds = 'Core01 Core02'
-cdp_path = 'networking,cdp_cache'
-cdp_columns = 'device_id,local_port,device_port'
-cdp_label = 'inv_CDP'
-lldp_path = 'networking,lldp_cache'
-lldp_columns = 'system_name,local_port_num,port_id'
-lldp_label = 'inv_LLDP'
-user_data_file = 'create_topology_data.toml'
+# constants
+CREATE_TOPOLOGY_VERSION = '0.0.9-202310127'
+SCRIPT = '~/local/bin/network-topology/create_topology_data.py'
+SAMPLE_SEEDS = 'Core01 Core02'
+PATH_CDP = 'networking,cdp_cache'
+PATH_LLDP = 'networking,lldp_cache'
+PATH_INTERFACES = 'networking,interfaces'
+LABEL_CDP = 'inv_CDP'
+LABEL_LLDP = 'inv_LLDP'
+COLUMNS_LLDP = 'system_name,local_port_num,port_id'
+COLUMNS_CDP = 'device_id,local_port,device_port'
+USER_DATA_FILE = 'create_topology_data.toml'
+LQ_INTERFACES = 'interface_items'
 
 
 def get_data_form_live_status(query: str):
@@ -91,7 +90,7 @@ def get_data_from_toml(file: str, debug: bool = False) -> Dict:
         except TOMLDecodeError as e:
             print(
                 f'ERROR: data file {toml_file} is not in valid TOML format! ({e}), (see https://toml.io/en/)')
-            exit(code=ExitCodes.BAD_TOML_FORMAT)
+            exit(code=ExitCodes.BAD_TOML_FORMAT.value)
     else:
         print(f'WARNING: User data {file} not found.')
     if debug:
@@ -113,7 +112,8 @@ def rm_tree(root: Path):
     root.rmdir()
 
 
-def remove_old_data(keep: int, min_age: int, path: Path, protected: List[str], debug: bool = False):
+def remove_old_data(keep: int, min_age: int, path: str, protected: List[str], debug: bool = False):
+    path = Path(path)
     default_topo = path.joinpath('default')
     directories = [str(directory) for directory in list(path.iterdir())]
     # keep default top
@@ -317,131 +317,46 @@ def is_equal_with_default(data: Dict, file: str) -> bool:
         return compare_dicts(data, default_data)
 
 
-def parse_arguments(create_topology_version: str) -> arg_Namespace:
-    parser = ArgumentParser(
-        prog='create_topology_data.py',
-        description='This script creates the topology data file needed for the Checkmk "network_visualization"\n'
-                    'plugin by Andreas Boesl and schnetz. For more information see\n'
-                    'the announcement from schnetz: https://forum.checkmk.com/t/network-visualization/41680\n'
-                    'and the plugin on the Exchange: https://exchange.checkmk.com/p/network-visualization .\n'
-                    '\n'
-                    'The required inventory data can be created with my inventory plugins:\n'
-                    'CDP: https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_cdp_cache\n'
-                    'LLDP: https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/inventory/inv_lldp_cache\n'
-                    '\n'
-                    f'\nVersion: {create_topology_version} | Written by: thl-cmk\n'
-                    f'for more information see: https://thl-cmk.hopto.org',
-        formatter_class=RawTextHelpFormatter,
-        epilog='Usage:\n'
-               'for CDP (the default):\n'
-               f'{script} -s {sample_seeds} -d\n'
-               'for LLDP:\n'
-               f'{script} -s {sample_seeds} -d --lldp\n',
-    )
-    command_group = parser.add_mutually_exclusive_group()
+def get_inventory_data(host: str, debug: bool = False, ) -> Dict[str, str] | None:
+    query = f'GET hosts\nColumns: mk_inventory\nOutputFormat: python3\nFilter: host_name = {host}\n'
+    data = get_data_form_live_status(query=query)
 
-    parser.add_argument(
-        '-d', '--default', default=False, action='store_const', const=True,
-        help='Set the created topology data as default',
-    )
-    parser.add_argument(
-        '-m', '--merge',
-        nargs=2,
-        choices=['CDP', 'LLDP'],
-        help=f'Merge topologies. This runs the topology creation for CDP and LLDP.\n'
-             f'The topologies are then merged in the specified order.\n'
-             f'I.e. -m CDP LLDP merges the CDP topology into the LLDP topology, overwriting\n'
-             f'the LLDP data in case there are conflicts.\n'
-             f'NOTE: static connection data from the user file will always merged with the\n'
-             f' highest priority',
-    )
-    parser.add_argument(
-        '-o', '--output-directory', type=str,
-        help='Directory name where to save the topology data.\n'
-             'I.e.: my_topology. Default is the actual date/time\n'
-             'in "--time-format" format.\n'
-             'NOTE: the directory is a sub directory under "~/var/topology_data/"',
-    )
-    parser.add_argument(
-        '-s', '--seed-devices', type=str, nargs='+',
-        help=f'List of devices to start the topology discovery from.\n'
-             f'I.e. {sample_seeds}',
-    )
-    parser.add_argument(
-        '-u', '--user-data-file', type=str,
-        help='Set the name uf the user provided data file\n'
-             'Default is ~local/bin/topology_data/create_topology_data.toml\n',
-    )
-    parser.add_argument(
-        '-v', '--version', default=False, action='store_const', const=True,
-        help='Print version of this script and exit',
-    )
-    parser.add_argument(
-        '--check-user-data-only', default=False, action='store_const', const=True,
-        help=f'Only tries to read/parse the user data from {user_data_file} and exits.',
-    )
-    parser.add_argument(
-        '--data-source', type=str,
-        help=f'The source from which the topology data originates.\n'
-             f'I.e. {cdp_label} for CDP data from the inventory.\n'
-             'NOTE: right now this only an unused label.',
-    )
-    parser.add_argument(
-        '--debug', default=False, action='store_const', const=True,
-        help='Print debug information',
-    )
-    parser.add_argument(
-        '--dont-compare', default=False, action='store_const', const=True,
-        help='Do not compare the actual topology data with the default topology\n'
-             'data. By default, the actual topology is compared with the default\n'
-             'topology. If the data matches, the actual topology is not saved.\n'
-             'So, if you run this tool in a cron job, a new topology will be\n'
-             'created only if there was a change, unless you use "--dont-compare".'
-    )
-    parser.add_argument(
-        '--inventory-columns', type=str,
-        help=f'Columns used from the inventory data.\n'
-             f'I.e. "{cdp_columns}"\n'
-             'NOTE: the columns must be in the order: neighbour, local_port,\n'
-             'neighbour_port',
-    )
-    parser.add_argument(
-        '--keep-domain', default=False, action='store_const', const=True,
-        help='Do not remove the domain name from the neighbor name',
-    )
-    parser.add_argument(
-        '--keep', type=int,
-        help=f'Number of topologies to keep. The oldest topologies above keep\n'
-             f'max will be deleted. The minimum value for --keep is 1.\n'
-             f'NOTE: The default topologies will be always kept.\n'
-    )
-    parser.add_argument(
-        '--lldp', default=False, action='store_const', const=True,
-        help=f'Sets data source to {lldp_label}, inventory path \n'
-             f'to "{lldp_path}" and columns\n'
-             f'to "{lldp_columns}"',
-    )
-    command_group.add_argument(
-        '--lowercase', default=False, action='store_const', const=True,
-        help='Change neighbour names to all lower case',
-    )
-    parser.add_argument(
-        '--min-age', type=int,
-        help=f'The minimum number of days before a topology is deleted\n'
-             f'by "--keep".\n'
-             f'NOTE: Topologies that are not older than 1 days are always kept.',
-    )
-    parser.add_argument(
-        '--path-in-inventory', type=str,
-        help=f'Checkmk inventory path to the topology data.\n'
-             f'I.e. "{cdp_path}"',
-    )
-    parser.add_argument(
-        '--time-format', type=str,
-        help='Format string to render the time. (default: %%Y-%%m-%%dT%%H:%%M:%%S.%%m)',
-    )
-    command_group.add_argument(
-        '--uppercase', default=False, action='store_const', const=True,
-        help='Change neighbour names to all upper case',
+    if data:
+        try:
+            data = literal_eval(data[0][0].decode('utf-8'))
+        except SyntaxError as e:
+            if debug:
+                print(f'data: |{data}|')
+                print(f'type: {type(data)}')
+                print(f'exception: {e}')
+            return
+        return data
+
+
+def get_table_from_inventory(inventory: Dict[str, Any], path: List[str]) -> List | None:
+    path = ('Nodes,' + ',Nodes,'.join(path.split(',')) + ',Table,Rows').split(',')
+    table = inventory.copy()
+    for m in path:
+        try:
+            table = table[m]
+        except KeyError:
+            return
+    return table
+
+
+def get_interface_items_from_lq(host: str, debug: bool = False) -> List:
+    query = (
+        'GET services\n'
+        'Columns: host_name description check_command\n'
+        'Filter: description ~ Interface\n'
+        f'Filter: host_name = {host}\n'
+        'OutputFormat: python3\n'
     )
-    return parser.parse_args()
+    data = get_data_form_live_status(query=query)
+    items = []
+    for host, description, check_command in data:
+        items.append(description[10:])  # remove 'Interface ' from description
+
+    if debug:
+        print(f'Interfaces items found: {len(items)} an host {host}')
+    return items
diff --git a/mkp/create_topology_data-0.0.9-20231027.mkp b/mkp/create_topology_data-0.0.9-20231027.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..f47d7e12ba7db7499e18557f65dab4193738595a
Binary files /dev/null and b/mkp/create_topology_data-0.0.9-20231027.mkp differ
diff --git a/packages/create_topology_data b/packages/create_topology_data
index 85ce824cda9156d9599bf186b03c70a55e9aab33..e181976999ddb68f7e71290f19e4b3984d665410 100644
--- a/packages/create_topology_data
+++ b/packages/create_topology_data
@@ -53,10 +53,11 @@
  'files': {'bin': ['topology_data/create_topology_classes.py',
                    'topology_data/create_topology_data.py',
                    'topology_data/create_topology_utils.py',
-                   'topology_data/create_topology_data.toml']},
+                   'topology_data/create_topology_data.toml',
+                   'topology_data/create_topology_args.py']},
  'name': 'create_topology_data',
  'title': 'Network Visualization data creation',
- 'version': '0.0.8-20231020',
+ 'version': '0.0.9-20231027',
  'version.min_required': '2.2.0p1',
  'version.packaged': '2.2.0p11',
  'version.usable_until': '2.3.0p1'}