131 lines
3.9 KiB
Python
131 lines
3.9 KiB
Python
import flask
|
|
import logging
|
|
import json
|
|
import threading
|
|
|
|
from spejsiot.manager import SpejsiotManager
|
|
from spejsiot.rendering import render_endpoint
|
|
|
|
logging.basicConfig(level=logging.DEBUG, format='[%(asctime)-15s] %(name)-10s %(levelname)7s: %(message)s')
|
|
|
|
app = flask.Flask(__name__)
|
|
app.config['DISABLE_GUI'] = True
|
|
app.config['PORT'] = 5100
|
|
app.config['BROKER'] = ('mqtt.waw.hackerspace.pl', 1883)
|
|
app.config['PREFIX'] = 'iot/'
|
|
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
|
|
|
manager = SpejsiotManager(app)
|
|
|
|
@app.context_processor
|
|
def utility_processor():
|
|
return {
|
|
'render_endpoint': render_endpoint,
|
|
}
|
|
|
|
@app.route('/')
|
|
def index():
|
|
if app.config.get('DISABLE_GUI'):
|
|
return flask.redirect(flask.url_for(
|
|
'static', filename='apidocs/index.html'))
|
|
|
|
return flask.render_template('index.html', devices=manager.devices)
|
|
|
|
def prometheus_sanitize(v):
|
|
return v.encode('unicode_escape').decode('utf-8')
|
|
|
|
def prometheus_value(v):
|
|
return float(v)
|
|
|
|
@app.route('/metrics')
|
|
def metrics():
|
|
proplist = []
|
|
|
|
for _, dev in manager.devices.items():
|
|
if not dev.online:
|
|
continue
|
|
|
|
for endpoint_id, props in dev.endpoints.items():
|
|
for property_id, value in props.items():
|
|
if property_id.startswith('$'):
|
|
continue
|
|
try:
|
|
proplist.append('spejsiot{node_id="%s", name="%s", ' \
|
|
'endpoint="%s", property="%s"} %s' % (
|
|
prometheus_sanitize(dev.node_id),
|
|
prometheus_sanitize(dev.name),
|
|
prometheus_sanitize(endpoint_id),
|
|
prometheus_sanitize(property_id),
|
|
prometheus_value(value),
|
|
))
|
|
except ValueError:
|
|
# This is most probably just a string value
|
|
continue
|
|
return '\n'.join(proplist), 200, {
|
|
'Content-Type': 'text/plain; version=0.0.4',
|
|
}
|
|
|
|
@app.route('/api/1/devices/')
|
|
def api_devices():
|
|
"""Lists all known devices.
|
|
|
|
:status 200: list of all devices
|
|
:>json object [device_id]: listed device info object
|
|
"""
|
|
|
|
return flask.jsonify({k: v.dictify() for k, v in manager.devices.items()})
|
|
|
|
@app.route('/api/1/devices/<node_id>/')
|
|
def api_device_info(node_id):
|
|
"""Returns specified device info object.
|
|
|
|
:param node_id: device ID or device name
|
|
:status 200: device found
|
|
:status 404: no device found
|
|
|
|
:>json string $name: human-readable device name
|
|
:>json boolean $online: device is currently online
|
|
:>json object [endpoint_name]: endpoint object
|
|
:>json [endpoint_name].[prop_name]: last endpoint property value
|
|
"""
|
|
node = manager.find_node(node_id)
|
|
|
|
if not node:
|
|
flask.abort(404)
|
|
|
|
return flask.jsonify(node.dictify())
|
|
|
|
# @app.route('/api/1/device/<node_id>/<endpoint>/<prop>/<value>')
|
|
@app.route('/api/1/devices/<node_id>/<endpoint>/<prop>/<value>')
|
|
def device_write(node_id, endpoint, prop, value):
|
|
"""Sets specified value to device endpoint and prop.
|
|
|
|
:param node_id: device ID or device name
|
|
:param endpoint: endpoint name
|
|
:param prop: endpoint property name
|
|
:param value: value to set
|
|
:status 200: device found
|
|
:status 404: no device found
|
|
"""
|
|
return flask.jsonify({
|
|
"result": manager.handle_request(node_id, endpoint, prop, value)
|
|
})
|
|
|
|
@app.route('/api/1/devices/<node_id>/<endpoint>/<prop>', methods=['PUT'])
|
|
def device_put(node_id, endpoint, prop):
|
|
"""Sets specified value to device endpoint and prop.
|
|
|
|
:param node_id: device ID or device name
|
|
:param endpoint: endpoint name
|
|
:param prop: endpoint property name
|
|
:<json value: value to set
|
|
:status 200: device found
|
|
:status 404: no device found
|
|
"""
|
|
return device_write(node_id, endpoint, prop, flask.request.json['value'])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
manager.run(*app.config['BROKER'])
|
|
app.run(port=app.config['PORT'])
|