From 661023cf7934bf3b34f341af1c866d37352f8286 Mon Sep 17 00:00:00 2001 From: Rob Lee Date: Mon, 6 Apr 2020 21:27:29 +0100 Subject: [PATCH] Initial commit --- .gitignore | 141 +++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 10 +++ README.md | 33 ++++++++++ huwawei_lte_exporter | 79 ++++++++++++++++++++++++ requirements.txt | 1 + 5 files changed, 264 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100755 huwawei_lte_exporter create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d13a73e --- /dev/null +++ b/.gitignore @@ -0,0 +1,141 @@ +build.sh + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..eb8ec43 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3 + +WORKDIR /usr/src/huwawei_lte_exporter + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD [ "python", "./huwawei_lte_exporter" ] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..17570c9 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +## huawei_let_exporter + +# Install + +``` +docker build -t huawei_lte_exporter . + +export ROUTER_ADDRESS=192.168.8.1 +export ROUTER_USER=admin +export ROUTER_PASS=admin +export PROM_PORT=8080 + +docker run -d -it -p $PROM_PORT:$PROM_PORT --name=hle huawei_lte_exporter +sleep 5 +curl http://localhost:$PROM_PORT + +HELP band The signal band the LTE connection is using +TYPE band gauge +band{deviceName="B535-232",iccid="111"} 1 +HELP rsrp The average power received from a single Reference signal, and Its typical range is around -44dbm (good) to -140dbm(bad) +TYPE rsrp gauge +rsrp{deviceName="B535-232",iccid="111"} -98 +HELP rsrq Indicates quality of the received signal, and its range is typically -19.5dB(bad) to -3dB (good) +TYPE rsrq gauge +rsrq{deviceName="B535-232",iccid="111"} -10.0 +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 +TYPE rssi gauge +rssi{deviceName="B535-232",iccid="111"} -71 +HELP sinr The signal-to-noise ratio of the given signal in dB +TYPE sinr gauge +rsrq{deviceName="B535-232",iccid="111"} 11 +``` + diff --git a/huwawei_lte_exporter b/huwawei_lte_exporter new file mode 100755 index 0000000..af1cc7d --- /dev/null +++ b/huwawei_lte_exporter @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +import os +import pprint +import http.server as SimpleHTTPServer +import socketserver as SocketServer +from huawei_lte_api.Client import Client +from huawei_lte_api.AuthorizedConnection import AuthorizedConnection +from huawei_lte_api.Connection import Connection + +def prom_exporter(): + MANDATORY_ENV_VARS = ["ROUTER_ADDRESS", "ROUTER_USER", "ROUTER_PASS", "PROM_PORT"] + for var in MANDATORY_ENV_VARS: + if var not in os.environ: + raise EnvironmentError("Failed because {} is not set.".format(var)) + + # 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 + + dev = 'deviceName="'+ client.device.information().get('DeviceName')+'",iccid="'+client.device.information().get('Iccid')+'"' + 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", "") + } + + # 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 + + response=[] + # Band + 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 + 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{'+dev+'} '+signal.get('rsrp')) + # rsrq + 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{'+dev+'} '+signal.get('rsrq')) + # rssi + 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{'+dev+'} '+signal.get('rssi')) + # sinr + response.append('HELP sinr The signal-to-noise ratio of the given signal in dB') + response.append('TYPE sinr gauge') + response.append('rsrq{'+dev+'} '+signal.get('sinr')) + s='\n' + return s.join(response) + + +class GetHandler( + SimpleHTTPServer.SimpleHTTPRequestHandler + ): + + def do_GET(self): + self.send_response(200) + self.end_headers() + self.wfile.write(prom_exporter().encode()) + + + +Handler = GetHandler +httpd = SocketServer.TCPServer(("", int(os.environ.get('PROM_PORT'))), Handler) + +httpd.serve_forever() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2772624 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +huawei-lte-api