def encode(self, dataframe: DataFrame): """Encode telemetry data matching the BEEP-BOB interface. https://gist.github.com/vkuhlen/51f7968266659f37d076bd66d57cdbbd https://github.com/Hiverize/FiPy/blob/master/logger/beep.py Example:: { 't': 22.66734, 'h': 52.41612, 'p': 1002.334, 'weight': 10.0, 't_i_1': 23.1875, 't_i_2': 23.125, 't_i_3': 23.125, 't_i_4': 23.1875 } :param data: """ # Rename all fields to designated BEEP-BOB fields. egress_data = {} mapping = self.settings.get('sensor_telemetry_map') mapping['key'] = 'key' for sensor_field, telemetry_field in mapping.items(): sensor_field = sensor_field.lower() if sensor_field in dataframe.data_in: egress_data[telemetry_field] = dataframe.data_in[sensor_field] dataframe.data_out = egress_data
def serialize(self, dataframe: DataFrame): """ :param data: defined in terkin/model.py moves & reformats data from dataframe.data_out to dataframe.payload_out """ # Serialize payload. if self.format == TelemetryClient.FORMAT_URLENCODED: payload = urlencode(dataframe.data_out) elif self.format == TelemetryClient.FORMAT_JSON: payload = json.dumps(dataframe.data_out) elif self.format == TelemetryClient.FORMAT_CAYENNELPP: payload = to_cayenne_lpp(dataframe) elif self.format == TelemetryClient.FORMAT_CSV: raise NotImplementedError( 'Serialization format "CSV" not implemented yet') else: raise ValueError('Unknown serialization format "{}"'.format( self.format)) # Apply content encoding. if self.content_encoding in (None, self.CONTENT_ENCODING_IDENTITY): pass elif self.content_encoding == self.CONTENT_ENCODING_BASE64: payload = to_base64(payload) dataframe.payload_out = payload
def transmit(self, dataframe: DataFrame, uri=None, serialize=True): """ :param dataframe: :param uri: (Default value = None) :param serialize: (Default value = True) """ # Submit telemetry data using HTTP POST request # Serialization: x-www-form-urlencoded # Compute target URI. if uri: real_uri = uri else: real_uri = self.uri suffix = self.uri_suffixes.get(self.transport, '').format(**self.__dict__) real_uri = real_uri + suffix # Resolve handler by URI. handler = self.get_handler(real_uri) # Prepare dataframe for egress. dataframe.payload_out = dataframe.data_out if serialize: self.serialize(dataframe) # Submit dataframe to handler. return handler.send(dataframe)
def encode(self, dataframe: DataFrame): """ :param dataframe: defined in terkin/model.py move data_in to data_out (why?) """ dataframe.data_out = dataframe.data_in
def read_sensors(self) -> DataFrame: """ Read measurements from all sensor objects that have been registered in the sensor_manager. Reading is done with the read() function of each respective sensor object. """ # Power up sensor peripherals. self.sensor_manager.power_on() # Collect observations. data = {} richdata = {} readings = [] # Iterate all registered sensors. sensors = self.sensor_manager.sensors log.info('Reading %s sensor ports', len(sensors)) for sensor in sensors: # Signal sensor reading to user. sensorname = sensor.__class__.__name__ log.info('Reading sensor port "%s"', sensorname) # Read sensor port. try: # Disable garbage collector to guarantee reasonable # realtime behavior before invoking sensor reading. with gc_disabled(): sensor_outcome = sensor.read() # Power off HX711 after reading if "HX711Sensor" in sensorname: sensor.power_off() # Backward compat. if isinstance(sensor_outcome, SensorReading): sensor_reading = sensor_outcome else: sensor_reading = SensorReading() sensor_reading.sensor = sensor sensor_reading.data = sensor_outcome sensor_data = sensor_reading.data # Evaluate sensor outcome. if sensor_data is None or sensor_data is AbstractSensor.SENSOR_NOT_INITIALIZED: continue # Round values according to sensor settings. if sensor.settings.get('decimals') is not None: for key, value in sensor_data.items(): sensor_data[key] = round( sensor_data[key], sensor.settings.get('decimals')) # Add sensor reading to observations. data.update(sensor_data) # Record reading for prettified output. self.record_reading(sensor, sensor_data, richdata) readings.append(sensor_reading) except Exception as ex: # Because of the ``gc_disabled`` context manager used above, # the propagation of exceptions has to be tweaked like that. log.exc(ex, 'Reading sensor "%s" failed', sensorname) # Feed the watchdog. self.device.watchdog.feed() # Clean up memory after reading each sensor object. #self.device.run_gc() # Debugging: Print sensor data before running telemetry. prettify_log = self.settings.get('sensors.prettify_log', False) if prettify_log: from terkin.util import ddformat log.info('Sensor data:\n\n%s', ddformat(richdata, indent=11)) else: log.info('Sensor data: %s', data) # Capture all sensor readings. result = DataFrame() result.readings = readings result.data_in = data return result