API reference¶
Generated from the docstrings. If something here is wrong or missing, fix the docstring rather than this page.
ents.dirtviz¶
Talking to the DirtViz backend.
Client interface with dirtviz.
TODO: - Add caching of data
- class ents.dirtviz.client.Cell(data: str)[source]¶
Bases:
objectClass representing a cell in the Dirtviz API.
- class ents.dirtviz.client.BackendClient(base_url: str = 'https://dirtviz.jlab.ucsc.edu/api/')[source]¶
Bases:
objectClient for interacting with the Dirtviz API.
- get(endpoint: str, params: dict | None = None) dict[source]¶
Get request to the API.
- Parameters:
endpoint – The API endpoint to request.
params – Optional parameters for the request.
- Returns:
A dictionary containing the response data.
- static time_to_params(start: datetime, end: datetime) dict[source]¶
Puts start and end datetime into an API paramter dictionary
- Parameters:
dt – The datetime object to format.
- Returns:
A string representing the formatted datetime.
- power_data(cell: Cell, start: datetime, end: datetime) DataFrame[source]¶
Gets power data for a specific cell by name.
- Parameters:
cell – The Cell object for which to get power data.
start – The start date of the data.
end – The end date of the data.
- Returns:
A pandas DataFrame containing the power data.
- teros_data(cell: Cell, start: datetime, end: datetime) DataFrame[source]¶
Gets teros data for a specific cell
- Parameters:
cell – The Cell object for which to get teros data.
start – The start date of the data.
end – The end date of the data.
- Returns:
A pandas DataFrame containing the teros data with columns vwc_raw, vwc_adj, temp, ec.
- sensor_data(cell: Cell, name: str, meas: str, start: datetime, end: datetime, resample: str = 'none') DataFrame[source]¶
Gets generic sensor data for a specific cell
- Parameters:
cell – The Cell object for which to get sensor data.
name – Name of the sensor (e.g., “power”, “teros”).
meas – The measurement type (e.g., “v”, “i”, “vwc”, “temp”, “ec”).
start – The start date of the data.
end – The end date of the data.
- Returns:
A pandas DataFrame containing the sensor data.
- cell_from_id(cell_id: int) Cell | None[source]¶
Get a Cell object from its ID.
- Parameters:
cell_id – The ID of the cell.
- Returns:
A Cell object. None if the cell does not exist.
Common plots for data on dirtviz.
Still need to fill in with common functions: - Plot power (voltage, current, calcualted power) - Plot teros12 - Plot bme280 - Plot all (take all available sensors) - Plot group (find mean/stddev for each point)
Can pull from personal scripts from SenSys (jtmadden)
ents.proto¶
Encoding and decoding the messages nodes upload.
Module for sensor measurements
Encode/decoding functions are wrappers around the protobuf messages. These take in the json dictionary format of the messages and return serialized byte arrays.
Format/parse functions implement the protocol for repeated sensor measurements. These take in a list of measurements and automatically optimize repeated metadata fields.
- ents.proto.sensor.parse_sensor_measurement(data: bytes) list[source]¶
Parses a sensor measurement into a usable dictionary.
- Function does the following:
Decodes the serialized byte array
Updates metadata for each measurement if missing
Adds names, descriptions, and units to metadata
- Parameters:
data – Byte array of message.
- Returns:
Dictionary of sensor measurement.
- ents.proto.sensor.format_sensor_measurement(meas: list) bytes[source]¶
Formats a sensor measurement dictionary into a serialized byte array.
- Function does the following:
Uses top level metadata for duplicate measurement metadata fields
Encodes the dictionary into a serialized byte array
- Parameters:
meas – Dictionary of sensor measurement.
- Returns:
Byte array of serialized message.
- ents.proto.sensor.get_sensor_data(meas_type: int) dict[source]¶
Gets sensor data information.
- Parameters:
meas_type – Sensor measurement dictionary.
- Returns:
Metadata associated with the sensor type.
- ents.proto.sensor.encode_repeated_sensor_measurements(meas_dict: dict) bytes[source]¶
Encodes a SensorMeasurement message
- Parameters:
rep_meas – Repeated sensor measurement dictionary.
- Returns:
Byte array of encoded RepeatedSensorMeasurements message.
- ents.proto.sensor.decode_sensor_measurement(data: bytes) dict[source]¶
Decodes a SensorMeasurement message
- Parameters:
data – Byte array of SensorMeasurement message.
- Returns:
Decoded sensor measurement dictionary.
- ents.proto.sensor.decode_repeated_sensor_measurements(data: bytes) dict[source]¶
Decodes repeated sensor measurements
- Parameters:
data – Byte array from RepeatedSensorMeasurements
- Returns:
List of decoded sensor measurement dictionaries.
- ents.proto.sensor.update_repeated_metadata(meas: dict) dict[source]¶
Ensures every measurements has metadata field set.
If a measurement is missing the metadata field, it is filled in from the repeated sensor measurement. Existing measurement metadata fields are not overwritten.
- Parameters:
meas – Sensor measurement dictionary.
- Returns:
Updated sensor measurement dictionary.
- ents.proto.sensor.encode_sensor_response(resp_dict: dict) bytes[source]¶
Encodes a sensor response message.
Shaped like:
{ "responses": [ {"status": int, "message": str}, ... ] }
- Parameters:
resp_dict – Sensor response dictionary.
- Returns:
Byte array of encoded SensorResponse message.
- ents.proto.sensor.decode_sensor_response(data: bytes) dict[source]¶
Decodes a sensor response message.
Shaped like:
{ "responses": [ {"status": int, "message": str}, ... ] }
- Parameters:
data – Byte array of SensorResponse message.
- Returns:
Decoded sensor response dictionary.
Module to encode soil power sensor protobuf messages
Encoding a response can be performed with
encode_response()
Each type of measurement has a corresponding encoding function as follows:
PowerMeasurement -> encode_power_measurement() Teros12Measurement -> encode_teros12_measurement()
- ents.proto.encode.encode_response(success: bool = True) bytes[source]¶
Encodes a Response message
The response indicates there was a successful upload, otherwise indicates an error.
- Parameters:
success – Specifies whether to encode a success or failure.
- Returns:
Byte string of response message.
- ents.proto.encode.encode_power_measurement(ts: int, cell_id: int, logger_id: int, voltage: float, current: float) bytes[source]¶
Encodes a PowerMeasurement within the Measurement message
- Parameters:
ts – Timestamp in unix epochs
cell_id – Cell Id from Dirtviz
logger_id – Logger Id from Dirtviz
voltage – Voltage in V (Volts)
current – Current in A (Amps)
- Returns:
Serialized Power measurement
- ents.proto.encode.encode_teros12_measurement(ts: int, cell_id: int, logger_id: int, vwc_raw: float, vwc_adj: float, temp: float, ec: int) bytes[source]¶
Encodes a Teros12Measurment within the Measurement message
- Parameters:
ts – Timestamp in unix epochs
cell_id – Cell Id from Dirtviz
logger_id – Logger Id from Dirtviz
vwc_raw – Raw volumetric water content from Teros12
vwc_adj – Volumetric water content from Teros12 with calibration applied
temp – Temperature in C
ec – Electrical conductivity
- Returns:
Serialized Teros12 measurement
- ents.proto.encode.encode_phytos31_measurement(ts: int, cell_id: int, logger_id: int, voltage: float, leaf_wetness: float) bytes[source]¶
Encodes a Phytos31Measurement within the Measurement message
- Parameters:
ts – Timestamp in unix epochs
cell_id – Cell Id from Dirtviz
logger_id – Logger Id from Dirtviz
voltage – Raw voltage reading
leaf_wetness – Calibrated leaf wetness
- Returns:
Serialized Phytos31 measurement
- ents.proto.encode.encode_bme280_measurement(ts: int, cell_id: int, logger_id: int, pressure: int, temperature: int, humidity: int)[source]¶
Encodes a BME280Measurement within the Measurement message
The following raw values correspond to the following SI units
Raw
pressure: 98473 temperature: 2275 humidity: 43600
SI Units
pressure: 9847.3 hPa temperature: 22.75 C humidity: 43.600 %
- Parameters:
ts – Timestamp in unix epochs
cell_id – Cell Id from Dirtviz
logger_id – Logger Id from Dirtviz
pressure – Ambient pressure
temperature – Ambient temperature
humidity – Relative humidity
- Returns:
Serialized BME280 Measurement
- ents.proto.encode.encode_teros21_measurement(ts: int, logger_id: int, cell_id: int, matric_pot: float, temp: float) bytes[source]¶
- ents.proto.encode.encode_user_configuration(logger_id: int, cell_id: int, Upload_method: str, Upload_interval: int, Enabled_sensors: list, Voltage_Slope: float, Voltage_Offset: float, Current_Slope: float, Current_Offset: float, WiFi_SSID: str, WiFi_Password: str, API_Endpoint_URL: str, API_Endpoint_Port: int) bytes[source]¶
Encodes a UserConfiguration message
- Parameters:
logger_id – ID of the logger.
cell_id – ID of the cell.
Upload_method – indicates whether LoRa or WiFi is used
Upload_interval – upload time in seconds
Enabled_sensors – used sensors
Voltage_Slope – Calibration slope for voltage.
Voltage_Offset – Calibration offset for voltage.
Current_Slope – Calibration slope for current.
Current_Offset – Calibration offset for current.
WiFi_SSID – WiFi SSID.
WiFi_Password – WiFi password.
API_Endpoint_URL
API_Endpoint_Port
- Returns:
Serialized UserConfiguration message
Module to decode soil power sensor messages
- ents.proto.decode.decode_response(data: bytes)[source]¶
Decodes a Response message.
- Parameters:
data – Byte array of Response message.
- Returns:
Returns the ResponseType.
- Raises:
KeyError – Missing the resp field.
- ents.proto.decode.decode_measurement(data: bytes, raw: bool = True) dict[source]¶
Decodes a Measurement message
The data is decoded into a flat dictionary with the measurement type.
- Parameters:
data – Byte array of Measurement message.
raw – Flag to return raw or adjusted measurements
- Returns:
Flat dictionary of values from the meta field, measurement field, and the key “type” to indicate the type of measurement.
- Raises:
KeyError – When the serialized data is missing a required field.
- ents.proto.decode.decode_user_configuration(data: bytes) dict[source]¶
Decodes a UserConfiguration message
- Parameters:
data – Byte array of UserConfiguration message.
- Returns:
Dictionary of UserConfiguration values.
- Raises:
KeyError – When the serialized data is missing a required field.
- ents.proto.esp32.encode_esp32command(cmd_type: str, **kwargs) bytes[source]¶
Encodes a command for the esp32
- Parameters:
cmd – Type of command to encode
**kwargs – See other encode functions
- Returns:
Bytes of protobuf serialized message
- ents.proto.esp32.encode_page_command(req: str, fd: int, bs: int = 0, n: int = 0) <module 'google.protobuf.message' from '/opt/hostedtoolcache/Python/3.14.8/x64/lib/python3.14/site-packages/google/protobuf/message.py'>[source]¶
Encodes a command for memory paging
- Parameters:
req – Page request type
fd – File descriptor
bs – Block size
n – Number of bytes
- Returns:
PageCommand message
- Raises:
NotImplementedError – When page request type does not exist
- ents.proto.esp32.encode_test_command(state: str, data: int) <module 'google.protobuf.message' from '/opt/hostedtoolcache/Python/3.14.8/x64/lib/python3.14/site-packages/google/protobuf/message.py'>[source]¶
Encodes a command for testing modules library
Valid strings for
state:receive: Data is received by the modulereceive_request: Data is received by the module, indicating data for a subsequent requestrequest: Data is sent by the module
- Parameters:
- Returns:
TestCommand message
- Raises:
NotImplementedError – When the ChangeState type does not exist
- ents.proto.esp32.encode_wifi_command(_type: str, ssid: str = '', passwd: str = '', url: str = '', port: int = 0, rc: int = 0, ts: int = 0, resp: bytes = b'') <module 'google.protobuf.message' from '/opt/hostedtoolcache/Python/3.14.8/x64/lib/python3.14/site-packages/google/protobuf/message.py'>[source]¶
Encodes a WiFi command
- Valid strings for _type are:
“connect”: Connecting to a WiFi network and any other setup “post”: Posting data to the endpoint
Not all arguments are necessary for valid commands.
- Parameters:
request (_type; Type of)
ssid – WiFi SSID
passwd – WiFi password
url – Endpoint URL
port – Port of webserver
rc – Return code
ts – Timestamp
resp – Binary data response from server
- Returns:
WiFiCommand message
- Raises:
NotImplementedError – When _type does not exist
ents.config¶
Node user configuration.
@brief PyQt5 GUI Application for Configuring User Settings
This module provides a PyQt5-based graphical interface for configuring user settings. The application allows users to input configuration details, including Logger ID, Cell ID, Upload Method (WiFi or LoRa), Upload Interval, Enabled Sensors, and Calibration parameters for voltage and current (V/I Slope and Offset).
Key features:
Save and Load: Users can save configurations to a file or load previous configurations for easy reuse.
Real-time Configuration: By pressing the “Send Configuration” button, the settings are serialized with Protobuf and transmitted over UART to the STM32 for direct application.
@file user_config.py @author Ahmed Hassan Falah @date 2024-10-10
- class ents.config.user_config.Ui_MainWindow[source]¶
Bases:
object- setupUi(MainWindow)[source]¶
@brief Sets up the user interface components.
Initializes the main window and creates the layout for user configurations.
- toggleUploadMethod()[source]¶
@brief Shows or hides WiFi settings based on the upload method selected.
- createLabel(text, font)[source]¶
@brief Creates a label with the specified text and font.
@param text Text for the label. @param font Font settings for the label. @return QLabel instance
- createLineEdit(placeholder)[source]¶
@brief Creates a QLineEdit with a placeholder.
@param placeholder Placeholder text for the QLineEdit. @return QLineEdit instance
- saveConfiguration(flag: str)[source]¶
@brief Validates inputs, encodes the configuration, and sends it via UART.
- loadConfiguration(flag: str)[source]¶
@brief Loads configuration from a selected JSON file and fills the input fields.
- sendToUART(encoded_data)[source]¶
@brief Sends the encoded configuration data via UART.
@param data Encoded configuration data.
- receiveFromUART()[source]¶
@brief Receives the current encoded configuration data via UART.
@param void. @return (success, data): A tuple containing success status and decoded data or an error message.
- validateURL(value, field_name)[source]¶
@brief Validates that the input is a valid URL. @param value The input value to validate. @param field_name The name of the field being validated. @return The validated URL string. @throws ValueError if the input is invalid.
- validateUInt(value, name)[source]¶
@brief Validates that the input is a positive integer.
@param value The input value to validate. @param name The name of the parameter (for error messages). @return Validated unsigned integer value.
ents.simulator¶
Standing in for hardware.
- class ents.simulator.node.NodeSimulator(cell: int, logger: int, sensors: list[str], fn=<built-in function sin>)[source]¶
Bases:
objectSimulation class to simulate measurements for different sensors
- class ents.simulator.node.NodeSimulatorGeneric(cell: int, logger: int, sensors: list[str], _min=-1, _max=1, fn=<built-in function sin>)[source]¶
Bases:
objectSimulation class to simulate measurements for different sensors
- send_next(url: str) bool[source]¶
Sends measurements to a dirtviz instance
- Parameters:
url – URL of the dirtviz instance
- Returns:
True if there are measurements to send, False otherwise
ents.calibrate¶
Calibration against a reference instrument.
- ents.calibrate.linear_regression.linear_regression(meas: list, actual: list)[source]¶
Performs linear regression between measured and actual values
- Parameters:
meas – Measure values
actual – Ground truth values
- Returns:
Linear regression model
- ents.calibrate.linear_regression.print_eval(pred: list, actual: list)[source]¶
Prints various evaluation parameters of the model
- The following metrics are used:
Mean absolute error
Root mean square error
R2 score
Mean absolute percentage error
- Parameters:
pred – Predicted values
actual – Actual values
- ents.calibrate.linear_regression.print_coef(model)[source]¶
Print coefficients of a model
- Parameters:
model – Linear model
- ents.calibrate.linear_regression.print_norm(residuals: list)[source]¶
Print mean offset and standard deviation
- Parameters:
residuals – List of residuals
Data recorder for Soil Power Sensor
The recorder controls the SPS firmware and a Keithley 2400 Source Measurement Unit (SMU). Ideally the script should work with any microcontrollre flashed with the firmware and any source measurement unit that supports Standard Commands for Programable Instruments (SCPI). The units listed are the ones that the script was developed and tested on. It allows to step through a range of output voltages on the Keithley and measure the voltage and current from both the SMU and the Soil Power Sensor (SPS).
- class ents.calibrate.recorder.SerialController(port, baudrate=115200, xonxoff=False)[source]¶
Bases:
objectGeneric serial controller that will open and close serial connections
- ser = None¶
- class ents.calibrate.recorder.LANController(host, port)[source]¶
Bases:
objectGeneric LAN controller that will open and close LAN connections
- sock = None¶
- class ents.calibrate.recorder.SoilPowerSensorController(port)[source]¶
Bases:
SerialControllerController used to read values from the SPS
- class ents.calibrate.recorder.SMUSerialController(port, source_mode)[source]¶
Bases:
SerialControllerController for the Keithley 2400 SMU used to supply known voltage to the SPS
Uses SCPI (Standard Control of Programmable Instruments) to control the SMU through its RS232 port. Written for the Keithley 2400 SMU, but should work for any other SMU that uses SCPI.
- class VoltageIterator(ser, start, stop, step)[source]¶
Bases:
objectVoltageIterator Class
Implements a iterator for looping through voltage output values
- vrange(start, stop, step) VoltageIterator[source]¶
Gets iterator to range of voltages
Parameters¶
- startfloat
Starting voltage
- stopfloat
End voltage
- stepfloat
Voltage step
- class ents.calibrate.recorder.SMULANController(host, port)[source]¶
Bases:
LANControllerController for the Keithley 2400 SMU used to supply known voltage to the SPS
Uses SCPI (Standard Control of Programmable Instruments) to control the SMU through its RS232 port. Written for the Keithley 2400 SMU, but should work for any other SMU that uses SCPI.
- class VoltageIterator(sock, start, stop, step)[source]¶
Bases:
objectVoltageIterator Class
Implements a iterator for looping through voltage output values
- class CurrentIterator(sock, start, stop, step)[source]¶
Bases:
objectCurrentIterator Class
Implements a iterator for looping through current output values
- vrange(start, stop, step) VoltageIterator[source]¶
Gets iterator to range of voltages
Parameters¶
- startfloat
Starting voltage
- stopfloat
End voltage
- stepfloat
Voltage step
- irange(start, stop, step) CurrentIterator[source]¶
Gets iterator to range of currents
Parameters¶
- startfloat
Starting current
- stopfloat
End current
- stepfloat
Current step
- class ents.calibrate.recorder.Recorder(serialport: str, host: str, port: int, delay: int = 1)[source]¶
Bases:
object- record_voltage(start: float, stop: float, step: float, samples: int) dict[str, list][source]¶
Records voltage measurements from the smu and sps
Input arguments given in volts units. Returned dictionary has keys for the expected voltage (number from python), actual voltage (value measured by the smu), and meas voltage (value measured by the sps).
- Parameters:
start – Start voltage
stop – Stop voltage (inclusive)
step – Step between voltage
samples – Number of samples taken at each voltage
- Returns:
Dictionary in a pandas compatible format:
{ "expected": [], "actual": [], "meas": [], }
- record_current(start: float, stop: float, step: float, samples: int) dict[str, list][source]¶
Records current measurements from the smu and sps
Input arguments given in amps units. Returned dictionary has keys for the expected current (number from python), actual current (value measured by the smu), and meas current (value measured by the sps).
- Parameters:
start – Start current
stop – Stop current (inclusive)
step – Step between current
samples – Number of samples taken at each voltage
- Returns:
Dictionary in a pandas compatible format:
{ "expected": [], "actual": [], "meas": [], }