Commit 0ab5e317 authored by Federico Sismondi's avatar Federico Sismondi

Add() feature for pushing sensor humitity values to FlowerBed if refSensor is defined and matches

parent 0ac7310b
#!/usr/bin/env python3
"""
Initializes FlowerBoxes data using LoRa platform metadata about sensors.
Listens to LoRa platform POSTS (sensor readings), reformats data, and forwards to IoT platform.
In simple words this module:
- Initializes Device entities
- Updates Device and Flowerbed entities' attributes.
# datetime for now should be datetime.datetime.now(datetime.timezone.utc).isoformat().replace("+00:00", "Z")
"""
import re
import os
......@@ -40,10 +44,17 @@ h = {'Authorization': secret}
URN_BASE_DEVICE_ENTITY = "urn:ngsi-ld:Device:Device-"
URN_BASE_FLOWERBED_ENTITY = "urn:ngsi-ld:FlowerBed:FlowerBed-"
# build header for IoT platform POSTs
# build header for POST
http_header_post = {
'Fiware-Service': 'carouge',
'Content-Type': 'application/json',
'Accept': 'application/json',
}
# build header for GET
http_header_get = {
'Fiware-Service': 'carouge',
'Accept': 'application/json',
}
......@@ -53,13 +64,13 @@ def get_ngsiv2_typed_description(val):
elif isinstance(val, int) or isinstance(val, float):
return {'type': 'Number', 'value': val}
elif isinstance(val, str):
pat=r'[<>"\'=;()]' # see https://fiware-orion.readthedocs.io/en/master/user/forbidden_characters/index.html
pat = r'[<>"\'=;()]' # see https://fiware-orion.readthedocs.io/en/master/user/forbidden_characters/index.html
r = re.compile(pat)
if r.search(val) is None:
new_val = val
else:
new_val = re.sub(pat, '',val)
app.logger.warning("Special char(s) deleted. This <{}> turned into this <{}>".format(val,new_val))
new_val = re.sub(pat, '', val)
app.logger.warning("Special char(s) deleted. This <{}> turned into this <{}>".format(val, new_val))
return {'type': 'Text', 'value': new_val}
elif isinstance(val, datetime.datetime):
# replace +00:00 is the same as Z but Orion doesnt like it :/
......@@ -178,9 +189,47 @@ def _get_reading(message_data):
# = = = = = = = = CONTEXT BROKER FUNCTIONS = = = = = = = =
def _update_flowerbed_entity(soil_moisture, sensor_eui):
flowerbed_id = None
# check if refDevice attr defined for any FlowerBed
url = "{}/v2/entities/?q=refDevice=={}&type=FlowerBed".format(URL_BASE, sensor_eui)
r = client_request.get(
url=url,
headers=http_header_get
)
if r.ok and r.json():
flowerbed_id = r.json()[0]['id']
if not flowerbed_id:
msg = 'No FlowerBed associated to sensor {}'.format(sensor_eui)
app.logger.warning(msg)
return msg
app.logger.debug('Found FlowerBed {} associated to sensor {}'.format(flowerbed_id, sensor_eui))
url = "{}/v2/entities/{}/attrs".format(URL_BASE, flowerbed_id)
r = client_request.patch(
url=url,
headers=http_header_post,
payload={
"soilMoisture": get_ngsiv2_typed_description(soil_moisture)
}
)
if not (200 <= r.status_code < 300):
app.logger.error('HTTP status code not 2xx, something went wrong..')
app.logger.error(r.status_code)
app.logger.error(r.reason)
app.logger.error(r.json())
return "Got error {}".format(r.reason)
else:
app.logger.info('HTTP response is {} - Entity updated'.format(r.status_code))
return "ok"
def _forward_lora_dev_data_to_ctx_broker(deveui, comment, longitude, latitude, last_reception, dataFrame,
dataFrame_rssi, dataFrame_timestamp):
def _update_device_entity(deveui, comment, longitude, latitude, last_reception, dataFrame,
dataFrame_rssi, dataFrame_timestamp):
""" Creates/Updates LoRa devs into ctx broker
Output Data model:
......@@ -314,12 +363,17 @@ def post_dca_carouge_watering_sensed_data_test():
@app.route('/dca-carouge-watering-sensed-data/rest/callback/payloads/ul', methods=['POST'])
def post_dca_carouge_watering_sensed_data_payload():
# get values
soil_humidity, sensor_eui = _get_reading(request.json['dataFrame']), request.json['deveui']
# log reading
_log_level_of_moisture(_get_reading(request.json['dataFrame']),request.json['deveui'],)
# forward reading to CTX BROKER
_log_level_of_moisture(soil_humidity, sensor_eui)
# push data to context broker
resp = {}
resp.update({"fs_dump": _dump_raw_data_to_filesystem()})
resp.update({"update_devices_entities": _forward_lora_dev_data_to_ctx_broker(
resp.update({"update_flowerbed_entities": _update_flowerbed_entity(soil_humidity, sensor_eui)})
resp.update({"update_device_entities": _update_device_entity(
deveui=request.json['deveui'],
comment=None,
longitude=None,
......@@ -329,9 +383,10 @@ def post_dca_carouge_watering_sensed_data_payload():
dataFrame_rssi=request.json['rssi'],
dataFrame_timestamp=request.json['timestamp']
)})
# resp.update({'description': _dummy_post_handler()})
return resp
@app.route('/dca-carouge-watering-sensed-data/rest/callback/nodeinfo', methods=['PUT'])
def put_dca_carouge_watering_sensed_node_info():
_dummy_post_handler()
......@@ -357,7 +412,7 @@ def init():
# push data to CTX broker
for i in lora_nodes_info:
_forward_lora_dev_data_to_ctx_broker(
_update_device_entity(
deveui=i['deveui'],
comment=i['comment'],
longitude=i['longitude'],
......
......@@ -39,8 +39,10 @@ http_header_post = {
}
# build header for GET
http_header_get = http_header_post.copy()
http_header_get.pop('Content-Type')
http_header_get = {
'Fiware-Service': 'carouge',
'Accept': 'application/json',
}
logger.info('Config: \n\tPOST_DATA_PERIOD: {} seconds \n\tURL: {}'.format(POST_DATA_PERIOD, URL_BASE))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment