Commit 78a42ed2 authored by Federico Sismondi's avatar Federico Sismondi

Add hencements to handle battery readings from flower boxes

parent 54ec5dbb
......@@ -144,13 +144,16 @@ def _log_level_of_moisture(cb, sensor):
else:
app.logger.error("Measurement not in expected range: {} cb".format(cb))
def _log_level_of_battery_level(bat, sensor):
if bat < 0.5:
app.logger.warning("{} battery level is critically low: {} %!".format(sensor, bat))
else:
app.logger.info("{} battery level is: {} %".format(sensor, bat))
def _conv_micro_volts_to_moiture_cb(micro_volts):
"""
Lora Bridge device has to channels (A and B).
Only the channel A is connected. To read correctly the value from the channel A, you should take the byte 3 to 5.
Then, you should decoded from Hex to Decimal. IMPORTANT: The value is expressed in µV. (1V = 1.000.000µV)
Sensor Voltage range is from 0V to 3V.
This voltage range is linearly dependent to the real value of the sensor, which is expressed in cb (kPa):
......@@ -159,6 +162,7 @@ def _conv_micro_volts_to_moiture_cb(micro_volts):
:param micro_volts:
:return: pressure (in cb ~ KPa)
"""
assert type(micro_volts) is int
......@@ -168,19 +172,63 @@ def _conv_micro_volts_to_moiture_cb(micro_volts):
return int((micro_volts * 239) / 3000000)
def _get_reading(message_data):
def _conv_micro_volts_to_battery_level(micro_volts):
"""Battery is 0-12v
but is connected with a Voltage divider R1=R2= 5 K ohm
https://en.wikipedia.org/wiki/Voltage_divider
- measured voltage is half on the real value
- measured voltage is in micro volts
hence:
bat_percetage = 100 * (v_input /1.000.000 ) * 2 / 12
:param micro_volts:
:return: battery percentage 0-100%
"""
>>> base64.standard_b64decode("QmABACcnAQAAAA==").hex()
'42600100272701000000'
assert type(micro_volts) is int
if micro_volts == 0:
return 0
return 2 * (micro_volts / 1000000) / 12
def _get_reading(message_data):
""" Lora Bridge device has to channels (A and B).
channel A is connected to moisture sensors
channel B is connected to battery voltage output
To read correctly the value from the channel A, you should take the byte 3 to 5 (included).
To read correctly the value from the channel B, you should take the byte 6 to 8 (included).
Then, you should decoded from Hex to Decimal.
IMPORTANT: The value is expressed in µV if sensor is configured as voltage input (1V = 1.000.000µV)
For more info look at LoRaWAN 863-870 ANALOG PWR - Guide utilisateur / User guide version V2.0.2
>>> base64.standard_b64decode("QsABAqD7AVL5yQ==").hex()
'42c00102a0fb0152f9c9'
# deplexing data:
# 42 -> it's a data frame!
# c0 ->
# 01 -> configured as 0-10v input for channel A
# 02a0fb -> data channel A
# 01 -> configured as 0-10v input for channel A
# 52f9c9 -> data channel B
:param message_data:
:return:
:return: moisture, battery_level
"""
reading_hex = base64.standard_b64decode(message_data).hex()
if reading_hex[0:2] == '42': # it's a dataFrame
return _conv_micro_volts_to_moiture_cb(int(reading_hex[6:12], 16))
moisture = _conv_micro_volts_to_moiture_cb(int(reading_hex[6:12], 16))
battery_level = _conv_micro_volts_to_battery_level(int(reading_hex[14:20], 16))
return moisture, battery_level
else:
msg = 'Not a sensor reading (expected 0x42) {}'.format(reading_hex)
......@@ -245,6 +293,7 @@ def _update_device_entity(deveui, comment, longitude, latitude, last_reception,
-value
-location
-rssi
-batteryLevel
NOTES:
name is regexed from LoRa platform <comment> field of device,
......@@ -299,7 +348,10 @@ def _update_device_entity(deveui, comment, longitude, latitude, last_reception,
app.logger.warning("No date parsed for updaging Device field: dateLastValueReported")
if dataFrame:
body.update({'value': get_ngsiv2_typed_description(_get_reading(dataFrame))})
moist, bat = _get_reading(dataFrame)
body.update({'value': get_ngsiv2_typed_description(moist)})
body.update({'batteryLevel': get_ngsiv2_typed_description(bat)})
if dataFrame_rssi:
body.update({'rssi': get_ngsiv2_typed_description(dataFrame_rssi)})
......@@ -365,10 +417,13 @@ 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']
soil_humidity, battery_level = _get_reading(request.json['dataFrame'])
sensor_eui = request.json['deveui']
# log reading
_log_level_of_moisture(soil_humidity, sensor_eui)
_log_level_of_battery_level(battery_level,sensor_eui)
# saves locally and pushed data to FlowerBed and Device entities
resp = {}
......
......@@ -115,41 +115,40 @@ attrs = {
# entities ids per pilot tuples
entities = [
# prediction use case - weather observed (current)
# weather prediction use case - weather observed (current)
('urn:ngsi-ld:WeatherObserved:WeatherObserved', ['carouge', 'braila']),
#('urn:ngsi-ld:WeatherObserved:WeatherObserved-1', ['alicante']),
#('urn:ngsi-ld:WeatherObserved:WeatherObserved-2', ['alicante']),
('urn:ngsi-ld:WeatherObserved:WeatherObserved-1', ['alicante']),
('urn:ngsi-ld:WeatherObserved:WeatherObserved-2', ['alicante']),
# forecast today
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-0', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-1', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-2', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-3', ['carouge', 'alicante', 'braila']),
# forecast tomorrow
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-0', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-1', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-2', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-3', ['carouge', 'alicante', 'braila']),
# forecast tomorrow
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-0', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-1', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-2', ['carouge', 'alicante', 'braila']),
('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-3', ['carouge', 'alicante', 'braila']),
# watering use case - flower beds
('urn:ngsi-ld:FlowerBed:FlowerBed-1', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-2', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-3', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-4', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-5', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-6', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-7', ['carouge']),
('urn:ngsi-ld:FlowerBed:FlowerBed-8', ['carouge']),
# water quality use cases
("urn:ngsi-ld:WaterQualityObserved:Fountain-1", ['carouge']),
("urn:ngsi-ld:WaterQualityObserved:WaterTreatmentPlant", ['wtp_lab']),
# # prediction use case - forecast today
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-0', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-1', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-2', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day0-3', ['carouge', 'alicante', 'braila']),
# #
# # # prediction use case - forecast tomorrow
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-0', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-1', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-2', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day1-3', ['carouge', 'alicante', 'braila']),
# #
# # # prediction use case - forecast tomorrow
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-0', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-1', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-2', ['carouge', 'alicante', 'braila']),
# ('urn:ngsi-ld:WeatherForecast:WeatherForecast-Day2-3', ['carouge', 'alicante', 'braila']),
#
# # watering use case - flower beds
# ('urn:ngsi-ld:FlowerBed:FlowerBed-1', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-2', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-3', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-4', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-5', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-6', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-7', ['carouge']),
# ('urn:ngsi-ld:FlowerBed:FlowerBed-8', ['carouge']),
]
# http headers
......
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