From bfbda564cc499df5ae33baef703618fd709c3583 Mon Sep 17 00:00:00 2001 From: Rob Lee Date: Thu, 9 Apr 2020 21:08:30 +0100 Subject: [PATCH] Refactored to provide more resilience against null values and added additional signal information to the exporter --- README.md | 2 ++ huwawei_lte_exporter | 76 ++++++++++++++++++-------------------------- 2 files changed, 33 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 9665081..52ce2e1 100644 --- a/README.md +++ b/README.md @@ -63,5 +63,7 @@ Example dashboard [config](/examples/grafana.json) Guage values taken from: https://wiki.teltonika-networks.com/view/Mobile_Signal_Strength_Recommendations +Note: Different operators appear to provide different signal information, so not all values will be available across all operators. The above dashboard works for Three, however not for Vodafonefor example. + ## Todo diff --git a/huwawei_lte_exporter b/huwawei_lte_exporter index 05e5e27..992dd0b 100755 --- a/huwawei_lte_exporter +++ b/huwawei_lte_exporter @@ -16,57 +16,45 @@ def prom_exporter(): # Auth to router conn ='http://'+os.environ.get('ROUTER_USER')+':'+os.environ.get('ROUTER_PASS')+'@'+os.environ.get('ROUTER_ADDRESS')+'/' - #print('Connecting to '+conn) connection = AuthorizedConnection(conn) # Initiatise client client = Client(connection) - pprint.pprint(client.device.signal()) # Can be accessed without authorization - #pprint.pprint(client.device.information()) # Needs valid authorization, will throw exception if invalid credentials are passed in URL + if os.environ.get('VERBOSE') is not None: + pprint.pprint(client.device.signal()) # Can be accessed without authorization + pprint.pprint(client.device.information()) # Needs valid authorization, will throw exception if invalid credentials are passed in URL - signal = { 'band' : client.device.signal().get('band'), - 'rsrp' : client.device.signal().get('rsrp').replace("dBm", ""), - 'rsrq' : client.device.signal().get('rsrq').replace("dB", ""), - 'rssi' : client.device.signal().get('rssi').replace("dBm", ""), - 'sinr' : client.device.signal().get('sinr').replace("dB", "") - } - - dev = 'deviceName="'+ client.device.information().get('DeviceName')+'",iccid="'+client.device.information().get('Iccid')+'"' - devband=dev - if signal.get('band') is not None: - devband = dev+',band="'+signal.get('band')+'"' - - # HELP ifInDiscards The number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being deliverable to a higher-layer protocol - 1.3.6.1.2.1.2.2.1.13 - # TYPE ifInDiscards counter - #ifInDiscards{ifAlias="",ifDescr="atm0",ifIndex="7",ifName=""} 81 + # Set common response attributes + band = client.device.signal().get('band') + device = 'deviceName="'+ client.device.information().get('DeviceName')+'",iccid="'+client.device.information().get('Iccid')+'"' + deviceband = device + if band is not None: + devband = device+',band="'+band+'"' + # Retrieve attributes + signal = { 'band': { 'help': 'The signal band the LTE connection is using', 'type': 'gauge', 'device': device, 'value': band}, + 'rsrp': { 'help': 'The average power received from a single Reference signal in dBm', 'type': 'gauge', 'device': deviceband, 'value': client.device.signal().get('rsrp')}, + 'rsrq': { 'help': 'Indicates quality of the received signal in db', 'type': 'gauge', 'device': deviceband, 'value': client.device.signal().get('rsrq')}, + 'rssi': { 'help': 'Represents the entire received power including the wanted power from the serving cell as well as all co-channel power and other sources of noise in dBm', 'type': 'gauge', 'device': deviceband, 'value': client.device.signal().get('rssi')}, + 'rscp': { 'help': 'Denotes the power measured by a receiver on a particular physical communication channel in dBm', 'type': 'gauge', 'device': deviceband, 'value': client.device.signal().get('rscp')}, + 'sinr': { 'help': 'The signal-to-noise ratio of the given signal in dB', 'type': 'gauge', 'device': deviceband, 'value': client.device.signal().get('sinr')}, + 'ecio': { 'help': 'The EC/IO is a measure of the quality/cleanliness of the signal from the tower to the modem and indicates the signal-to noise ratio in dB', 'type': 'gauge', 'device': deviceband, 'value': client.device.signal().get('ecio')} + } + if os.environ.get('VERBOSE') is not None: + pprint.pprint(signal) + # Cleanse data + for attribute, info in signal.items(): + if info['value'] is not None: + info['value'] = info['value'].replace("dBm", "") + info['value'] = info['value'].replace("dB", "") + # Populate response response=[] - # Band - if signal.get('band') is not None: - response.append('#HELP band The signal band the LTE connection is using') - response.append('#TYPE band gauge') - response.append('band{'+dev+'} '+signal.get('band')) - # rsrp - if signal.get('rsrp') is not None: - response.append('#HELP rsrp The average power received from a single Reference signal, and Its typical range is around -44dbm (good) to -140dbm(bad)') - response.append('#TYPE rsrp gauge') - response.append('rsrp{'+devband+'} '+signal.get('rsrp')) - # rsrq - if signal.get('rsrq') is not None: - response.append('#HELP rsrq Indicates quality of the received signal, and its range is typically -19.5dB(bad) to -3dB (good)') - response.append('#TYPE rsrq gauge') - response.append('rsrq{'+devband+'} '+signal.get('rsrq')) - # rssi - if signal.get('rssi') is not None: - response.append('#HELP rssi Represents the entire received power including the wanted power from the serving cell as well as all co-channel power and other sources of noise in dBm') - response.append('#TYPE rssi gauge') - response.append('rssi{'+devband+'} '+signal.get('rssi')) - # sinr - if signal.get('sinr') is not None: - response.append('#HELP sinr The signal-to-noise ratio of the given signal in dB') - response.append('#TYPE sinr gauge') - response.append('sinr{'+devband+'} '+signal.get('sinr')) + for attribute, info in signal.items(): + if attribute is not None and info['value'] is not None: + response.append('#HELP '+attribute+' '+info['help']) + response.append('#TYPE '+attribute+' '+info['type']) + response.append(attribute+'{'+info['device']+'} '+info['value']) s='\n' return s.join(response) @@ -80,8 +68,6 @@ class GetHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): self.end_headers() self.wfile.write(prom_exporter().encode()) - - Handler = GetHandler httpd = SocketServer.TCPServer(("", int(os.environ.get('PROM_PORT'))), Handler)