410 lines
11 KiB
Python
410 lines
11 KiB
Python
# Copyright 2017 MDSLAB - University of Messina
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from iotronic_lightningrod.plugins import Plugin
|
|
from iotronic_lightningrod.plugins import pluginApis as API
|
|
|
|
from oslo_log import log as logging
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
# User imports
|
|
import datetime
|
|
import json
|
|
import math
|
|
import threading
|
|
import time
|
|
|
|
# User global variables
|
|
ckan_addr = 'smartme-data.unime.it'
|
|
action_URL = "http://" + ckan_addr + "/api/3/action/datastore_upsert"
|
|
api_key = '22c5cfa7-9dea-4dd9-9f9d-eedf296852ae'
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
'Authorization': "" + api_key + ""
|
|
}
|
|
|
|
sensors_list = [
|
|
'temperature',
|
|
'brightness',
|
|
'humidity',
|
|
'pressure',
|
|
'noise'
|
|
# , 'gas'
|
|
]
|
|
position = None
|
|
|
|
SENSORS = {}
|
|
|
|
location = {}
|
|
|
|
device = API.getBoardGpio()
|
|
|
|
THR_KILL = None
|
|
|
|
|
|
# Sensors gloabl parameters
|
|
|
|
# Temperature Parameters
|
|
ADCres = 1023.0
|
|
Beta = 3950
|
|
Kelvin = 273.15
|
|
Rb = 10000
|
|
Ginf = 120.6685
|
|
latest_temp = None
|
|
|
|
# Noise Parameters
|
|
samples_number = 1000
|
|
amplitudes_sum = 0
|
|
amplitudes_count = 0
|
|
|
|
|
|
def Temperature():
|
|
"""To get Temperature value.
|
|
|
|
:return: Temperature value (float)
|
|
|
|
"""
|
|
try:
|
|
voltage = device._readVoltage(SENSORS['temperature']['pin'])
|
|
|
|
Rthermistor = float(Rb) * (float(ADCres) / float(voltage) - 1)
|
|
rel_temp = float(Beta) / (math.log(float(Rthermistor) * float(Ginf)))
|
|
temp = rel_temp - Kelvin
|
|
|
|
# LOG.info("Temperature " + str(temp) + u" \u2103")
|
|
|
|
except Exception as err:
|
|
LOG.error("Error getting temperature: " + str(err))
|
|
|
|
return temp
|
|
|
|
|
|
def Brightness():
|
|
"""To get Brightness value.
|
|
|
|
:return: Brightness value (float)
|
|
|
|
"""
|
|
try:
|
|
voltage = float(device._readVoltage(SENSORS['brightness']['pin']))
|
|
|
|
ldr = (2500 / (5 - voltage * float(0.004887)) - 500) / float(3.3)
|
|
|
|
LOG.info("Brightness: " + str(ldr) + " (lux)")
|
|
|
|
except Exception as err:
|
|
LOG.error("Error getting brightness: " + str(err))
|
|
|
|
return ldr
|
|
|
|
|
|
def Humidity():
|
|
"""To get Humidity value: this function uses the Temperature sensor too.
|
|
|
|
:return: Humidity value (float)
|
|
|
|
"""
|
|
try:
|
|
|
|
degCelsius = Temperature()
|
|
supplyVolt = float(4.64)
|
|
HIH4030_Value = float(device._readVoltage(SENSORS['humidity']['pin']))
|
|
voltage = HIH4030_Value / float(1023.) * supplyVolt
|
|
sensorRH = float(161.0) * float(voltage) / supplyVolt - float(25.8)
|
|
relHum = sensorRH / (float(1.0546) - float(0.0026) * degCelsius)
|
|
|
|
LOG.info("Humidity " + str(relHum) + " percent")
|
|
|
|
except Exception as err:
|
|
LOG.error("Error getting humidity: " + str(err))
|
|
|
|
return relHum
|
|
|
|
|
|
def Pressure():
|
|
"""To get Pressure value.
|
|
|
|
:return: Pressure value (float)
|
|
|
|
"""
|
|
try:
|
|
|
|
in_pressure_raw = device.i2cRead('pressure')
|
|
pressure = float(in_pressure_raw) * float(0.00025) * 10
|
|
|
|
LOG.info("Pressure: " + str(pressure) + " hPa")
|
|
|
|
except Exception as err:
|
|
LOG.error("Error getting pressure: " + str(err))
|
|
|
|
return pressure
|
|
|
|
|
|
def Noise():
|
|
"""To get Noise value.
|
|
|
|
Elaborate a noise avarange value from noise listener.
|
|
|
|
:return: Noise value (float)
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
global amplitudes_sum, amplitudes_count
|
|
|
|
if amplitudes_count == float(0):
|
|
amplitude = float(0)
|
|
|
|
else:
|
|
amplitude = float(amplitudes_sum / amplitudes_count)
|
|
|
|
amplitudes_sum = 0
|
|
amplitudes_count = 0
|
|
|
|
except Exception as err:
|
|
LOG.error("Error getting noise: " + str(err))
|
|
|
|
return amplitude
|
|
|
|
|
|
def noise_listner():
|
|
"""Each two seconds collect a Noise sample.
|
|
|
|
"""
|
|
|
|
global THR_KILL
|
|
|
|
vect = []
|
|
|
|
if THR_KILL:
|
|
|
|
# LOG.info("listening noise..." + str(THR_KILL))
|
|
|
|
for x in range(samples_number):
|
|
|
|
read = float(device._readVoltage(SENSORS['noise']['pin']))
|
|
vect.append(read)
|
|
|
|
sorted_vect = sorted(vect)
|
|
|
|
minimum = float(sorted_vect[50])
|
|
maximum = float(sorted_vect[samples_number - 51])
|
|
tmp_amplitude = float(maximum - minimum)
|
|
|
|
global amplitudes_sum, amplitudes_count
|
|
amplitudes_sum = float(amplitudes_sum + tmp_amplitude)
|
|
amplitudes_count = float(amplitudes_count + 1)
|
|
# LOG.info("amplitudes_sum = " + str(amplitudes_sum))
|
|
# LOG.info("amplitudes_count = " + str(amplitudes_count))
|
|
|
|
threading.Timer(2.0, noise_listner).start()
|
|
|
|
else:
|
|
LOG.debug("Cancelled SmartME noise listening: " + str(THR_KILL))
|
|
|
|
|
|
def getMetric(metric, ckan):
|
|
"""Function to get metric values.
|
|
|
|
This function call the function relative to the 'metric'
|
|
specified and if the 'ckan' flag is True we create the body for the
|
|
REST request to send to CKAN database to store the sample there;
|
|
|
|
:param metric: name of the metric analized: 'Temperature', etc
|
|
:param ckan: flag True --> create JSON body for the CKAN request
|
|
:return: ckan_data --> JSON data to send as request body to CKAN
|
|
|
|
"""
|
|
|
|
# Call Sensors Metrics: Temperature(), etc...
|
|
m_value = str(globals()[metric.capitalize()]())
|
|
|
|
m_timestamp = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')
|
|
|
|
if metric == 'noise':
|
|
LOG.info("Noise: " + str(m_value) + " amplitude")
|
|
|
|
elif metric == 'temperature':
|
|
LOG.info("Temperature " + str(m_value) + u" \u2103")
|
|
|
|
if ckan:
|
|
|
|
ckan_data = {}
|
|
ckan_data["resource_id"] = str(SENSORS[metric]['ckanID'])
|
|
ckan_data["method"] = "insert"
|
|
ckan_data["records"] = []
|
|
sample = {}
|
|
sample["Latitude"] = location['latitude']
|
|
sample["Longitude"] = location['longitude']
|
|
sample["Altitude"] = location['altitude']
|
|
metric_func_name = metric.capitalize()
|
|
sample[metric_func_name] = m_value
|
|
sample["Date"] = m_timestamp
|
|
ckan_data["records"].append(sample)
|
|
|
|
ckan_data = json.dumps(ckan_data)
|
|
|
|
else:
|
|
ckan_data = None
|
|
|
|
return ckan_data
|
|
|
|
|
|
def getCKANdataset(board_uuid):
|
|
"""To get CKAN resource IDs for each metric type managed by SmartME boards.
|
|
|
|
:param board_uuid:
|
|
:return:
|
|
|
|
"""
|
|
|
|
datasets_url = "http://" + ckan_addr + "/api/rest/dataset/" + board_uuid
|
|
datasets = API.sendRequest(url=datasets_url, action='GET')
|
|
ckan_data = json.loads(datasets)
|
|
|
|
for resource in ckan_data['resources']:
|
|
|
|
# LOG.info(resource['name'].capitalize())
|
|
|
|
if resource['name'] in sensors_list:
|
|
# LOG.debug(resource['name'])
|
|
SENSORS[resource['name']]['ckanID'] = resource['id']
|
|
# LOG.info(resource['name'] + " - " + resource['id'])
|
|
|
|
|
|
def setSensorsLayout(params):
|
|
for sensor in sensors_list:
|
|
SENSORS[sensor] = {}
|
|
SENSORS[sensor]['pin'] = params[sensor]['pin']
|
|
SENSORS[sensor]['enabled'] = params[sensor]['enabled']
|
|
|
|
|
|
def InitSmartMeBoard(params):
|
|
"""This function init the SmartME board.
|
|
|
|
In the SmartME Arduino YUN board this function enables the needed
|
|
devices and set the needed parameters about sensors and location.
|
|
|
|
:param params: plugin parameters to configure the board.
|
|
|
|
"""
|
|
|
|
# get location
|
|
global location
|
|
location = API.getLocation()
|
|
LOG.info(
|
|
"Board location: \n"
|
|
+ json.dumps(location, indent=4, separators=(',', ': '))
|
|
)
|
|
|
|
# set devices
|
|
try:
|
|
|
|
device.EnableI2c()
|
|
device.EnableGPIO()
|
|
|
|
except Exception as err:
|
|
LOG.error("Error configuring devices: " + str(err))
|
|
global THR_KILL
|
|
THR_KILL = False
|
|
|
|
# set up sensors
|
|
setSensorsLayout(params)
|
|
|
|
|
|
class Worker(Plugin.Plugin):
|
|
|
|
def __init__(self, uuid, name, q_result=None, params=None):
|
|
super(Worker, self).__init__(
|
|
uuid, name,
|
|
q_result=q_result,
|
|
params=params
|
|
)
|
|
|
|
def run(self):
|
|
|
|
LOG.info("SmartME plugin starting...")
|
|
|
|
global THR_KILL
|
|
THR_KILL = self._is_running
|
|
|
|
# Board initialization
|
|
LOG.info("PARAMS list: " + str(self.params.keys()))
|
|
|
|
if len(self.params.keys()) != 0:
|
|
|
|
InitSmartMeBoard(self.params)
|
|
|
|
# Get polling time
|
|
polling_time = float(self.params['polling'])
|
|
LOG.info("Polling time: " + str(polling_time))
|
|
|
|
# GET CKAN SENSORS UUID
|
|
getCKANdataset(API.getBoardID())
|
|
|
|
LOG.info(
|
|
"SENSORS: \n"
|
|
+ json.dumps(SENSORS, indent=4, separators=(',', ': '))
|
|
)
|
|
|
|
# START NOISE LISTENER if sensor enabled
|
|
if SENSORS['noise']['enabled']:
|
|
LOG.info("Starting noise listening...")
|
|
noise_listner()
|
|
|
|
LOG.info("CKAN enabled: " + str(self.params['ckan_enabled']))
|
|
|
|
counter = 0
|
|
|
|
while (self._is_running and THR_KILL):
|
|
|
|
if sensors_list.__len__() != 0:
|
|
|
|
LOG.info("\n\n")
|
|
|
|
for sensor in sensors_list:
|
|
|
|
if SENSORS[sensor]['enabled']:
|
|
|
|
if self.params['ckan_enabled']:
|
|
|
|
API.sendRequest(
|
|
url=action_URL,
|
|
action='POST',
|
|
headers=headers,
|
|
body=getMetric(sensor, ckan=True),
|
|
verbose=False
|
|
)
|
|
|
|
else:
|
|
getMetric(sensor, ckan=False)
|
|
|
|
counter = counter + 1
|
|
LOG.info("Samples sent: " + str(counter))
|
|
|
|
time.sleep(polling_time)
|
|
|
|
else:
|
|
LOG.warning("No sensors!")
|
|
self._is_running = False
|
|
THR_KILL = self._is_running
|
|
|
|
# Update the thread status: at this stage THR_KILL will be False
|
|
THR_KILL = self._is_running
|
|
|
|
else:
|
|
LOG.error("No parameters provided!")
|