From 519c68c455961042b282db94a94f0fad0fa2e965 Mon Sep 17 00:00:00 2001 From: clerie Date: Sat, 19 Jun 2021 11:05:35 +0200 Subject: [PATCH] Initial commit --- LICENSE | 21 +++++++++++++++++ README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++ iot_data/__init__.py | 54 +++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + setup.py | 18 +++++++++++++++ 5 files changed, 149 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 iot_data/__init__.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..26c2c20 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 clerie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c3d78c --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# IOT Data + +Just a tiny service for posting small datasets to a server which can get fetched by other services afterwards. + +It just keeps the data in RAM so it is definetely not for big stuff and log term storages. + +## Usage + +Read data: +``` +curl http://iot-data.clerie.de/data/sensor1/ +``` + +Write data: +``` +curl -X POST -d 'hello world!'' -H 'Content-Type: text/plain' http://iot-data.clerie.de/ingress/asdf1234/ +``` + +Content type is considered too: +``` +curl -X POST -d '{"key": "value"}' -H 'Content-Type: application/json' http://iot-data.clerie.de/ingress/asdf1234/ +``` + +## Deployment +Init codebase +``` +git clone https://github.com/clerie/iot-data.git +cd iot-data/ +virtualenv -p python3 ENV +cd .. +``` + +Create `config.json` with the following contents and edit values for your needs: + +``` +{ + "sensor1": { + "key": "asdf1234" + }, + "sensor2": { + "key": "supersecret" + }, +} + +``` + +Starten und updaten lässt sich die Flask-App folgendermaßen: +``` +cd iot-data/ +git pull +source ENV/bin/activate +pip install -r requirements.txt +IOT_DATA_CONFIG=/path/to/config.json gunicorn iot_data:app +deactivate +``` diff --git a/iot_data/__init__.py b/iot_data/__init__.py new file mode 100644 index 0000000..fc35800 --- /dev/null +++ b/iot_data/__init__.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +from flask import Flask, abort, request, make_response +import json +import os + +app = Flask(__name__) + +values = {} + +config = {} + +if "IOT_DATA_CONFIG" in os.environ: + config = json.loads(open(os.environ["IOT_DATA_CONFIG"]).read()) + +# just make the key lookup faster +keys = {} +for name, c in config.items(): + if "key" in c: + if c["key"] in keys: + raise Exception("Keys need to be unique") + else: + keys[c["key"]] = name + +@app.route("/ingress//", methods=["POST"]) +def ingress(key): + if key in keys: + content_type = "text/plain" + if "content-type" in request.headers: + content_type = request.headers["content-type"] + + values[keys[key]] = { + "payload": request.data, + "content-type": content_type, + } + else: + abort(401) + + resp = make_response("", 201) + return resp + +@app.route("/data//") +def data(name): + if not name in config: + abort(404) + if not name in values: + resp = make_response("", 204) + return resp + resp = make_response(values[name]["payload"], 200) + resp.headers['content-type'] = values[name]["content-type"] + return resp + +if __name__ == "__main__": + app.run(debug=True) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..015f37a --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name="iot-data", + version="0.0.1", + author="clerie", + author_email="hallo@clerie.de", + description="IOT Data", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://git.clerie.de/clerie/iot-data", + packages=setuptools.find_packages(), +)