From dfba150bd67eaafaa976453ca44402187e0d6d09 Mon Sep 17 00:00:00 2001 From: localhorst Date: Thu, 2 Mar 2023 21:00:29 +0100 Subject: [PATCH] parse all metrics from payload --- .gitignore | 155 ++++++++++++++++++++++++++++++++++++++- README.md | 75 +++++++++++++++++++ msv_clubhouse_backend.py | 54 ++++++++++---- 3 files changed, 270 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index cfdef90..9fa915b 100644 --- a/.gitignore +++ b/.gitignore @@ -113,4 +113,157 @@ dkms.conf *.out *.app -config.py +# ---> Python +# 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/ +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 + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__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/README.md b/README.md index 35af250..3a85b12 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,78 @@ TTN LoRa frequency / region `pip3 install paho-mqtt` + +JS Payload Formatter: + +``` +function Decoder(bytes, port) { + var decoded = {}; + + // temperature + rawTemp = bytes[0] + bytes[1] * 256; + decoded.degreesC = sflt162f(rawTemp) * 100; + + // pressure + rawPressure = bytes[2] + bytes[3] * 256; + decoded.pressure = sflt162f(rawPressure) * 100; + + // windspeed + rawWindspeed = bytes[4] + bytes[5] * 256; + decoded.windspeed = sflt162f(rawWindspeed) * 100; + + // winddirection + rawWinddirection = bytes[6] + bytes[7] * 256; + decoded.winddirection = sflt162f(rawWinddirection) * 100; + + if(bytes[8] === 0){ + decoded.dooropen = false; + }else{ + decoded.dooropen = true; + } + + + return decoded; +} + +function sflt162f(rawSflt16) + { + // rawSflt16 is the 2-byte number decoded from wherever; + // it's in range 0..0xFFFF + // bit 15 is the sign bit + // bits 14..11 are the exponent + // bits 10..0 are the the mantissa. Unlike IEEE format, + // the msb is transmitted; this means that numbers + // might not be normalized, but makes coding for + // underflow easier. + // As with IEEE format, negative zero is possible, so + // we special-case that in hopes that JavaScript will + // also cooperate. + // + // The result is a number in the open interval (-1.0, 1.0); + // + + // throw away high bits for repeatability. + rawSflt16 &= 0xFFFF; + + // special case minus zero: + if (rawSflt16 == 0x8000) + return -0.0; + + // extract the sign. + var sSign = ((rawSflt16 & 0x8000) !== 0) ? -1 : 1; + + // extract the exponent + var exp1 = (rawSflt16 >> 11) & 0xF; + + // extract the "mantissa" (the fractional part) + var mant1 = (rawSflt16 & 0x7FF) / 2048.0; + + // convert back to a floating point number. We hope + // that Math.pow(2, k) is handled efficiently by + // the JS interpreter! If this is time critical code, + // you can replace by a suitable shift and divide. + var f_unscaled = sSign * mant1 * Math.pow(2, exp1 - 15); + + return f_unscaled; + } + ``` \ No newline at end of file diff --git a/msv_clubhouse_backend.py b/msv_clubhouse_backend.py index 546b5c7..fa1ae82 100644 --- a/msv_clubhouse_backend.py +++ b/msv_clubhouse_backend.py @@ -58,10 +58,9 @@ class RequestHandler(BaseHTTPRequestHandler): self.wfile.write(bytes("", "utf-8")) def update_metrics(payload, metadata): - print("Payload: "+ str(payload)) - print("Metadata: "+ str(metadata)) + #print("Payload: "+ str(payload)) + #print("Metadata: "+ str(metadata)) - print("set data from ttn") global node_metrics global mutex global scrape_healthy @@ -69,17 +68,46 @@ def update_metrics(payload, metadata): scrape_healthy = True node_metrics.clear() - try: - node_metrics.append("target_temperature " + str(int(42))) - node_metrics.append("valve " + str(int(42))) - node_metrics.append("low_battery " + str(int(42))) - node_metrics.append("window_open " + str(int(42))) - except Exception as ex: - print("unable to poll data from TTN! error: " + str(ex)) - scrape_healthy = False - pass + if "degreesC" in payload: + print("set degree: " + str(float(payload["degreesC"]))) + node_metrics.append("temperature " + str(float(payload["degreesC"]))) + + if "pressure" in payload: + print("set pressure: " + str(float(payload["pressure"]))) + node_metrics.append("pressure " + str(float(payload["pressure"]))) + + if "winddirection" in payload: + print("set winddirection: " + str(float(payload["winddirection"]))) + node_metrics.append("winddirection " + str(float(payload["winddirection"]))) + + if "windspeed" in payload: + print("set windspeed: " + str(float(payload["windspeed"]))) + node_metrics.append("windspeed " + str(float(payload["windspeed"]))) + + if "dooropen" in payload: + print("set dooropen: " + str(bool(payload["dooropen"]))) + node_metrics.append("dooropen " + str(int(payload["dooropen"]))) + + # if "gateway_id" in metadata[0]["gateway_ids"]: + # print("set gateway_id: " + str(metadata[0]["gateway_ids"]["gateway_id"])) + # node_metrics.append("gateway_id " + str(metadata[0]["gateway_ids"]["gateway_id"])) + + if "rssi" in metadata[0]: + print("set rssi: " + str(int(metadata[0]["rssi"]))) + node_metrics.append("rssi " + str(int(metadata[0]["rssi"]))) + + if "channel_rssi" in metadata[0]: + print("set channel_rssi: " + str(int(metadata[0]["channel_rssi"]))) + node_metrics.append("channel_rssi " + str(int(metadata[0]["channel_rssi"]))) + + if "snr" in metadata[0]: + print("set snr: " + str(float(metadata[0]["snr"]))) + node_metrics.append("snr " + str(float(metadata[0]["snr"]))) + + + #scrape_healthy = False + mutex.release() - time.sleep(300) def on_connect(mqttc, obj, flags, rc): print("\nConnected to MQTT: rc = " + str(rc))