def fetch(self): try: conn = http.client.HTTPConnection(self.url) conn.request( 'GET', '/data/2.5/weather?q={}&APPID={}'.format( self.city, self.appid)) r = conn.getresponse() res = r.read().decode() conn.close() if r.status != 200: raise ValueError(res) jdoc = json.loads(res) reads = { 'city': jdoc['name'], 'wind_speed': jdoc['wind']['speed'], 'clouds': jdoc['clouds']['all'], 'temperature': jdoc['main']['temp'], 'pressure': jdoc['main']['pressure'], 'humidity': jdoc['main']['humidity'], 'visibility': jdoc['visibility'] } data = { 'asset': self.asset_name, 'timestamp': utils.local_timestamp(), 'key': str(uuid.uuid4()), 'readings': reads } async_ingest.ingest_callback(c_callback, c_ingest_ref, data) except ValueError as ex: err = "Unable to fetch information from api.openweathermap: {}".format( str(ex)) _LOGGER.error(err)
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ try: humidity, temperature = Adafruit_DHT.read_retry( Adafruit_DHT.DHT11, handle['gpioPin']['value']) if humidity is not None and temperature is not None: time_stamp = utils.local_timestamp() readings = {'temperature': temperature, 'humidity': humidity} wrapper = { 'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': readings } else: raise exceptions.DataRetrievalError except Exception: raise else: return wrapper
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ try: _LOGGER.info('Arrived at poll function') time_stamp = utils.local_timestamp() mean_value, median_value, rms_value = generate_data(ATTRIBUTE_NAME) data = { 'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "mean_value": mean_value, "median_value": median_value, "rms_value": rms_value } } except (Exception, RuntimeError) as ex: _LOGGER.exception("Pandas CSV Reader exception: {}".format(str(ex))) raise ex else: return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ try: x, y, z = handle['sensor'].get_values() except: x = y = z = 0 time_stamp = utils.local_timestamp() """ # For cases where you just want readings to be acceleration # https://physics.stackexchange.com/questions/41653/how-do-i-get-the-total-acceleration-from-3-axes acceleration=math.sqrt(pow(x,2)+pow(y,2)+pow(z,2)) rreadings = {'acceleration': acceleration} """ # unique values (x, y, z) readings = {'x': x, 'y': y, 'z': z} wrapper = { 'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': readings } return wrapper
async def save_data(): try: while True: time_stamp = utils.local_timestamp() data = { 'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "sinusoid": next(generate_data()) } } await Ingest.add_readings(asset='{}'.format(data['asset']), timestamp=data['timestamp'], key=data['key'], readings=data['readings']) try: await asyncio.sleep( 1 / (float(handle['dataPointsPerSec']['value']))) except ZeroDivisionError: _LOGGER.warning( 'Data points per second must be greater than 0, defaulting to 1' ) handle['dataPointsPerSec']['value'] = '1' await asyncio.sleep(1) except asyncio.CancelledError: pass except (Exception, RuntimeError) as ex: _LOGGER.exception("Sinusoid exception: {}".format(str(ex))) raise exceptions.DataRetrievalError(ex)
def datachange_notification(self, node: Node, val, data): """ Callback for OPC UA Subscription. This method will be called when the Client received a data change message from the Server. """ time_stamp = utils.local_timestamp() asset_name = str(node) #Trim the string to start with ns= ns_start = asset_name.find('ns=') if ns_start != -1: asset_name = asset_name[ns_start:] #Some OPC UA servers add extra parentheses, so remove them #Remove any extraneous parentheses asset_name = asset_name.replace("(","") asset_name = asset_name.replace(")","") #_LOGGER.info('opcua_py: datachange_notification %r %s', asset_name, val) key = str(uuid.uuid4()) data = { 'asset': asset_name, 'timestamp': time_stamp, # metric.timestamp 'key' : key, 'readings': {"value": val} } async_ingest.ingest_callback(c_callback, c_ingest_ref, data)
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: TimeoutError """ data = {} time_stamp = utils.local_timestamp() for sensor in handle['sensors']: if sensor.count == 0: try: readings = sensor.get_reading() if readings is not None: if sensor.assetName in data: data[sensor.assetName]['readings'] = {**data[sensor.assetName]['readings'], **readings} else: data[sensor.assetName] = { 'asset': '{}{}'.format(handle['assetPrefix']['value'], sensor.assetName), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': readings } except (Exception, RuntimeError) as ex: _LOGGER.exception("phidget exception: {}".format(str(ex))) sensor.count = (sensor.count + 1) % sensor.poll return list(data.values())
def plugin_poll(handle): """ Poll readings from the modbus device and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ readings = [] data = {} try: qualitrol_tm1 = handle['qualitrol_tm1'] readings = qualitrol_tm1.get_readings() if readings: data = { "asset": handle['assetName']['value'], "timestamp": utils.local_timestamp(), "key": str(uuid.uuid4()), "readings": readings } else: _LOGGER.error('No readings received') except Exception as ex: raise exceptions.DataRetrievalError(ex) else: return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ probes = handle['probes'] data = list() try: for probe in probes: temperature = probe.readTemp() data.append({ 'asset': '{}temperature{}'.format(handle['assetNamePrefix']['value'], probe.csPin), 'timestamp': utils.local_timestamp(), 'key': str(uuid.uuid4()), 'readings': { "temperature": temperature } }) except (Exception, RuntimeError) as ex: _LOGGER.exception("PT100 exception: {}".format(str(ex))) raise ex else: _LOGGER.debug("PT100 reading: {}".format(json.dumps(data))) return data
def plugin_poll(handle): """ Poll readings from the modbus device and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ try: readings = get_readings(handle) wrapper = { 'asset': handle['assetName']['value'], 'timestamp': utils.local_timestamp(), 'key': str(uuid.uuid4()), 'readings': readings } except Exception as ex: raise exceptions.DataRetrievalError(ex) else: return wrapper
def plugin_poll(handle): """ Poll readings from the modbus device and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call - i.e. "the config" Returns: returns a reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ global pollCounter """ We don't want to send readings on every poll so we keep track """ if pollCounter == 0: try: source_address = handle['address']['value'] source_port = int(handle['port']['value']) """ Address and Port are set in the plugin config """ b100_ltc_tank_temp_reg = int( handle['b100_ltc_tank_temp_reg']['value']) b100_top_oil_temp_reg = int( handle['b100_top_oil_temp_reg']['value']) qualitrol_top_oil_reg = int( handle['qualitrol_top_oil_temp_reg']['value']) qualitrol_ltc_tank_reg = int( handle['qualitrol_ltc_tank_temp_reg']['value']) qualitrol_ltc_tap_position_reg = int( handle['qualitrol_ltc_tap_position_reg']['value']) readings = get_sel_readings(source_address, source_port, b100_ltc_tank_temp_reg, b100_top_oil_temp_reg, qualitrol_top_oil_reg, qualitrol_ltc_tank_reg, qualitrol_ltc_tap_position_reg) wrapper = { 'asset': handle['assetName']['value'], 'timestamp': utils.local_timestamp(), 'key': str(uuid.uuid4()), 'readings': readings } except Exception as ex: raise exceptions.DataRetrievalError(ex) else: pollCounter = int(handle['pollInterval']['value']) """ reset the pollcounter to the pollInterval plugin setting """ return wrapper else: pollCounter -= 1
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ port = handle['serial_port']['value'] baudrate = handle['baudrate']['value'] ser = serial.Serial(port, baudrate) counter = 0 x = ser.readline() # _LOGGER.info('RPICT3T1: {}', format(str(x))) values = x.split() if (len(values) == 5): Current1 = float(values[1].decode('UTF-8')) Current2 = float(values[2].decode('UTF-8')) Current3 = float(values[3].decode('UTF-8')) Temperature1 = float(values[4].decode('UTF-8')) else: _LOGGER.info('RPICT3T1: {}', format(str(len(values)))) try: time_stamp = utils.local_timestamp() readings = { 'Current1': Current1, 'Current2': Current2, 'Current3': Current3, 'Temperature': Temperature1 } data = { 'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': readings } except (Exception, RuntimeError) as ex: _LOGGER.exception("RPICT3T1 exception: {}", format(str(ex))) raise exceptions.DataRetrievalError(ex) else: return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ time_stamp = utils.local_timestamp() wrapper = list() asset_prefix = handle['assetNamePrefix']['value'] if (handle['temperatureSensor']['value'] == 'true' and handle['temperatureModCount'] == 0): asset = '{}{}'.format(asset_prefix, handle['temperatureSensorName']['value']) temp_wrapper = _am2315_temp(handle, asset, time_stamp) if temp_wrapper: wrapper.append(temp_wrapper) if (handle['humiditySensor']['value'] == 'true' and handle['humidityModCount'] == 0): asset = '{}{}'.format(asset_prefix, handle['humiditySensorName']['value']) humid_wrapper = _am2315_humid(handle, asset, time_stamp) if humid_wrapper: wrapper.append(humid_wrapper) if (handle['currentSensor']['value'] == 'true' and handle['currentModCount'] == 0): asset = '{}{}'.format(asset_prefix, handle['currentSensorName']['value']) current_wrapper = _ina219(handle, asset, time_stamp) if current_wrapper: wrapper.append(current_wrapper) if (handle['accelerationSensor']['value'] == 'true' and handle['accelerationModCount'] == 0): asset = '{}{}'.format(asset_prefix, handle['accelerationSensorName']['value']) a_wrapper = _mma8451(handle, asset, time_stamp) if a_wrapper: wrapper.append(a_wrapper) handle['temperatureModCount'] = (handle['temperatureModCount'] + 1) % int(handle['temperaturePollInterval']['value']) handle['humidityModCount'] = (handle['humidityModCount'] + 1) % int(handle['humidityPollInterval']['value']) handle['currentModCount'] = (handle['currentModCount'] + 1) % int(handle['currentPollInterval']['value']) handle['accelerationModCount'] = (handle['accelerationModCount'] + 1) % int(handle['accelerationPollInterval']['value']) return wrapper
async def run(self): """ SELECT against the statistics table, to get a snapshot of the data at that moment. Based on the snapshot: 1. INSERT the delta between `value` and `previous_value` into statistics_history 2. UPDATE the previous_value in statistics table to be equal to statistics.value at snapshot """ current_time = utils.local_timestamp() results = await self._storage_async.query_tbl("statistics") for r in results['rows']: key = r['key'] value = int(r["value"]) previous_value = int(r["previous_value"]) delta = value - previous_value await self._insert_into_stats_history(key=key, value=delta, history_ts=current_time) await self._update_previous_value(key=key, value=value)
async def test_insert_into_stats_history(self): with patch.object(FoglampProcess, '__init__'): with patch.object(logger, "setup"): sh = StatisticsHistory() sh._storage_async = MagicMock(spec=StorageClientAsync) with patch.object( sh._storage_async, "insert_into_tbl", return_value=mock_coro(None)) as patch_storage: ts = utils.local_timestamp() await sh._insert_into_stats_history(key='Bla', value=1, history_ts=ts) args, kwargs = patch_storage.call_args assert "statistics_history" == args[0] payload = ast.literal_eval(args[1]) assert "Bla" == payload["key"] assert 1 == payload["value"]
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ try: time_stamp = utils.local_timestamp() data = {'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': {"sinusoid": next(generate_data())}} except (Exception, RuntimeError) as ex: _LOGGER.exception("Sinusoid exception: {}".format(str(ex))) raise ex else: return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ try: if handle['lastValue'] is None: new = randint(int(handle['minValue']['value']), int(handle['maxValue']['value'])) else: new = handle['lastValue'] + randint(-1, 1) if new > int(handle['maxValue']['value']): new = int(handle['maxValue']['value']) elif new < int(handle['minValue']['value']): new = int(handle['minValue']['value']) time_stamp = utils.local_timestamp() data = { 'asset': handle['assetName']['value'], 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "randomwalk": new } } handle['lastValue'] = new except (Exception, RuntimeError) as ex: _LOGGER.exception("RandomWalk exception: {}".format(str(ex))) raise ex else: return data
def on_message(client, userdata, msg): global _callback_event_loop #_LOGGER.info('{} has a message.'.format(_PLUGIN_NAME)) try: if not Ingest.is_available(): _LOGGER.error("Ingest is not availabe") else: inboundPayload = sparkplug_b_pb2.Payload() inboundPayload.ParseFromString(msg.payload) time_stamp = utils.local_timestamp() if _callback_event_loop is None: _LOGGER.debug("Message processing event doesn't yet exist - creating new event loop.") asyncio.set_event_loop(asyncio.new_event_loop()) _callback_event_loop = asyncio.get_event_loop() for metric in inboundPayload.metrics: readingKey = str(uuid.uuid4()) data = { 'asset' : metric.name, 'timestamp' : time_stamp, #metric.timestamp, 'key' : readingKey, 'readings' : { "value": metric.float_value, } } #_LOGGER.info("UUID: " + readingKey) #_LOGGER.info("Metric Name: " + str(metric.name)) #_LOGGER.info(metric) _callback_event_loop.run_until_complete(save_data(data)) #_LOGGER.info('Exiting message callback.') except Exception as e: _LOGGER.error(e)
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ try: bus = handle["bus"] i2c_address = handle['i2cAddress']['value'] sensor_add = hex(int(i2c_address, 16)) start_add = 0x00 function_code = 0x03 register_number = 0x04 response_bytes = 8 attempt_threshold = 50 asset_name = '{}'.format(handle['assetName']['value']).replace( '%M', i2c_address) try: # wake up call bus.write_i2c_block_data(sensor_add, function_code, [start_add, register_number]) except Exception as e: # expected exception as sensor is sleeping pass # request data bus.write_i2c_block_data(sensor_add, function_code, [start_add, register_number]) # read data sensor_response = bytearray( bus.read_i2c_block_data(sensor_add, function_code, response_bytes)) # temperature temperature = (sensor_response[4] * 256 + sensor_response[5]) / 10 # humidity humidity = (sensor_response[2] * 256 + sensor_response[3]) / 10 # crc crc = sensor_response[7] * 256 + sensor_response[6] # calc crc to verify calc_crc = 0xFFFF for byte in sensor_response[0:6]: calc_crc = calc_crc ^ byte for i in range(1, 9): if (calc_crc & 0x01): calc_crc = calc_crc >> 1 calc_crc = calc_crc ^ 0xA001 else: calc_crc = calc_crc >> 1 if calc_crc != crc: pass time_stamp = utils.local_timestamp() data = { 'asset': asset_name, 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "temperature": temperature, "humidity": humidity } } except (Exception, RuntimeError) as ex: _LOGGER.exception("AM2315 exception: {}".format(str(ex))) raise exceptions.DataRetrievalError(ex) return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: DataRetrievalError """ if 'tag' not in handle: raise RuntimeError time_stamp = utils.local_timestamp() data = list() bluetooth_adr = handle['bluetoothAddress']['value'] tag = handle['tag'] object_temp_celsius = None ambient_temp_celsius = None lux_luminance = None rel_humidity = None rel_temperature = None bar_pressure = None movement = None battery_level = None keypress_state = None try: if not tag.is_connected: raise RuntimeError # Enable sensors tag.char_write_cmd( handle['characteristics']['temperature']['configuration'] ['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['luminance']['configuration']['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['humidity']['configuration']['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['pressure']['configuration']['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['movement']['configuration']['handle'], movement_enable) # Get temperature count = 0 while count < SensorTagCC2650.reading_iterations: object_temp_celsius, ambient_temp_celsius = tag.hex_temp_to_celsius( tag.char_read_hnd( handle['characteristics']['temperature']['data']['handle'], "temperature")) time.sleep(0.5) # wait for a while count = count + 1 # Get luminance lux_luminance = tag.hex_lux_to_lux( tag.char_read_hnd( handle['characteristics']['luminance']['data']['handle'], "luminance")) # Get humidity rel_humidity, rel_temperature = tag.hex_humidity_to_rel_humidity( tag.char_read_hnd( handle['characteristics']['humidity']['data']['handle'], "humidity")) # Get pressure bar_pressure = tag.hex_pressure_to_pressure( tag.char_read_hnd( handle['characteristics']['pressure']['data']['handle'], "pressure")) # Get movement gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z, mag_x, mag_y, mag_z, acc_range = tag.hex_movement_to_movement( tag.char_read_hnd( handle['characteristics']['movement']['data']['handle'], "movement")) movement = { 'gyro': { 'x': gyro_x, 'y': gyro_y, 'z': gyro_z, }, 'acc': { 'x': acc_x, 'y': acc_y, 'z': acc_z, }, 'mag': { 'x': mag_x, 'y': mag_y, 'z': mag_z, }, 'acc_range': acc_range } battery_level = tag.get_battery_level( tag.char_read_hnd( handle['characteristics']['battery']['data']['handle'], "battery")) # Disable sensors tag.char_write_cmd( handle['characteristics']['temperature']['configuration'] ['handle'], char_disable) tag.char_write_cmd( handle['characteristics']['luminance']['configuration']['handle'], char_disable) tag.char_write_cmd( handle['characteristics']['humidity']['configuration']['handle'], char_disable) tag.char_write_cmd( handle['characteristics']['pressure']['configuration']['handle'], char_disable) tag.char_write_cmd( handle['characteristics']['movement']['configuration']['handle'], movement_disable) # "values" (and not "readings") denotes that this reading needs to be further broken down to components. readings = { 'temperature': { "object": object_temp_celsius, 'ambient': ambient_temp_celsius }, 'luxometer': { "lux": lux_luminance }, 'humidity': { "humidity": rel_humidity, "temperature": rel_temperature }, 'pressure': { "pressure": bar_pressure }, 'gyroscope': { "x": gyro_x, "y": gyro_y, "z": gyro_z }, 'accelerometer': { "x": acc_x, "y": acc_y, "z": acc_z }, 'magnetometer': { "x": mag_x, "y": mag_y, "z": mag_z }, 'battery': { "percentage": battery_level }, } for reading_key in readings.keys(): data.append({ 'asset': 'TI Sensortag CC2650/' + reading_key, 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': readings[reading_key] }) except (Exception, RuntimeError, pexpect.exceptions.TIMEOUT) as ex: _LOGGER.exception("SensorTagCC2650 {} exception: {}".format( bluetooth_adr, str(ex))) raise exceptions.DataRetrievalError(ex) _LOGGER.debug("SensorTagCC2650 {} reading: {}".format( bluetooth_adr, json.dumps(data))) return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: TimeoutError """ # air quality is voltage reading between 0 and 5.1 # we scale is to a value between 0 and 1023 try: time_stamp = utils.local_timestamp() data = list() if handle['tempHumEnable']['value'] == 'true' and handle['tempHumCount'] == 0: data.append({ 'asset': '{}{}'.format(handle['assetPrefix']['value'], handle['tempHumAssetName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "temperature": handle['temperature'].getTemperature(), "humidity": handle['humidity'].getHumidity() } }) if handle['currentEnable']['value'] == 'true' and handle['currentCount'] == 0: data.append({ 'asset': '{}{}'.format(handle['assetPrefix']['value'], handle['currentAssetName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "current": handle['current'].getCurrent() } }) if handle['encoderEnable']['value'] == 'true' and handle['encoderCount'] == 0: value = handle['encoder'].getPosition() # convert time_stamp to be usable if ":" == time_stamp[-3:-2]: timestamp_new = datetime.datetime.strptime(time_stamp[:-3]+time_stamp[-2:], '%Y-%m-%d %H:%M:%S.%f%z') else: timestamp_new = datetime.datetime.strptime(time_stamp, '%Y-%m-%d %H:%M:%S.%f%z') if handle['encoderPreviousValue'] > 0: # omit first one # calculate elapse time in milliseconds elapse_time = timestamp_new - handle['encoderPreviousTime'] elapse_time = elapse_time.total_seconds() data.append({ 'asset': '{}{}'.format(handle['assetPrefix']['value'], handle['encoderAssetName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { # (current_total_iterations - previous_total_iterations) / (elapsed time in seconds) "rotation-per-second": ((value - handle['encoderPreviousValue'])/1200)/elapse_time } }) # update old values handle['encoderPreviousValue'] = value handle['encoderPreviousTime'] = timestamp_new if handle['accelerometerEnable']['value'] == 'true' and handle['accelerometerCount'] == 0: x, y, z = handle['accelerometer'].getAcceleration() data.append({ 'asset': '{}{}'.format(handle['assetPrefix']['value'], handle['accelerometerAssetName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "accelerometer-x": x, "accelerometer-y": y, "accelerometer-z": z } }) if handle['gyroscopeEnable']['value'] == 'true' and handle['gyroscopeCount'] == 0: x, y, z = handle['gyroscope'].getAngularRate() data.append({ 'asset': '{}{}'.format(handle['assetPrefix']['value'], handle['gyroscopeAssetName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "gyroscope-x": x, "gyroscope-y": y, "gyroscope-z": z } }) if handle['magnetometerEnable']['value'] == 'true' and handle['magnetometerCount'] == 0: x, y, z = handle['magnetometer'].getMagneticField() data.append({ 'asset': '{}{}'.format(handle['assetPrefix']['value'], handle['magnetometerAssetName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "magnetometer-x": x, "magnetometer-y": y, "magnetometer-z": z } }) handle['tempHumCount'] = (handle['tempHumCount'] + 1) % int(handle['tempHumPoll']['value']) handle['currentCount'] = (handle['currentCount'] + 1) % int(handle['currentPoll']['value']) handle['encoderCount'] = (handle['encoderCount'] + 1) % int(handle['encoderPoll']['value']) handle['accelerometerCount'] = (handle['accelerometerCount'] + 1) % int(handle['accelerometerPoll']['value']) handle['gyroscopeCount'] = (handle['gyroscopeCount'] + 1) % int(handle['gyroscopePoll']['value']) handle['magnetometerCount'] = (handle['magnetometerCount'] + 1) % int(handle['magnetometerPoll']['value']) except (Exception, RuntimeError) as ex: _LOGGER.exception("wind_turbine exception: {}".format(str(ex))) raise exceptions.DataRetrievalError(ex) else: return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ time_stamp = utils.local_timestamp() data = list() try: moving = False rgb = light.rgb() magnetometer = motion.magnetometer() if abs(magnetometer[0] - state["magx"]) > _MAGNETOMETER_THRESHOLD: moving = True state["magx"] = magnetometer[0] state["magy"] = magnetometer[1] state["magz"] = magnetometer[2] accelerometer = [round(x, 1) for x in motion.accelerometer()] if moving and state["light"] != "red" and rgb[0] > rgb[ 1] + _LIGHT_THRESHOLD and rgb[0] > rgb[2] + _LIGHT_THRESHOLD: data.append({ 'asset': 'game/points', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "red": _RED_POINTS, "green": 0.0, "blue": 0.0, "accelerometer": 0.0, "lateral": 0.0, "flip": 0.0 } }) state["light"] = "red" leds.on() elif moving and state["light"] != "green" and rgb[1] > rgb[ 0] + _LIGHT_THRESHOLD and rgb[1] > rgb[2] + _LIGHT_THRESHOLD: data.append({ 'asset': 'game/points', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "red": 0.0, "green": _GREEN_POINTS, "blue": 0.0, "accelerometer": 0.0, "lateral": 0.0, "flip": 0.0 } }) state["light"] = "green" leds.on() elif moving and state["light"] != "blue" and rgb[2] > rgb[ 0] + _LIGHT_THRESHOLD and rgb[2] > rgb[1] + _LIGHT_THRESHOLD: data.append({ 'asset': 'game/points', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "red": 0.0, "green": 0.0, "blue": _BLUE_POINTS, "accelerometer": 0.0, "lateral": 0.0, "flip": 0.0 } }) state["light"] = "blue" leds.on() elif moving: state["light"] = "white" leds.off() if abs(accelerometer[0]) > 0.1: data.append({ 'asset': 'game/points', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "red": 0.0, "green": 0.0, "blue": 0.0, "accelerometer": abs(accelerometer[0] * _LINEAR_FACTOR), "lateral": 0.0, "flip": 0.0 } }) if abs(accelerometer[1]) > 0.1: data.append({ 'asset': 'game/points', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "red": 0.0, "green": 0.0, "blue": 0.0, "accelerometer": 0.0, "lateral": abs(accelerometer[1] * _LATERAL_FACTOR), "flip": 0.0 } }) if state["inverted"] == "No" and accelerometer[2] < -0.2: data.append({ 'asset': 'game/points', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "red": 0.0, "green": 0.0, "blue": 0.0, "accelerometer": 0.0, "lateral": 0.0, "flip": _FLIP_PENALTY } }) state["inverted"] = "Yes" elif accelerometer[2] > 0.2: state["inverted"] = "No" except (Exception, RuntimeError) as ex: _LOGGER.exception("IoT Lab Game exception: {}".format(str(ex))) raise ex else: _LOGGER.debug("IoT Lab Game reading: {}".format(json.dumps(data))) return data
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ unit = 'hPa' # Pressure unit, can be either hPa (hectopascals) or Pa (pascals) time_stamp = utils.local_timestamp() data = list() asset_prefix = handle['assetNamePrefix']['value'] try: if handle['rgbSensor']['value'] == 'true': rgb = light.rgb() data.append({ 'asset': '{}{}'.format(asset_prefix, handle['rgbSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "r": rgb[0], "g": rgb[1], "b": rgb[2] } }) if handle['magnetometerSensor']['value'] == 'true': magnetometer = motion.magnetometer() data.append({ 'asset': '{}{}'.format(asset_prefix, handle['magnetometerSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "x": magnetometer[0], "y": magnetometer[1], "z": magnetometer[2] } }) if handle['accelerometerSensor']['value'] == 'true': accelerometer = [round(x, 2) for x in motion.accelerometer()] data.append({ 'asset': '{}{}'.format(asset_prefix, handle['accelerometerSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "x": accelerometer[0], "y": accelerometer[1], "z": accelerometer[2] } }) if handle['weatherSensor']['value'] == 'true': altitude = weather.altitude() temperature = weather.temperature() pressure = weather.pressure(unit=unit) data.append({ 'asset': '{}{}'.format(asset_prefix, handle['weatherSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "altitude": altitude, "temperature": temperature, "pressure": pressure, } }) except Exception as ex: _LOGGER.exception("Enviro pHAT exception: {}".format(str(ex))) raise ex return data
async def save_data(): if 'tag' not in handle: return time_stamp = utils.local_timestamp() data = { 'asset': 'TI Sensortag CC2650', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': {} } bluetooth_adr = handle['bluetoothAddress']['value'] tag = handle['tag'] object_temp_celsius = None ambient_temp_celsius = None lux_luminance = None rel_humidity = None rel_temperature = None bar_pressure = None movement = None battery_level = None keypress_state = None attempt_count = 1 try: if not tag.is_connected: raise RuntimeError # Enable notification for notification_handle in handle['notification_handles']: tag.char_write_cmd(notification_handle, notification_enable) # Enable sensors tag.char_write_cmd( handle['characteristics']['temperature']['configuration'] ['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['luminance']['configuration'] ['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['humidity']['configuration'] ['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['pressure']['configuration'] ['handle'], char_enable) tag.char_write_cmd( handle['characteristics']['movement']['configuration'] ['handle'], movement_enable) # debug_cnt = 0 # Used only for debugging. debug_cnt should be set to 0 in production. cnt = 0 while tag.is_connected: time_stamp = utils.local_timestamp() try: pattern_index = tag.con.expect( 'Notification handle = .*? \r', timeout=4) # Re-initialize attempt_count on success attempt_count = 1 except pexpect.exceptions.TIMEOUT: attempt_count += 1 if attempt_count > 15: _LOGGER.error( "SensorTagCC2650 {} timeout error".format( bluetooth_adr)) break else: _LOGGER.error( "SensorTagCC2650 {} async exception attempt_count {}" .format(bluetooth_adr, attempt_count)) await asyncio.sleep(1) continue # expect, if succesfull, will return the index of the pattern "Notification handle = " which ideally # should appear at col 0. If not, then pexpect.TIMEOUT will be raised. Also, this choice of pattern # will help in splitting at line#190. if pattern_index != 0: attempt_count += 1 if attempt_count > 15: _LOGGER.error( "SensorTagCC2650 {} async timeout error".format( bluetooth_adr)) break else: _LOGGER.error( "SensorTagCC2650 {} async pattern attempt_count {}" .format(bluetooth_adr, attempt_count)) await asyncio.sleep(1) continue # Re-initialize attempt_count on success attempt_count = 1 after = tag.con.after hex_string = after.split()[3:] cnt += 1 # # Used only for debugging. debug_cnt should be set to 0 in production # if debug_cnt > 0: # if cnt >= debug_cnt: # break # Allow some breathing time for event loop to finish the background tasks such as responding to ping etc if cnt % 10 == 0: await asyncio.sleep(.5) # Get temperature if int(handle['characteristics']['temperature']['data']['handle'], 16) == \ int(hex_string[0].decode(), 16): object_temp_celsius, ambient_temp_celsius = tag.hex_temp_to_celsius( tag.get_raw_measurement("temperature", hex_string)) data = { 'asset': 'temperature', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "object": object_temp_celsius, 'ambient': ambient_temp_celsius } } # Get luminance if int(handle['characteristics']['luminance']['data']['handle'], 16) == \ int(hex_string[0].decode(), 16): lux_luminance = tag.hex_lux_to_lux( tag.get_raw_measurement("luminance", hex_string)) data = { 'asset': 'luxometer', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "lux": lux_luminance } } # Get humidity if int(handle['characteristics']['humidity']['data']['handle'], 16) == \ int(hex_string[0].decode(), 16): rel_humidity, rel_temperature = tag.hex_humidity_to_rel_humidity( tag.get_raw_measurement("humidity", hex_string)) data = { 'asset': 'humidity', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "humidity": rel_humidity, "temperature": rel_temperature } } # Get pressure if int(handle['characteristics']['pressure']['data']['handle'], 16) == \ int(hex_string[0].decode(), 16): bar_pressure = tag.hex_pressure_to_pressure( tag.get_raw_measurement("pressure", hex_string)) data = { 'asset': 'pressure', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "pressure": bar_pressure } } # Get movement if int(handle['characteristics']['movement']['data']['handle'], 16) == \ int(hex_string[0].decode(), 16): gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z, mag_x, mag_y, mag_z, acc_range = \ tag.hex_movement_to_movement(tag.char_read_hnd( handle['characteristics']['movement']['data']['handle'], "movement")) movement = { 'gyroscope': { "x": gyro_x, "y": gyro_y, "z": gyro_z }, 'accelerometer': { "x": acc_x, "y": acc_y, "z": acc_z }, 'magnetometer': { "x": mag_x, "y": mag_y, "z": mag_z }, } # Dedicated add_readings for movement for reading_key in movement: data = { 'asset': reading_key, 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': movement[reading_key] } await Ingest.add_readings( asset='TI Sensortag CC2650/{}'.format( data['asset']), timestamp=data['timestamp'], key=data['key'], readings=data['readings']) # Get battery # FIXME: Investigate why no battery input in async mode? if int(battery['data']['handle'], 16) == int(hex_string[0].decode(), 16): battery_level = tag.get_battery_level( tag.char_read_hnd(battery['data']['handle'], "battery")) data = { 'asset': 'battery', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "percentage": battery_level } } # Get keypress # FIXME: Investigate why no keypress input? if int(keypress['data']['handle'], 16) == int(hex_string[0].decode(), 16): keypress_state = tag.get_keypress_state( tag.char_read_hnd(keypress['data']['handle'], "keypress")) data = { 'asset': 'keypress', 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "state": keypress_state } } # Common add_readings for all keys other than movement if int(handle['characteristics']['movement']['data']['handle'], 16) != \ int(hex_string[0].decode(), 16): await Ingest.add_readings( asset='TI Sensortag CC2650/{}'.format(data['asset']), timestamp=data['timestamp'], key=data['key'], readings=data['readings']) except (Exception, RuntimeError, pexpect.exceptions.TIMEOUT) as ex: _LOGGER.exception("SensorTagCC2650 async {} exception: {}".format( bluetooth_adr, str(ex))) raise exceptions.DataRetrievalError(ex) _LOGGER.debug("SensorTagCC2650 async {} reading: {}".format( bluetooth_adr, json.dumps(data))) return
def plugin_poll(handle): """ Extracts data from the system info and returns it in a JSON document as a Python dict. Available for async mode only. Args: handle: handle returned by the plugin initialisation call Returns: a system info reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: TimeoutError """ readings = [] def get_subprocess_result(cmd): a = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) outs, errs = a.communicate() if a.returncode != 0: raise OSError('Error in executing command "{}". Error: {}'.format( cmd, errs.decode('utf-8').replace('\n', ''))) d = [b for b in outs.decode('utf-8').split('\n') if b != ''] return d def get_system_info(time_stamp): data = {} # Get hostname hostname = get_subprocess_result(cmd='hostname')[0] insert_reading("hostName", time_stamp, {"hostName": hostname}) # Get platform info platform = get_subprocess_result(cmd='cat /proc/version')[0] insert_reading("platform", time_stamp, {"platform": platform}) # Get uptime uptime_secs = get_subprocess_result(cmd='cat /proc/uptime')[0].split() uptime = { "system_seconds": float(uptime_secs[0].strip()), "idle_processes_seconds": float(uptime_secs[1].strip()), } insert_reading("uptime", time_stamp, uptime) # Get load average line_load = get_subprocess_result(cmd='cat /proc/loadavg')[0].split() load_average = { "overLast1min": float(line_load[0].strip()), "overLast5mins": float(line_load[1].strip()), "overLast15mins": float(line_load[2].strip()) } insert_reading("loadAverage", time_stamp, load_average) # Get processes count tasks_states = get_subprocess_result(cmd="ps -e -o state") processes = { "running": tasks_states.count("R"), "sleeping": tasks_states.count("S") + tasks_states.count("D"), "stopped": tasks_states.count("T") + tasks_states.count("t"), "paging": tasks_states.count("W"), "dead": tasks_states.count("X"), "zombie": tasks_states.count("Z") } insert_reading("processes", time_stamp, processes) # Get CPU usage c3_mpstat = get_subprocess_result(cmd='mpstat') cpu_usage = {} col_heads = c3_mpstat[1].split() # first line is the header row start_index = col_heads.index("CPU") + 1 for line in c3_mpstat[2:]: # second line onwards are value rows col_vals = line.split() for i in range(start_index, len(col_vals)): cpu_usage[col_heads[i].replace("%", "prcntg_")] = float( col_vals[i].strip()) insert_reading("cpuUsage_" + col_vals[start_index - 1], time_stamp, cpu_usage) # Get memory info c3_mem = get_subprocess_result(cmd='cat /proc/meminfo') mem_info = {} for line in c3_mem: line_a = line.split(':') line_vals = line_a[1].split() k = "{}{}".format(line_a[0], '_KB' if len(line_vals) > 1 else '').replace( "(", "").replace(")", "").strip() v = int(line_vals[0].strip()) mem_info.update({k: v}) insert_reading("memInfo", time_stamp, mem_info) # Get disk usage c3_all = get_subprocess_result(cmd='df -l') # On some systems, errors are reported by df command, hence we need to filter those lines first c3_temp1 = get_subprocess_result(cmd='df -l | grep -n Filesystem') c3_temp2 = c3_temp1[0].split("Filesystem") c3_start = int(c3_temp2[0].strip().replace(":", "")) - 1 c3 = c3_all[c3_start:] col_heads = c3[0].split() # first line is the header row for line in c3[1:]: # second line onwards are value rows col_vals = line.split() disk_usage = {} for i in range(1, len(col_vals)): disk_usage[col_heads[i].replace( "%", "_prcntg")] = int(col_vals[i].replace( "%", "").strip()) if i < len(col_vals) - 1 else col_vals[i] dev_key = (col_vals[0])[1:] if col_vals[0].startswith( '/') else col_vals[0] # remove starting / from /dev/sda5 etc insert_reading("diskUsage_" + dev_key, time_stamp, disk_usage) # Get Network and other info c3_net = get_subprocess_result(cmd='cat /proc/net/dev') col_heads = c3_net[1].replace("|", " ").split() for i in range(len(col_heads)): col_heads[i] = "{}_{}".format("Receive" if i <= 8 else "Transmit", col_heads[i].strip()) col_heads[0] = "Interface" for line in c3_net[2:]: line_a = line.replace(":", " ").split() interface_name = line_a[0].strip() net_info = {} for i in range(1, len(line_a)): net_info.update({col_heads[i]: line_a[i]}) insert_reading("networkTraffic_" + interface_name, time_stamp, net_info) # Paging and Swapping c6 = get_subprocess_result(cmd='vmstat -s') paging_swapping = {} for line in c6: if 'page' in line: a_line = line.strip().split("pages") paging_swapping.update( {a_line[1].replace(' ', ''): int(a_line[0].strip())}) insert_reading("pagingAndSwappingEvents", time_stamp, paging_swapping) # Disk Traffic c4 = get_subprocess_result(cmd='iostat -xd 2 1') c5 = [i for i in c4[1:] if i.strip() != ''] # Remove all empty lines col_heads = c5[0].split() # first line is header row for line in c5[1:]: # second line onwards are value rows col_vals = line.split() disk_traffic = {} for i in range(1, len(col_vals)): disk_traffic[col_heads[i].replace("%", "prcntg_").replace( "/s", "_per_sec")] = float(col_vals[i].strip()) insert_reading("diskTraffic_" + col_vals[0], time_stamp, disk_traffic) return data def insert_reading(asset, time_stamp, data): data = { 'asset': "{}{}".format(handle['assetNamePrefix']['value'], asset), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': data } readings.append(data) try: time_stamp = utils.local_timestamp() get_system_info(time_stamp) except (OSError, Exception, RuntimeError) as ex: _LOGGER.exception("System Info exception: {}".format(str(ex))) raise ex return readings
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor readings in a JSON document, as a Python dict, if it is available None - If no readings is available Raises: DataRetrievalError """ time_stamp = utils.local_timestamp() data = list() asset_prefix = handle['assetNamePrefix']['value'] try: lux = handle['sensor'].lux except: _LOGGER.info("Unable to get lux value") else: data.append({ 'asset': '{}{}'.format(asset_prefix, handle['luxSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': {'lux': lux} } ) try: infrared = handle['sensor'].infrared except: _LOGGER.info("Unable to get infrared value") else: data.append({ 'asset': '{}{}'.format(asset_prefix, handle['infraredSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': {'infrared': infrared} } ) try: visible = handle['sensor'].visible except: _LOGGER.info("Unable to get visible value") else: data.append({ 'asset': '{}{}'.format(asset_prefix, handle['visibleSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': {'visible': visible} } ) try: fullSpectrum = handle['sensor'].full_spectrum except: _LOGGER.info("Unable to get fullSpectrum value") else: data.append({ 'asset': '{}{}'.format(asset_prefix, handle['fullSpectrumSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': {'fullSpectrum': fullSpectrum} } ) return data
def plugin_poll(handle): """ Poll readings from the modbus device and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: """ try: global mbus_client if mbus_client is None: try: source_address = handle['address']['value'] source_port = int(handle['port']['value']) except Exception as ex: e_msg = 'Failed to parse Modbus TCP address and / or port configuration.' _LOGGER.error('%s %s', e_msg, str(ex)) raise ValueError(e_msg) try: mbus_client = ModbusTcpClient(host=source_address, port=source_port) mbus_client_connected = mbus_client.connect() if mbus_client_connected: _LOGGER.info('Modbus TCP Client is connected. %s:%d', source_address, source_port) else: raise RuntimeError("Modbus TCP Connection failed!") except: mbus_client = None _LOGGER.warn('Failed to connect! Modbus TCP host %s on port %d', source_address, source_port) return """ read_coils(self, address, count=1, **kwargs) read_discrete_inputs(self, address, count=1, **kwargs) read_holding_registers(self, address, count=1, **kwargs) read_input_registers(self, address, count=1, **kwargs) - address: The starting address to read from - count: The number of coils / discrete or registers to read - unit: The slave unit this request is targeting On TCP/IP, the MODBUS server is addressed using its IP address; therefore, the MODBUS Unit Identifier is useless. Remark : The value 0 is also accepted to communicate directly to a MODBUS TCP device. """ unit_id = UNIT modbus_map = json.loads(handle['map']['value']) readings = {} # Read coils coils_address_info = modbus_map['coils'] if len(coils_address_info) > 0: for k, address in coils_address_info.items(): coil_bit_values = mbus_client.read_coils(99 + int(address), 1, unit=unit_id) readings.update({k: coil_bit_values.bits[0]}) # Discrete input discrete_input_info = modbus_map['inputs'] if len(discrete_input_info) > 0: for k, address in discrete_input_info.items(): read_discrete_inputs = mbus_client.read_discrete_inputs(99 + int(address), 1, unit=unit_id) readings.update({k: read_discrete_inputs.bits[0]}) # Holding registers holding_registers_info = modbus_map['registers'] if len(holding_registers_info) > 0: for k, address in holding_registers_info.items(): register_values = mbus_client.read_holding_registers(99 + int(address), 1, unit=unit_id) readings.update({k: register_values.registers[0]}) # Read input registers input_registers_info = modbus_map['inputRegisters'] if len(input_registers_info) > 0: for k, address in input_registers_info.items(): read_input_reg = mbus_client.read_input_registers(99 + int(address), 1, unit=unit_id) readings.update({k: read_input_reg.registers[0] }) wrapper = { 'asset': handle['assetName']['value'], 'timestamp': utils.local_timestamp(), 'key': str(uuid.uuid4()), 'readings': readings } except Exception as ex: _LOGGER.error('Failed to read data from modbus device. Got error %s', str(ex)) raise ex else: return wrapper
def plugin_poll(handle): """ Extracts data from the sensor and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a sensor reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: Exception """ global _handle, _restart_config bluetooth_adr = _handle['bluetoothAddress']['value'] tag = _handle['tag'] asset_prefix = '{}'.format(_handle['assetNamePrefix']['value']).replace( '%M', bluetooth_adr) try: if not tag.is_connected: raise RuntimeError( "SensorTagCC2650 {} not connected".format(bluetooth_adr)) time_stamp = utils.local_timestamp() data = list() # In this method, cannot use "handle" as it might have changed due to restart. Hence use "_handle". if _handle['temperatureSensor']['value'] == 'true': count = 0 while count < SensorTagCC2650.reading_iterations: object_temp_celsius, ambient_temp_celsius = tag.hex_temp_to_celsius( tag.char_read_hnd( _handle['characteristics']['temperature']['data'] ['handle'], "temperature")) time.sleep(0.5) # wait for a while count = count + 1 data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['temperatureSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "object": object_temp_celsius, 'ambient': ambient_temp_celsius } }) if _handle['luminanceSensor']['value'] == 'true': lux_luminance = tag.hex_lux_to_lux( tag.char_read_hnd( _handle['characteristics']['luminance']['data']['handle'], "luminance")) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['luminanceSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "lux": lux_luminance } }) if _handle['humiditySensor']['value'] == 'true': rel_humidity, rel_temperature = tag.hex_humidity_to_rel_humidity( tag.char_read_hnd( _handle['characteristics']['humidity']['data']['handle'], "humidity")) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['humiditySensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "humidity": rel_humidity, "temperature": rel_temperature } }) if _handle['pressureSensor']['value'] == 'true': bar_pressure = tag.hex_pressure_to_pressure( tag.char_read_hnd( _handle['characteristics']['pressure']['data']['handle'], "pressure")) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['pressureSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "pressure": bar_pressure } }) if _handle['movementSensor']['value'] == 'true': gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z, mag_x, mag_y, mag_z, acc_range = tag.hex_movement_to_movement( tag.char_read_hnd( _handle['characteristics']['movement']['data']['handle'], "movement")) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['gyroscopeSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "x": gyro_x, "y": gyro_y, "z": gyro_z } }) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['accelerometerSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "x": acc_x, "y": acc_y, "z": acc_z } }) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['magnetometerSensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "x": mag_x, "y": mag_y, "z": mag_z } }) if _handle['batteryData']['value'] == 'true': battery_level = tag.get_battery_level( tag.char_read_hnd( _handle['characteristics']['battery']['data']['handle'], "battery")) data.append({ 'asset': '{}{}'.format(asset_prefix, _handle['batterySensorName']['value']), 'timestamp': time_stamp, 'key': str(uuid.uuid4()), 'readings': { "percentage": battery_level } }) except (Exception, RuntimeError, pexpect.exceptions.TIMEOUT) as ex: _plugin_restart(bluetooth_adr) raise ex return data