From 81296f647dd5e112f7d06acb13b6092864da299d Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 7 Oct 2024 15:17:27 -0400 Subject: [PATCH 01/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Sketch=20?= =?UTF-8?q?out=20ds18x20=20classes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Wippersnapper_V2.cpp | 3 -- src/Wippersnapper_V2.h | 3 -- src/components/ds18x20/controller.cpp | 30 ++++++++++++++++ src/components/ds18x20/controller.h | 42 ++++++++++++++++++++++ src/components/ds18x20/hardware.cpp | 23 ++++++++++++ src/components/ds18x20/hardware.h | 51 +++++++++++++++++++++++++++ src/components/ds18x20/model.cpp | 22 ++++++++++++ src/components/ds18x20/model.h | 37 +++++++++++++++++++ 8 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 src/components/ds18x20/controller.cpp create mode 100644 src/components/ds18x20/controller.h create mode 100644 src/components/ds18x20/hardware.cpp create mode 100644 src/components/ds18x20/hardware.h create mode 100644 src/components/ds18x20/model.cpp create mode 100644 src/components/ds18x20/model.h diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 83b7a16a1..a70cea4f7 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -65,9 +65,6 @@ Wippersnapper_V2::Wippersnapper_V2() { // UART WsV2._uartComponentV2 = new ws_uart(); - // DallasSemi (OneWire) - WsV2._ds18x20ComponentV2 = new ws_ds18x20(); - // Initialize model classes WsV2.sensorModel = new SensorModel(); diff --git a/src/Wippersnapper_V2.h b/src/Wippersnapper_V2.h index 7b2291f76..246186ad8 100644 --- a/src/Wippersnapper_V2.h +++ b/src/Wippersnapper_V2.h @@ -56,7 +56,6 @@ // Components (API v1) #include "components/analogIO/Wippersnapper_AnalogIO.h" -#include "components/ds18x20/ws_ds18x20.h" #include "components/i2c/WipperSnapper_I2C.h" #include "components/pixels/ws_pixels.h" #include "components/pwm/ws_pwm.h" @@ -107,7 +106,6 @@ class ws_ledc; class WipperSnapper_Component_I2C; class ws_servo; class ws_pwm; -class ws_ds18x20; class ws_pixels; class ws_uart; @@ -214,7 +212,6 @@ class Wippersnapper_V2 { ws_pixels *_ws_pixelsComponentV2; ///< ptr to instance of ws_pixels class ws_pwm *_pwmComponentV2; ///< Instance of pwm class ws_servo *_servoComponentV2; ///< Instance of servo class - ws_ds18x20 *_ds18x20ComponentV2; ///< Instance of DS18x20 class ws_uart *_uartComponentV2; ///< Instance of UART class // API v2 Components diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp new file mode 100644 index 000000000..ec7a8ea20 --- /dev/null +++ b/src/components/ds18x20/controller.cpp @@ -0,0 +1,30 @@ +/*! + * @file controller.cpp + * + * Controller for the ds18x20.proto API + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "controller.h" + +DS18X20Controller::DS18X20Controller() { + _DS18X20_model = new DS18X20Model(); + _DS18X20_hardware = new DS18X20Hardware(); +} + +DS18X20Controller::~DS18X20Controller() { + delete _DS18X20_model; + delete _DS18X20_hardware; +} + +bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { + // TODO: This requires an implementation + return true; +} diff --git a/src/components/ds18x20/controller.h b/src/components/ds18x20/controller.h new file mode 100644 index 000000000..7bfb544d6 --- /dev/null +++ b/src/components/ds18x20/controller.h @@ -0,0 +1,42 @@ +/*! + * @file controller.h + * + * Controller for the DS18X20 API + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DS18X20_CONTROLLER_H +#define WS_DS18X20_CONTROLLER_H +#include "Wippersnapper_V2.h" +#include "hardware.h" +#include "model.h" + +class Wippersnapper_V2; ///< Forward declaration +class DS18X20Model; ///< Forward declaration +class DS18X20Hardware; ///< Forward declaration + +/**************************************************************************/ +/*! + @brief Routes messages between the ds18x20.proto API and the hardware. +*/ +/**************************************************************************/ +class DS18X20Controller { +public: + DS18X20Controller(); + ~DS18X20Controller(); + // Routing + bool Handle_Ds18x20Add(pb_istream_t *stream); + +private: + DS18X20Model *_DS18X20_model; ///< ds18x20 model + DS18X20Hardware *_DS18X20_hardware; ///< ds18x20 hardware +}; +extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance +#endif // WS_DS18X20_CONTROLLER_H \ No newline at end of file diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp new file mode 100644 index 000000000..199f73615 --- /dev/null +++ b/src/components/ds18x20/hardware.cpp @@ -0,0 +1,23 @@ +/*! + * @file hardware.cpp + * + * Hardware interface for the ds18x20.proto API + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "hardware.h" + +DS18X20Hardware::DS18X20Hardware() { + // TODO: Implement this +} + +DS18X20Hardware::~DS18X20Hardware() { + // TODO: Implement this +} \ No newline at end of file diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h new file mode 100644 index 000000000..213ce9df1 --- /dev/null +++ b/src/components/ds18x20/hardware.h @@ -0,0 +1,51 @@ +/*! + * @file model.h + * + * Hardware implementation for the ds18x20.proto message. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DS18X20_HARDWARE_H +#define WS_DS18X20_HARDWARE_H +#include "Wippersnapper_V2.h" +#include + +struct DS18X20_Pin { + // Specific to the DS18X20 sensor object + OneWire + *oneWire; ///< Ptr reference to the OneWire bus object used by this pin + DallasTemperature + *dallasTempObj; ///< Pointer to a DallasTemperature sensor object + DeviceAddress dallasTempAddr; ///< Temperature sensor's address + // From the PB model + char onewire_pin[5]; ///< Pin utilized by the OneWire bus, used for addressing + float period; ///< The desired period to read the sensor, in seconds + float prv_period; ///< Last time the sensor was polled, in seconds + pb_size_t + sensor_types_count; ///< Number of sensor types to read from the sensor + wippersnapper_sensor_SensorType + sensor_types[2]; ///< DS sensor type(s) to read from the sensor +}; ///< DS18X20 Pin Object + +/**************************************************************************/ +/*! + @brief Interface for interacting with the's DallasTemp + and OneWire APIs. +*/ +/**************************************************************************/ +class DS18X20Hardware { +public: + DS18X20Hardware(); + ~DS18X20Hardware(); + +private: + std::vector _DS18X20_Pins; ///< Vector of analogio pins +}; +#endif // WS_DS18X20_HARDWARE_H \ No newline at end of file diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp new file mode 100644 index 000000000..e69f0b850 --- /dev/null +++ b/src/components/ds18x20/model.cpp @@ -0,0 +1,22 @@ +/*! + * @file model.cpp + * + * Model for the ds18x20.proto message. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "model.h" + +DS18X20Model::DS18X20Model() { + // Initialize the DS18X20 messages + _msg_DS18x20Add = wippersnapper_ds18x20_Ds18x20Add_init_zero; +} + +DS18X20Model::~DS18X20Model() {} \ No newline at end of file diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h new file mode 100644 index 000000000..4836d5224 --- /dev/null +++ b/src/components/ds18x20/model.h @@ -0,0 +1,37 @@ +/*! + * @file model.h + * + * Model interface for the DS18X20.proto message. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DS18X20_MODEL_H +#define WS_DS18X20_MODEL_H +#include "Wippersnapper_V2.h" + +/**************************************************************************/ +/*! + @brief Provides an interface for creating, encoding, and parsing + messages from DS18X20.proto. +*/ +/**************************************************************************/ +class DS18X20Model { +public: + DS18X20Model(); + ~DS18X20Model(); + // Ds18x20Add Message + bool DecodeDS18x20Add(pb_istream_t *stream); + wippersnapper_ds18x20_Ds18x20Add *GetDS18x20AddMsg(); + +private: + wippersnapper_ds18x20_Ds18x20Add + _msg_DS18x20Add; ///< wippersnapper_ds18x20_Ds18x20Add message +}; +#endif // WS_DIGITALIO_MODEL_H \ No newline at end of file From ed44d24ea5f3c4d57c41f5d5bc0c0928aff1a5f0 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 7 Oct 2024 15:37:41 -0400 Subject: [PATCH 02/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Plumbing?= =?UTF-8?q?=20for=20ds18x=20in=20App,=20switch=20to=20OneWireNG=20interfac?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio.ini | 4 ++-- src/Wippersnapper_V2.cpp | 1 + src/Wippersnapper_V2.h | 4 ++++ src/components/ds18x20/hardware.h | 8 +------- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/platformio.ini b/platformio.ini index bdd1757b7..79a0d065f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -71,8 +71,8 @@ lib_deps = adafruit/Adafruit TouchScreen adafruit/Adafruit MQTT Library bblanchon/ArduinoJson - https://github.com/PaulStoffregen/OneWire.git - https://github.com/milesburton/Arduino-Temperature-Control-Library.git + https://github.com/pstolarz/OneWireNg.git + https://github.com/pstolarz/Arduino-Temperature-Control-Library.git#OneWireNg https://github.com/Sensirion/arduino-sht.git https://github.com/Sensirion/arduino-i2c-scd4x.git https://github.com/Sensirion/arduino-i2c-sen5x.git diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index a70cea4f7..4dc04b2d7 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -71,6 +71,7 @@ Wippersnapper_V2::Wippersnapper_V2() { // Initialize controller classes WsV2.digital_io_controller = new DigitalIOController(); WsV2.analogio_controller = new AnalogIOController(); + WsV2._ds18x20_controller = new DS18X20Controller(); }; /**************************************************************************/ diff --git a/src/Wippersnapper_V2.h b/src/Wippersnapper_V2.h index 246186ad8..317bac0d4 100644 --- a/src/Wippersnapper_V2.h +++ b/src/Wippersnapper_V2.h @@ -32,6 +32,7 @@ #include "protos/checkin.pb.h" #include "protos/digitalio.pb.h" #include "protos/signal.pb.h" +#include "protos/ds18x20.pb.h" // External libraries #include "Adafruit_MQTT.h" // MQTT Client @@ -52,6 +53,7 @@ #include "components/sensor/model.h" #include "components/digitalIO/controller.h" #include "components/analogio/controller.h" +#include "components/ds18x20/controller.h" // Components (API v1) @@ -114,6 +116,7 @@ class CheckinModel; class SensorModel; class DigitalIOController; class AnalogIOController; +class DS18X20Controller; /**************************************************************************/ /*! @@ -220,6 +223,7 @@ class Wippersnapper_V2 { DigitalIOController *digital_io_controller; ///< Instance of DigitalIO controller class AnalogIOController *analogio_controller; ///< Instance of AnalogIO controller + DS18X20Controller *_ds18x20_controller; ///< Instance of DS18X20 controller // TODO: does this really need to be global? uint8_t _macAddrV2[6]; /*!< Unique network iface identifier */ diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 213ce9df1..a166d13c7 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -15,15 +15,10 @@ #ifndef WS_DS18X20_HARDWARE_H #define WS_DS18X20_HARDWARE_H #include "Wippersnapper_V2.h" -#include struct DS18X20_Pin { // Specific to the DS18X20 sensor object - OneWire - *oneWire; ///< Ptr reference to the OneWire bus object used by this pin - DallasTemperature - *dallasTempObj; ///< Pointer to a DallasTemperature sensor object - DeviceAddress dallasTempAddr; ///< Temperature sensor's address + // TODO: Implement this! // From the PB model char onewire_pin[5]; ///< Pin utilized by the OneWire bus, used for addressing float period; ///< The desired period to read the sensor, in seconds @@ -44,7 +39,6 @@ class DS18X20Hardware { public: DS18X20Hardware(); ~DS18X20Hardware(); - private: std::vector _DS18X20_Pins; ///< Vector of analogio pins }; From c10dca5ce42044b76dae2e24cbe10713754cda88 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Oct 2024 10:21:09 -0400 Subject: [PATCH 03/21] implement setup for dsx, remove deps that conflict --- platformio.ini | 1 - src/Wippersnapper.cpp | 44 ---- src/Wippersnapper.h | 3 - src/components/ds18x20/controller.cpp | 20 +- src/components/ds18x20/controller.h | 5 +- src/components/ds18x20/hardware.cpp | 37 ++- src/components/ds18x20/hardware.h | 34 +-- src/components/ds18x20/model.cpp | 9 +- src/components/ds18x20/ws_ds18x20.cpp | 313 -------------------------- src/components/ds18x20/ws_ds18x20.h | 65 ------ 10 files changed, 75 insertions(+), 456 deletions(-) delete mode 100644 src/components/ds18x20/ws_ds18x20.cpp delete mode 100644 src/components/ds18x20/ws_ds18x20.h diff --git a/platformio.ini b/platformio.ini index 79a0d065f..7377a2f5f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -72,7 +72,6 @@ lib_deps = adafruit/Adafruit MQTT Library bblanchon/ArduinoJson https://github.com/pstolarz/OneWireNg.git - https://github.com/pstolarz/Arduino-Temperature-Control-Library.git#OneWireNg https://github.com/Sensirion/arduino-sht.git https://github.com/Sensirion/arduino-i2c-scd4x.git https://github.com/Sensirion/arduino-i2c-sen5x.git diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 90c443a8f..e34d893a8 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -66,9 +66,6 @@ Wippersnapper::Wippersnapper() { // UART WS._uartComponent = new ws_uart(); - - // DallasSemi (OneWire) - WS._ds18x20Component = new ws_ds18x20(); }; /**************************************************************************/ @@ -1319,43 +1316,6 @@ void cbPWMMsg(char *data, uint16_t len) { bool cbDecodeDs18x20Msg(pb_istream_t *stream, const pb_field_t *field, void **arg) { (void)arg; // marking unused parameter to avoid compiler warning - if (field->tag == - wippersnapper_signal_v1_Ds18x20Request_req_ds18x20_init_tag) { - WS_DEBUG_PRINTLN("[Message Type] Init. DS Sensor"); - // Attempt to decode contents of DS18x20 message - wippersnapper_ds18x20_v1_Ds18x20InitRequest msgDS18xInitReq = - wippersnapper_ds18x20_v1_Ds18x20InitRequest_init_zero; - - if (!ws_pb_decode(stream, - wippersnapper_ds18x20_v1_Ds18x20InitRequest_fields, - &msgDS18xInitReq)) { - WS_DEBUG_PRINTLN("ERROR: Could not decode " - "wippersnapper_ds18x20_v1_Ds18x20InitRequest"); - return false; // fail out if we can't decode the request - } - WS_DEBUG_PRINT("Adding DS18x20 Component..."); - if (!WS._ds18x20Component->addDS18x20(&msgDS18xInitReq)) - return false; - WS_DEBUG_PRINTLN("Added!"); - } else if (field->tag == - wippersnapper_signal_v1_Ds18x20Request_req_ds18x20_deinit_tag) { - WS_DEBUG_PRINTLN("[Message Type] De-init. DS Sensor"); - // Attempt to decode contents of message - wippersnapper_ds18x20_v1_Ds18x20DeInitRequest msgDS18xDeInitReq = - wippersnapper_ds18x20_v1_Ds18x20DeInitRequest_init_zero; - if (!ws_pb_decode(stream, - wippersnapper_ds18x20_v1_Ds18x20DeInitRequest_fields, - &msgDS18xDeInitReq)) { - WS_DEBUG_PRINTLN("ERROR: Could not decode " - "wippersnapper_ds18x20_v1_Ds18x20DeInitRequest"); - return false; // fail out if we can't decode the request - } - // exec. deinit request - WS._ds18x20Component->deleteDS18x20(&msgDS18xDeInitReq); - } else { - WS_DEBUG_PRINTLN("ERROR: DS Message type not found!"); - return false; - } return true; } @@ -2876,10 +2836,6 @@ ws_status_t Wippersnapper::run() { WS._i2cPort0->update(); WS.feedWDT(); - // Process DS18x20 sensor events - WS._ds18x20Component->update(); - WS.feedWDT(); - // Process UART sensor events WS._uartComponent->update(); WS.feedWDT(); diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 7f4ae8790..a79beebd4 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -64,7 +64,6 @@ #include "display/ws_display_ui_helper.h" #endif -#include "components/ds18x20/ws_ds18x20.h" #include "components/pixels/ws_pixels.h" #include "components/pwm/ws_pwm.h" #include "components/servo/ws_servo.h" @@ -104,7 +103,6 @@ class ws_ledc; class WipperSnapper_Component_I2C; class ws_servo; class ws_pwm; -class ws_ds18x20; class ws_pixels; class ws_uart; @@ -227,7 +225,6 @@ class Wippersnapper { ws_pixels *_ws_pixelsComponent; ///< ptr to instance of ws_pixels class ws_pwm *_pwmComponent; ///< Instance of pwm class ws_servo *_servoComponent; ///< Instance of servo class - ws_ds18x20 *_ds18x20Component; ///< Instance of DS18x20 class ws_uart *_uartComponent; ///< Instance of UART class // TODO: does this really need to be global? diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index ec7a8ea20..16ee86126 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -14,17 +14,19 @@ */ #include "controller.h" -DS18X20Controller::DS18X20Controller() { - _DS18X20_model = new DS18X20Model(); - _DS18X20_hardware = new DS18X20Hardware(); -} +DS18X20Controller::DS18X20Controller() { _DS18X20_model = new DS18X20Model(); } -DS18X20Controller::~DS18X20Controller() { - delete _DS18X20_model; - delete _DS18X20_hardware; -} +DS18X20Controller::~DS18X20Controller() { delete _DS18X20_model; } bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { - // TODO: This requires an implementation + // Attempt to decode the incoming message into a Ds18x20Add message + if (!_DS18X20_model->DecodeDS18x20Add(stream)) { + WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Add message"); + return false; + } + // Pass the decoded message to the hardware + // TODO: Brent you were here and looking at this: + // https://github.com/pstolarz/OneWireNg/blob/master/examples/arduino/DallasTemperature/DallasTemperature.ino#L125 + return true; } diff --git a/src/components/ds18x20/controller.h b/src/components/ds18x20/controller.h index 7bfb544d6..aa48e47ee 100644 --- a/src/components/ds18x20/controller.h +++ b/src/components/ds18x20/controller.h @@ -35,8 +35,9 @@ class DS18X20Controller { bool Handle_Ds18x20Add(pb_istream_t *stream); private: - DS18X20Model *_DS18X20_model; ///< ds18x20 model - DS18X20Hardware *_DS18X20_hardware; ///< ds18x20 hardware + DS18X20Model *_DS18X20_model; ///< ds18x20 model + std::vector + _DS18X20_pins; ///< Vector containing multiple DS18X20Hardware objects }; extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance #endif // WS_DS18X20_CONTROLLER_H \ No newline at end of file diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 199f73615..602106d56 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -14,10 +14,39 @@ */ #include "hardware.h" -DS18X20Hardware::DS18X20Hardware() { - // TODO: Implement this +DS18X20Hardware::DS18X20Hardware(uint8_t onewire_pin) : _drv_therm(_ow) { + new (&_ow) OneWireNg_CurrentPlatform(onewire_pin, false); } -DS18X20Hardware::~DS18X20Hardware() { - // TODO: Implement this +DS18X20Hardware::~DS18X20Hardware() { delete &_ow; } + +void DS18X20Hardware::setResolution(int resolution) { + // Set the resolution of the DS18X20 sensor driver + switch (resolution) { + case 9: + _resolution = DSTherm::Resolution::RES_9_BIT; + break; + case 10: + _resolution = DSTherm::Resolution::RES_10_BIT; + break; + case 11: + _resolution = DSTherm::Resolution::RES_11_BIT; + break; + case 12: + _resolution = DSTherm::Resolution::RES_12_BIT; + break; + default: + _resolution = + DSTherm::Resolution::RES_12_BIT; // Default to 12-bit resolution + break; + } + + // Set common resolution for all sensors. + // Th, Tl (high/low alarm triggers) are set to 0. + _drv_therm.writeScratchpadAll(0, 0, _resolution); + + // The configuration above is stored in volatile sensors scratchpad + // memory and will be lost after power unplug. Therefore store the + // configuration permanently in sensors EEPROM. + _drv_therm.copyScratchpadAll(false); } \ No newline at end of file diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index a166d13c7..c37737681 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -16,18 +16,9 @@ #define WS_DS18X20_HARDWARE_H #include "Wippersnapper_V2.h" -struct DS18X20_Pin { - // Specific to the DS18X20 sensor object - // TODO: Implement this! - // From the PB model - char onewire_pin[5]; ///< Pin utilized by the OneWire bus, used for addressing - float period; ///< The desired period to read the sensor, in seconds - float prv_period; ///< Last time the sensor was polled, in seconds - pb_size_t - sensor_types_count; ///< Number of sensor types to read from the sensor - wippersnapper_sensor_SensorType - sensor_types[2]; ///< DS sensor type(s) to read from the sensor -}; ///< DS18X20 Pin Object +#include "OneWireNg_CurrentPlatform.h" +#include "drivers/DSTherm.h" +#include "utils/Placeholder.h" /**************************************************************************/ /*! @@ -37,9 +28,24 @@ struct DS18X20_Pin { /**************************************************************************/ class DS18X20Hardware { public: - DS18X20Hardware(); + DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); + void setResolution(int resolution); + private: - std::vector _DS18X20_Pins; ///< Vector of analogio pins + // NOTE: We are going to try definining a vector of DS18X20Hardware objects + // iwthin the controller so instead of a struct, these are all assigned to + // this class + Placeholder _ow; ///< OneWire bus object + DSTherm _drv_therm; ///< DS18X20 driver object + DSTherm::Resolution _resolution; ///< Resolution of the DS18X20 sensor + // From the PB model + uint8_t onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing + float _period; ///< The desired period to read the sensor, in seconds + float _prv_period; ///< Last time the sensor was polled, in seconds + pb_size_t + _sensor_types_count; ///< Number of sensor types to read from the sensor + wippersnapper_sensor_SensorType + _sensor_types[2]; ///< DS sensor type(s) to read from the sensor }; #endif // WS_DS18X20_HARDWARE_H \ No newline at end of file diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index e69f0b850..39a3decbf 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -19,4 +19,11 @@ DS18X20Model::DS18X20Model() { _msg_DS18x20Add = wippersnapper_ds18x20_Ds18x20Add_init_zero; } -DS18X20Model::~DS18X20Model() {} \ No newline at end of file +DS18X20Model::~DS18X20Model() {} + +bool DS18X20Model::DecodeDS18x20Add(pb_istream_t *stream) { + _msg_DS18x20Add = wippersnapper_ds18x20_Ds18x20Add_init_zero; + // Attempt to decode the stream into a Ds18x20Add message + return pb_decode(stream, wippersnapper_ds18x20_Ds18x20Add_fields, + &_msg_DS18x20Add); +} \ No newline at end of file diff --git a/src/components/ds18x20/ws_ds18x20.cpp b/src/components/ds18x20/ws_ds18x20.cpp deleted file mode 100644 index 0cfa6e0c5..000000000 --- a/src/components/ds18x20/ws_ds18x20.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/*! - * @file ws_ds18x20.cpp - * - * This component implements 1-wire communication - * for the DS18X20-line of Maxim Temperature ICs. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2022-2023 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ - -#include "ws_ds18x20.h" - -/*************************************************************/ -/*! - @brief Creates a new WipperSnapper Ds18x20 component. -*/ -/*************************************************************/ -ws_ds18x20::ws_ds18x20() {} - -/*************************************************************/ -/*! - @brief Destructor for a WipperSnapper DS18X20 component. -*/ -/*************************************************************/ -ws_ds18x20::~ws_ds18x20() { - // delete DallasTemp sensors and release onewire buses - for (size_t idx = 0; idx < _ds18xDrivers.size(); idx++) { - delete _ds18xDrivers[idx]->dallasTempObj; - delete _ds18xDrivers[idx]->oneWire; - } - // remove all elements - _ds18xDrivers.clear(); -} - -/********************************************************************/ -/*! - @brief Initializes a DS18x20 sensor using a - configuration sent by the broker and adds it to a - vector of ds18x20 sensor drivers. - @param msgDs18x20InitReq - Message containing configuration data for a - ds18x20 sensor. - @returns True if initialized successfully, False otherwise. -*/ -/********************************************************************/ -bool ws_ds18x20::addDS18x20( - wippersnapper_ds18x20_v1_Ds18x20InitRequest *msgDs18x20InitReq) { - bool is_success = false; - - // init. new ds18x20 object - ds18x20Obj *newObj = new ds18x20Obj(); - char *oneWirePin = msgDs18x20InitReq->onewire_pin + 1; - newObj->oneWire = new OneWire(atoi(oneWirePin)); - newObj->dallasTempObj = new DallasTemperature(newObj->oneWire); - newObj->dallasTempObj->begin(); - // attempt to obtain sensor address - if (newObj->dallasTempObj->getAddress(newObj->dallasTempAddr, 0)) { - // attempt to set sensor resolution - newObj->dallasTempObj->setResolution(msgDs18x20InitReq->sensor_resolution); - // copy the device's sensor properties - newObj->sensorPropertiesCount = - msgDs18x20InitReq->i2c_device_properties_count; - // TODO: Make sure this works, it's a new idea and untested :) - for (int i = 0; i < newObj->sensorPropertiesCount; i++) { - newObj->sensorProperties[i].sensor_type = - msgDs18x20InitReq->i2c_device_properties[i].sensor_type; - newObj->sensorProperties[i].sensor_period = - (long)msgDs18x20InitReq->i2c_device_properties[i].sensor_period * - 1000; - } - // set pin - strcpy(newObj->onewire_pin, msgDs18x20InitReq->onewire_pin); - // add the new ds18x20 driver to vec. - _ds18xDrivers.push_back(newObj); - is_success = true; - } else { - WS_DEBUG_PRINTLN("Failed to find DSx sensor on specified pin."); - } - - // fill and publish the initialization response back to the broker - size_t msgSz; // message's encoded size - wippersnapper_signal_v1_Ds18x20Response msgInitResp = - wippersnapper_signal_v1_Ds18x20Response_init_zero; - msgInitResp.which_payload = - wippersnapper_signal_v1_Ds18x20Response_resp_ds18x20_init_tag; - msgInitResp.payload.resp_ds18x20_init.is_initialized = is_success; - strcpy(msgInitResp.payload.resp_ds18x20_init.onewire_pin, - msgDs18x20InitReq->onewire_pin); - - WS_DEBUG_PRINT("Created OneWireBus on GPIO "); - WS_DEBUG_PRINT(msgDs18x20InitReq->onewire_pin); - WS_DEBUG_PRINTLN(" with DS18x20 attached!"); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[DS18x] Attached DS18x20 sensor to pin %s\n", - msgDs18x20InitReq->onewire_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - - // Encode and publish response back to broker - memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing)); - pb_ostream_t ostream = - pb_ostream_from_buffer(WS._buffer_outgoing, sizeof(WS._buffer_outgoing)); - if (!ws_pb_encode(&ostream, wippersnapper_signal_v1_Ds18x20Response_fields, - &msgInitResp)) { - WS_DEBUG_PRINTLN("ERROR: Unable to encode msg_init response message!"); - return false; - } - pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_Ds18x20Response_fields, - &msgInitResp); - WS_DEBUG_PRINT("-> DS18x Init Response..."); - WS._mqtt->publish(WS._topic_signal_ds18_device, WS._buffer_outgoing, msgSz, - 1); - WS_DEBUG_PRINTLN("Published!"); - - return is_success; -} - -/********************************************************************/ -/*! - @brief De-initializes a DS18x20 sensor and releases its - pin and resources. - @param msgDS18x20DeinitReq - Message containing configuration data for a - ds18x20 sensor. -*/ -/********************************************************************/ -void ws_ds18x20::deleteDS18x20( - wippersnapper_ds18x20_v1_Ds18x20DeInitRequest *msgDS18x20DeinitReq) { - // Loop thru vector of drivers to find the unique address - for (size_t idx = 0; idx < _ds18xDrivers.size(); idx++) { - if (strcmp(_ds18xDrivers[idx]->onewire_pin, - msgDS18x20DeinitReq->onewire_pin) == 0) { - WS_DEBUG_PRINT("Deleting OneWire instance on pin "); - WS_DEBUG_PRINTLN(msgDS18x20DeinitReq->onewire_pin); - delete _ds18xDrivers[idx] - ->dallasTempObj; // delete dallas temp instance on pin - delete _ds18xDrivers[idx] - ->oneWire; // delete OneWire instance on pin and release pin for reuse - _ds18xDrivers.erase(_ds18xDrivers.begin() + - idx); // erase vector and re-allocate - } - } - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[DS18x] Deleted DS18x20 sensor on pin %s\n", - msgDS18x20DeinitReq->onewire_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif -} - -/*************************************************************/ -/*! - @brief Iterates through each ds18x20 sensor and - reports data (if period expired) to Adafruit IO. -*/ -/*************************************************************/ -void ws_ds18x20::update() { - // return immediately if no drivers have been initialized - if (_ds18xDrivers.size() == 0) - return; - - long curTime; // used for holding the millis() value - std::vector::iterator iter, end; - for (iter = _ds18xDrivers.begin(), end = _ds18xDrivers.end(); iter != end; - ++iter) { - - // Create an empty DS18x20 event signal message and configure - wippersnapper_signal_v1_Ds18x20Response msgDS18x20Response = - wippersnapper_signal_v1_Ds18x20Response_init_zero; - msgDS18x20Response.which_payload = - wippersnapper_signal_v1_Ds18x20Response_resp_ds18x20_event_tag; - - // take the current time for the driver (*iter) - curTime = millis(); - // Poll each sensor type, if period has elapsed - for (int i = 0; i < (*iter)->sensorPropertiesCount; i++) { - // has sensor_period elapsed? - if (curTime - (*iter)->sensorPeriodPrv > - (long)(*iter)->sensorProperties[i].sensor_period) { - // issue global temperature request to all DS sensors - WS_DEBUG_PRINTLN("Requesting temperature.."); - (*iter)->dallasTempObj->requestTemperatures(); - // poll the DS sensor driver - float tempC = (*iter)->dallasTempObj->getTempC((*iter)->dallasTempAddr); - if (tempC == DEVICE_DISCONNECTED_C) { - WS_DEBUG_PRINTLN("ERROR: Could not read temperature data, is the " - "sensor disconnected?"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[DS18x ERROR] Unable to read temperature, is the sensor " - "disconnected?\n"); -#endif - break; - } - - // check and pack based on sensorType - char buffer[100]; - if ((*iter)->sensorProperties[i].sensor_type == - wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE) { - - WS_DEBUG_PRINT("(OneWireBus GPIO: "); - WS_DEBUG_PRINT((*iter)->onewire_pin); - WS_DEBUG_PRINT(") DS18x20 Value: "); - WS_DEBUG_PRINT(tempC); - WS_DEBUG_PRINTLN("*C") - snprintf(buffer, 100, "[DS18x] Read %0.2f*C on GPIO %s\n", tempC, - (*iter)->onewire_pin); - - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i].type = - wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i].value = - tempC; - - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event_count++; - } - - if ((*iter)->sensorProperties[i].sensor_type == - wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT) { - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i].type = - wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i].value = - (*iter)->dallasTempObj->toFahrenheit(tempC); - WS_DEBUG_PRINT("(OneWireBus GPIO: "); - WS_DEBUG_PRINT((*iter)->onewire_pin); - WS_DEBUG_PRINT(") DS18x20 Value: "); - WS_DEBUG_PRINT( - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i] - .value); - WS_DEBUG_PRINTLN("*F") - snprintf(buffer, 100, "[DS18x] Read %0.2f*F on GPIO %s\n", - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i] - .value, - (*iter)->onewire_pin); - - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event_count++; - } - - // did we obtain the expected amount of sensor events for the - // `resp_ds18x20_event` message? - if (msgDS18x20Response.payload.resp_ds18x20_event.sensor_event_count == - (*iter)->sensorPropertiesCount) { - - // prep sensor event data for sending to IO - // use onewire_pin as the "address" - strcpy(msgDS18x20Response.payload.resp_ds18x20_event.onewire_pin, - (*iter)->onewire_pin); - // prep and encode buffer - memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing)); - pb_ostream_t ostream = pb_ostream_from_buffer( - WS._buffer_outgoing, sizeof(WS._buffer_outgoing)); - if (!ws_pb_encode(&ostream, - wippersnapper_signal_v1_Ds18x20Response_fields, - &msgDS18x20Response)) { - WS_DEBUG_PRINTLN( - "ERROR: Unable to encode DS18x20 event responsemessage!"); - snprintf(buffer, 100, - "[DS18x ERROR] Unable to encode event message!"); - return; - } - - WS_DEBUG_PRINTLN( - "DEBUG: msgDS18x20Response sensor_event message contents:"); - for (int i = 0; - i < - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event_count; - i++) { - WS_DEBUG_PRINT("sensor_event[#]: "); - WS_DEBUG_PRINTLN(i); - WS_DEBUG_PRINT("\tOneWire Bus: "); - WS_DEBUG_PRINTLN( - msgDS18x20Response.payload.resp_ds18x20_event.onewire_pin); - WS_DEBUG_PRINT("\tsensor_event type: "); - WS_DEBUG_PRINTLN( - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i] - .type); - WS_DEBUG_PRINT("\tsensor_event value: "); - WS_DEBUG_PRINTLN( - msgDS18x20Response.payload.resp_ds18x20_event.sensor_event[i] - .value); - } - - // Publish I2CResponse msg - size_t msgSz; - pb_get_encoded_size(&msgSz, - wippersnapper_signal_v1_Ds18x20Response_fields, - &msgDS18x20Response); - WS_DEBUG_PRINT("PUBLISHING -> msgDS18x20Response Event Message..."); - if (!WS._mqtt->publish(WS._topic_signal_ds18_device, - WS._buffer_outgoing, msgSz, 1)) { - WS_DEBUG_PRINTLN("ERROR: Unable to publish DS18x20 event message - " - "MQTT Publish failed!"); - return; - }; - WS_DEBUG_PRINTLN("PUBLISHED!"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal(buffer); -#endif - - (*iter)->sensorPeriodPrv = curTime; // set prv period - } - } - } - } -} \ No newline at end of file diff --git a/src/components/ds18x20/ws_ds18x20.h b/src/components/ds18x20/ws_ds18x20.h deleted file mode 100644 index 5398d4c4f..000000000 --- a/src/components/ds18x20/ws_ds18x20.h +++ /dev/null @@ -1,65 +0,0 @@ -/*! - * @file ws_ds18x20.h - * - * This component implements 1-wire communication - * for the DS18X20-line of Maxim Temperature ICs. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2022 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#ifndef WIPPERSNAPPER_DS18X20_H -#define WIPPERSNAPPER_DS18X20_H - -#include "Wippersnapper.h" - -#include -#include - -/** DS18x20 Object */ -struct ds18x20Obj { - OneWire * - oneWire; ///< Pointer to an OneWire bus used by a DallasTemperature object - char onewire_pin[5]; ///< Pin utilized by the OneWire bus, used for addressing - DallasTemperature - *dallasTempObj; ///< Pointer to a DallasTemperature sensor object - DeviceAddress dallasTempAddr; ///< Temperature sensor's address - int sensorPropertiesCount; ///< Tracks # of sensorProperties - wippersnapper_i2c_v1_I2CDeviceSensorProperties sensorProperties[2] = - wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero; ///< DS sensor - ///< type(s) - long sensorPeriodPrv; ///< Last time the sensor was polled, in millis -}; - -// forward decl. -class Wippersnapper; - -/**************************************************************************/ -/*! - @brief Class that provides an interface with DS18X20-compatible - sensors. -*/ -/**************************************************************************/ -class ws_ds18x20 { -public: - ws_ds18x20(); - ~ws_ds18x20(); - - bool - addDS18x20(wippersnapper_ds18x20_v1_Ds18x20InitRequest *msgDs18x20InitReq); - void deleteDS18x20( - wippersnapper_ds18x20_v1_Ds18x20DeInitRequest *msgDS18x20DeinitReq); - void update(); - -private: - std::vector - _ds18xDrivers; ///< Vec. of ptrs. to ds18x driver objects -}; -extern Wippersnapper WS; - -#endif // WIPPERSNAPPER_DS18X20_H \ No newline at end of file From f4f7432cffe45a1b2774fbcb44ba597d52f5cf6a Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Oct 2024 12:37:23 -0400 Subject: [PATCH 04/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20added=20m?= =?UTF-8?q?essage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 15 ++++++++++++--- src/components/ds18x20/model.cpp | 23 +++++++++++++++++++++++ src/components/ds18x20/model.h | 4 ++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 16ee86126..d7bfd5f7c 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -24,9 +24,18 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Add message"); return false; } - // Pass the decoded message to the hardware - // TODO: Brent you were here and looking at this: - // https://github.com/pstolarz/OneWireNg/blob/master/examples/arduino/DallasTemperature/DallasTemperature.ino#L125 + // Extract the OneWire pin from the message + uint8_t pin_name = atoi(_DS18X20_model->GetDS18x20AddMsg()->onewire_pin + 1); + + // Initialize the DS18X20Hardware object + DS18X20Hardware new_dsx_driver(pin_name); + new_dsx_driver.setResolution( + _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); + + // Add the DS18X20Hardware object to the vector of hardware objects + _DS18X20_pins.push_back(new_dsx_driver); + + // TODO: We should publish back an Added message to the broker return true; } diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index 39a3decbf..cf3724f7c 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -26,4 +26,27 @@ bool DS18X20Model::DecodeDS18x20Add(pb_istream_t *stream) { // Attempt to decode the stream into a Ds18x20Add message return pb_decode(stream, wippersnapper_ds18x20_Ds18x20Add_fields, &_msg_DS18x20Add); +} + +wippersnapper_ds18x20_Ds18x20Add *DS18X20Model::GetDS18x20AddMsg() { + return &_msg_DS18x20Add; +} + +bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { + // Fill the Ds18x20Added message + _msg_DS18x20Added = wippersnapper_ds18x20_Ds18x20Added_init_zero; + _msg_DS18x20Added.is_initialized = is_init; + strcpy(_msg_DS18x20Added.onewire_pin, onewire_pin); + + // Encode the Ds18x20Added message + size_t sz_aio_event_msg; + if (!pb_get_encoded_size(&sz_aio_event_msg, + wippersnapper_ds18x20_Ds18x20Added_fields, + &_msg_DS18x20Added)) + return false; + + uint8_t buf[sz_aio_event_msg]; + pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); + return pb_encode(&msg_stream, wippersnapper_ds18x20_Ds18x20Added_fields, + &_msg_DS18x20Added); } \ No newline at end of file diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index 4836d5224..eda6c0ff3 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -29,9 +29,13 @@ class DS18X20Model { // Ds18x20Add Message bool DecodeDS18x20Add(pb_istream_t *stream); wippersnapper_ds18x20_Ds18x20Add *GetDS18x20AddMsg(); + // Ds18x20Remove Message + bool EncodeDS18x20Added(char *onewire_pin, bool is_init); private: wippersnapper_ds18x20_Ds18x20Add _msg_DS18x20Add; ///< wippersnapper_ds18x20_Ds18x20Add message + wippersnapper_ds18x20_Ds18x20Added + _msg_DS18x20Added; ///< wippersnapper_ds18x20_Ds18x20Added message }; #endif // WS_DIGITALIO_MODEL_H \ No newline at end of file From dc7c54ea780acc479739080109abc21d9417f3be Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Oct 2024 12:49:05 -0400 Subject: [PATCH 05/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20analogio=20-=20publ?= =?UTF-8?q?ish=20out=20to=20the=20broker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Wippersnapper_V2.cpp | 12 +++++++++--- src/components/ds18x20/controller.cpp | 14 +++++++++++++- src/components/ds18x20/model.cpp | 6 +++++- src/components/ds18x20/model.h | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 4dc04b2d7..17ab247ca 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -862,26 +862,32 @@ bool Wippersnapper_V2::PublishSignal(pb_size_t which_payload, void *payload) { WS_DEBUG_PRINT("Signal Payload Type: "); switch (which_payload) { case wippersnapper_signal_DeviceToBroker_checkin_request_tag: - WS_DEBUG_PRINTLN("Checkin Request"); + WS_DEBUG_PRINTLN("CheckinRequest"); MsgSignal.which_payload = wippersnapper_signal_DeviceToBroker_checkin_request_tag; MsgSignal.payload.checkin_request = *(wippersnapper_checkin_CheckinRequest *)payload; break; case wippersnapper_signal_DeviceToBroker_digitalio_event_tag: - WS_DEBUG_PRINTLN("DigitalIO Event"); + WS_DEBUG_PRINTLN("DigitalIOEvent"); MsgSignal.which_payload = wippersnapper_signal_DeviceToBroker_digitalio_event_tag; MsgSignal.payload.digitalio_event = *(wippersnapper_digitalio_DigitalIOEvent *)payload; break; case wippersnapper_signal_DeviceToBroker_analogio_event_tag: - WS_DEBUG_PRINTLN("AnalogIO Event"); + WS_DEBUG_PRINTLN("AnalogIOEvent"); MsgSignal.which_payload = wippersnapper_signal_DeviceToBroker_analogio_event_tag; MsgSignal.payload.analogio_event = *(wippersnapper_analogio_AnalogIOEvent *)payload; break; + case wippersnapper_signal_DeviceToBroker_ds18x20_added_tag: + WS_DEBUG_PRINTLN("DS18X20Added"); + MsgSignal.which_payload = + wippersnapper_signal_DeviceToBroker_ds18x20_added_tag; + MsgSignal.payload.ds18x20_added = *(wippersnapper_ds18x20_Ds18x20Added *)payload; + break; default: WS_DEBUG_PRINTLN("ERROR: Invalid signal payload type, bailing out!"); return false; diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index d7bfd5f7c..18b048d7a 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -35,7 +35,19 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { // Add the DS18X20Hardware object to the vector of hardware objects _DS18X20_pins.push_back(new_dsx_driver); - // TODO: We should publish back an Added message to the broker + // Encode and publish a Ds18x20Added message back to the broker + if (!_DS18X20_model->EncodeDS18x20Added( + _DS18X20_model->GetDS18x20AddMsg()->onewire_pin, true)) { + WS_DEBUG_PRINTLN("ERROR: Unable to encode Ds18x20Added message"); + return false; + } + + // Publish the AnalogIO message to the broker + if (!WsV2.PublishSignal(wippersnapper_signal_DeviceToBroker_ds18x20_added_tag, + _DS18X20_model->GetDS18x20AddedMsg())) { + WS_DEBUG_PRINTLN("ERROR: Unable to publish Ds18x20Added message"); + return false; + } return true; } diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index cf3724f7c..5d0565a53 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -32,6 +32,10 @@ wippersnapper_ds18x20_Ds18x20Add *DS18X20Model::GetDS18x20AddMsg() { return &_msg_DS18x20Add; } +wippersnapper_ds18x20_Ds18x20Added *DS18X20Model::GetDS18x20AddedMsg() { + return &_msg_DS18x20Added; +} + bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { // Fill the Ds18x20Added message _msg_DS18x20Added = wippersnapper_ds18x20_Ds18x20Added_init_zero; @@ -49,4 +53,4 @@ bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); return pb_encode(&msg_stream, wippersnapper_ds18x20_Ds18x20Added_fields, &_msg_DS18x20Added); -} \ No newline at end of file +} diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index eda6c0ff3..dad1be0f6 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -31,6 +31,7 @@ class DS18X20Model { wippersnapper_ds18x20_Ds18x20Add *GetDS18x20AddMsg(); // Ds18x20Remove Message bool EncodeDS18x20Added(char *onewire_pin, bool is_init); + wippersnapper_ds18x20_Ds18x20Added *GetDS18x20AddedMsg(); private: wippersnapper_ds18x20_Ds18x20Add From 936f2763e7473d966d7149b705dbde2be78b634b Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Oct 2024 15:46:40 -0400 Subject: [PATCH 06/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Add=20rea?= =?UTF-8?q?d=20and=20sensor=20id=20funcs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 34 +++++++++++++++++++++---- src/components/ds18x20/controller.h | 2 ++ src/components/ds18x20/hardware.cpp | 36 +++++++++++++++++++++++++++ src/components/ds18x20/hardware.h | 8 +++++- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 18b048d7a..c04006e46 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -29,15 +29,23 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { // Initialize the DS18X20Hardware object DS18X20Hardware new_dsx_driver(pin_name); - new_dsx_driver.setResolution( - _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); + // Attempt to get the sensor's ID on the OneWire bus to show it's been init'd + bool is_initialized = new_dsx_driver.GetSensor(); + if (!is_initialized) { + WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); + // Set the sensor's resolution + new_dsx_driver.setResolution( + _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); - // Add the DS18X20Hardware object to the vector of hardware objects - _DS18X20_pins.push_back(new_dsx_driver); + // Add the DS18X20Hardware object to the vector of hardware objects + _DS18X20_pins.push_back(new_dsx_driver); + } else { + WS_DEBUG_PRINTLN("ERROR: Unable to get sensor ID, sensor not initialized"); + } // Encode and publish a Ds18x20Added message back to the broker if (!_DS18X20_model->EncodeDS18x20Added( - _DS18X20_model->GetDS18x20AddMsg()->onewire_pin, true)) { + _DS18X20_model->GetDS18x20AddMsg()->onewire_pin, is_initialized)) { WS_DEBUG_PRINTLN("ERROR: Unable to encode Ds18x20Added message"); return false; } @@ -51,3 +59,19 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { return true; } + +void DS18X20Controller::update() { + // Bail out if there are no OneWire pins to poll + if (_DS18X20_pins.size() == 0) + return; + + // Iterate through the vector + for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { + // Create a temporary DS18X20Hardware driver + DS18X20Hardware *temp_dsx_driver = &_DS18X20_pins[i]; + // Check if the driver's timer has expired + if (temp_dsx_driver->IsTimerExpired()) + return; + // TODO: Poll the sensor + } +} \ No newline at end of file diff --git a/src/components/ds18x20/controller.h b/src/components/ds18x20/controller.h index aa48e47ee..9309377fc 100644 --- a/src/components/ds18x20/controller.h +++ b/src/components/ds18x20/controller.h @@ -33,6 +33,8 @@ class DS18X20Controller { ~DS18X20Controller(); // Routing bool Handle_Ds18x20Add(pb_istream_t *stream); + // Polling + void update(); private: DS18X20Model *_DS18X20_model; ///< ds18x20 model diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 602106d56..fb4843bc1 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -15,11 +15,17 @@ #include "hardware.h" DS18X20Hardware::DS18X20Hardware(uint8_t onewire_pin) : _drv_therm(_ow) { + // Initialize the OneWire bus object new (&_ow) OneWireNg_CurrentPlatform(onewire_pin, false); } DS18X20Hardware::~DS18X20Hardware() { delete &_ow; } +bool DS18X20Hardware::GetSensor() { + OneWireNg::ErrorCode ec = _ow->readSingleId(_sensorId); + return ec == OneWireNg::EC_SUCCESS; +} + void DS18X20Hardware::setResolution(int resolution) { // Set the resolution of the DS18X20 sensor driver switch (resolution) { @@ -49,4 +55,34 @@ void DS18X20Hardware::setResolution(int resolution) { // memory and will be lost after power unplug. Therefore store the // configuration permanently in sensors EEPROM. _drv_therm.copyScratchpadAll(false); +} + +bool DS18X20Hardware::IsTimerExpired() { + // Get the current time in milliseconds and compare it to the last time + // the sensor was polled + ulong cur_time = millis(); + return millis() - _prv_period > _period; +} + +OneWireNg::ErrorCode DS18X20Hardware::ReadTemperatureC() { + // Start temperature conversion for the first identified sensor on the OneWire + // bus + OneWireNg::ErrorCode ec = + _drv_therm.convertTemp(_sensorId, DSTherm::MAX_CONV_TIME, false); + if (ec != OneWireNg::EC_SUCCESS) + return ec; + + // Scratchpad placeholder is static to allow reuse of the associated + // sensor id while reissuing readScratchpadSingle() calls. + // Note, due to its storage class the placeholder is zero initialized. + static Placeholder scrpd; + ec = _drv_therm.readScratchpadSingle(scrpd); + if (ec != OneWireNg::EC_SUCCESS) + return ec; + + // Read the temperature from the sensor + long temp = scrpd->getTemp2(); + _temp_c = temp / 16.0; // Convert from 16-bit int to float + + return ec; } \ No newline at end of file diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index c37737681..4a1459615 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -30,15 +30,21 @@ class DS18X20Hardware { public: DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); + bool GetSensor(); + OneWireNg::ErrorCode DS18X20Hardware::ReadTemperatureC(); void setResolution(int resolution); + bool IsTimerExpired(); private: // NOTE: We are going to try definining a vector of DS18X20Hardware objects // iwthin the controller so instead of a struct, these are all assigned to // this class Placeholder _ow; ///< OneWire bus object - DSTherm _drv_therm; ///< DS18X20 driver object + OneWireNg::Id _sensorId; + DSTherm _drv_therm; ///< DS18X20 driver object DSTherm::Resolution _resolution; ///< Resolution of the DS18X20 sensor + float _temp_c; + float _temp_f; // From the PB model uint8_t onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing float _period; ///< The desired period to read the sensor, in seconds From 605040758a19a2ce09dbd489b8276e09d871850d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Oct 2024 16:17:07 -0400 Subject: [PATCH 07/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Implement?= =?UTF-8?q?=20readF,=20getters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 3 ++- src/components/ds18x20/hardware.cpp | 32 +++++++++++++++++++-------- src/components/ds18x20/hardware.h | 12 +++++----- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index c04006e46..229abb350 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -72,6 +72,7 @@ void DS18X20Controller::update() { // Check if the driver's timer has expired if (temp_dsx_driver->IsTimerExpired()) return; - // TODO: Poll the sensor + // TODO: the update() method should check sensor type(s) + // before polling ReadTemperatureX methods! } } \ No newline at end of file diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index fb4843bc1..1ce14c77e 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -64,25 +64,39 @@ bool DS18X20Hardware::IsTimerExpired() { return millis() - _prv_period > _period; } -OneWireNg::ErrorCode DS18X20Hardware::ReadTemperatureC() { +float DS18X20Hardware::GetTemperatureC() { return _temp_c; } + +float DS18X20Hardware::GetTemperatureF() { return _temp_f; } + +bool DS18X20Hardware::ReadTemperatureF() { + bool is_success = ReadTemperatureC(); + // Did we read the temperature successfully? + if (!is_success) + return false; + // We have the temperature in Celsius, convert to Fahrenheit + _temp_f = _temp_c * 9.0 / 5.0 + 32.0; + return true; +} + +bool DS18X20Hardware::ReadTemperatureC() { // Start temperature conversion for the first identified sensor on the OneWire // bus OneWireNg::ErrorCode ec = _drv_therm.convertTemp(_sensorId, DSTherm::MAX_CONV_TIME, false); if (ec != OneWireNg::EC_SUCCESS) - return ec; + return false - // Scratchpad placeholder is static to allow reuse of the associated - // sensor id while reissuing readScratchpadSingle() calls. - // Note, due to its storage class the placeholder is zero initialized. - static Placeholder scrpd; + // Scratchpad placeholder is static to allow reuse of the associated + // sensor id while reissuing readScratchpadSingle() calls. + // Note, due to its storage class the placeholder is zero initialized. + static Placeholder + scrpd; ec = _drv_therm.readScratchpadSingle(scrpd); if (ec != OneWireNg::EC_SUCCESS) - return ec; + return false; // Read the temperature from the sensor long temp = scrpd->getTemp2(); _temp_c = temp / 16.0; // Convert from 16-bit int to float - - return ec; + return true; } \ No newline at end of file diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 4a1459615..68abe8b62 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -31,20 +31,20 @@ class DS18X20Hardware { DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); bool GetSensor(); - OneWireNg::ErrorCode DS18X20Hardware::ReadTemperatureC(); void setResolution(int resolution); bool IsTimerExpired(); + bool ReadTemperatureC(); + bool ReadTemperatureF(); + float GetTemperatureC(); + float GetTemperatureF(); private: - // NOTE: We are going to try definining a vector of DS18X20Hardware objects - // iwthin the controller so instead of a struct, these are all assigned to - // this class Placeholder _ow; ///< OneWire bus object OneWireNg::Id _sensorId; DSTherm _drv_therm; ///< DS18X20 driver object DSTherm::Resolution _resolution; ///< Resolution of the DS18X20 sensor - float _temp_c; - float _temp_f; + float _temp_c; ///< Temperature in Celsius + float _temp_f; ///< Temperature in Fahrenheit // From the PB model uint8_t onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing float _period; ///< The desired period to read the sensor, in seconds From 922f0a671f6b999d20e578da692aa4ad4799d0d3 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 9 Oct 2024 14:23:37 -0400 Subject: [PATCH 08/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Add=20to?= =?UTF-8?q?=20hardware,=20updat=20eloop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 45 +++++++++++++++++++++------ src/components/ds18x20/hardware.cpp | 38 +++++++++++++++------- src/components/ds18x20/hardware.h | 18 +++++------ 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 229abb350..ac7770135 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -24,6 +24,13 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Add message"); return false; } + + // If we receive no sensor types to configure, bail out + if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types_count == 0) { + WS_DEBUG_PRINTLN("ERROR: No ds18x sensor types provided!"); + return false; + } + // Extract the OneWire pin from the message uint8_t pin_name = atoi(_DS18X20_model->GetDS18x20AddMsg()->onewire_pin + 1); @@ -34,13 +41,27 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { if (!is_initialized) { WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); // Set the sensor's resolution - new_dsx_driver.setResolution( + new_dsx_driver.SetResolution( _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); - + // Set the sensor's period + new_dsx_driver.SetPeriod(_DS18X20_model->GetDS18x20AddMsg()->period); + // Configure the types of sensor reads to perform + for (int i = 0; i < _DS18X20_model->GetDS18x20AddMsg()->sensor_types_count; + i++) { + if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE) { + new_dsx_driver.is_read_temp_c = true; + } else if ( + _DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT) { + new_dsx_driver.is_read_temp_f = true; + } + } // Add the DS18X20Hardware object to the vector of hardware objects _DS18X20_pins.push_back(new_dsx_driver); } else { - WS_DEBUG_PRINTLN("ERROR: Unable to get sensor ID, sensor not initialized"); + WS_DEBUG_PRINTLN( + "ERROR: Unable to get ds18x sensor ID, ds18x sensor not initialized"); } // Encode and publish a Ds18x20Added message back to the broker @@ -62,17 +83,21 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { void DS18X20Controller::update() { // Bail out if there are no OneWire pins to poll - if (_DS18X20_pins.size() == 0) + if (_DS18X20_pins.empty()) return; // Iterate through the vector for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { // Create a temporary DS18X20Hardware driver - DS18X20Hardware *temp_dsx_driver = &_DS18X20_pins[i]; - // Check if the driver's timer has expired - if (temp_dsx_driver->IsTimerExpired()) - return; - // TODO: the update() method should check sensor type(s) - // before polling ReadTemperatureX methods! + DS18X20Hardware &temp_dsx_driver = _DS18X20_pins[i]; + // Check if the driver's timer has not expired yet + if (!temp_dsx_driver.IsTimerExpired()) + continue; + // Are we reading the temperature in Celsius, Fahrenheit, or both? + if (temp_dsx_driver.is_read_temp_c) + temp_dsx_driver.GetTemperatureC(); + if (temp_dsx_driver.is_read_temp_f) + temp_dsx_driver.GetTemperatureF(); + // wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE } } \ No newline at end of file diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 1ce14c77e..48cdb538e 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -15,18 +15,25 @@ #include "hardware.h" DS18X20Hardware::DS18X20Hardware(uint8_t onewire_pin) : _drv_therm(_ow) { + is_read_temp_c = false; + is_read_temp_f = false; // Initialize the OneWire bus object + _onewire_pin = onewire_pin; new (&_ow) OneWireNg_CurrentPlatform(onewire_pin, false); } -DS18X20Hardware::~DS18X20Hardware() { delete &_ow; } +DS18X20Hardware::~DS18X20Hardware() { + pinMode(_onewire_pin, + INPUT); // Set the pin to hi-z and release it for other uses + delete &_ow; +} bool DS18X20Hardware::GetSensor() { OneWireNg::ErrorCode ec = _ow->readSingleId(_sensorId); return ec == OneWireNg::EC_SUCCESS; } -void DS18X20Hardware::setResolution(int resolution) { +void DS18X20Hardware::SetResolution(int resolution) { // Set the resolution of the DS18X20 sensor driver switch (resolution) { case 9: @@ -57,10 +64,13 @@ void DS18X20Hardware::setResolution(int resolution) { _drv_therm.copyScratchpadAll(false); } +void DS18X20Hardware::SetPeriod(float period) { + _period = period * 1000; // Convert to milliseconds +} + +// Get the current time in milliseconds and compare it to the last time +// the sensor was polled bool DS18X20Hardware::IsTimerExpired() { - // Get the current time in milliseconds and compare it to the last time - // the sensor was polled - ulong cur_time = millis(); return millis() - _prv_period > _period; } @@ -73,8 +83,11 @@ bool DS18X20Hardware::ReadTemperatureF() { // Did we read the temperature successfully? if (!is_success) return false; - // We have the temperature in Celsius, convert to Fahrenheit + // We now have the temperature but it's in in Celsius. Let's convert it to + // Fahrenheit _temp_f = _temp_c * 9.0 / 5.0 + 32.0; + + _prv_period = millis(); // Update the last time the sensor was polled return true; } @@ -84,13 +97,12 @@ bool DS18X20Hardware::ReadTemperatureC() { OneWireNg::ErrorCode ec = _drv_therm.convertTemp(_sensorId, DSTherm::MAX_CONV_TIME, false); if (ec != OneWireNg::EC_SUCCESS) - return false + return false; - // Scratchpad placeholder is static to allow reuse of the associated - // sensor id while reissuing readScratchpadSingle() calls. - // Note, due to its storage class the placeholder is zero initialized. - static Placeholder - scrpd; + // Scratchpad placeholder is static to allow reuse of the associated + // sensor id while reissuing readScratchpadSingle() calls. + // Note, due to its storage class the placeholder is zero initialized. + static Placeholder scrpd; ec = _drv_therm.readScratchpadSingle(scrpd); if (ec != OneWireNg::EC_SUCCESS) return false; @@ -98,5 +110,7 @@ bool DS18X20Hardware::ReadTemperatureC() { // Read the temperature from the sensor long temp = scrpd->getTemp2(); _temp_c = temp / 16.0; // Convert from 16-bit int to float + + _prv_period = millis(); // Update the last time the sensor was polled return true; } \ No newline at end of file diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 68abe8b62..5f433f492 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -30,13 +30,16 @@ class DS18X20Hardware { public: DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); - bool GetSensor(); - void setResolution(int resolution); + void SetResolution(int resolution); + void SetPeriod(float period); bool IsTimerExpired(); + bool GetSensor(); bool ReadTemperatureC(); bool ReadTemperatureF(); float GetTemperatureC(); float GetTemperatureF(); + bool is_read_temp_c; + bool is_read_temp_f; private: Placeholder _ow; ///< OneWire bus object @@ -46,12 +49,9 @@ class DS18X20Hardware { float _temp_c; ///< Temperature in Celsius float _temp_f; ///< Temperature in Fahrenheit // From the PB model - uint8_t onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing - float _period; ///< The desired period to read the sensor, in seconds - float _prv_period; ///< Last time the sensor was polled, in seconds - pb_size_t - _sensor_types_count; ///< Number of sensor types to read from the sensor - wippersnapper_sensor_SensorType - _sensor_types[2]; ///< DS sensor type(s) to read from the sensor + uint8_t + _onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing + float _period; ///< The desired period to read the sensor, in seconds + float _prv_period; ///< Last time the sensor was polled, in seconds }; #endif // WS_DS18X20_HARDWARE_H \ No newline at end of file From fa0828d2fb2d265da4d80b6a4d85781cf1e40761 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 10 Oct 2024 12:21:49 -0400 Subject: [PATCH 09/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Attempt?= =?UTF-8?q?=20towards=20encoding=20multiple=20sensor=20events=20in=20one?= =?UTF-8?q?=20update()=20=20looop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Wippersnapper_V2.h | 2 +- src/components/ds18x20/controller.cpp | 45 ++++++++-- src/components/ds18x20/controller.h | 1 + src/components/ds18x20/model.cpp | 48 +++++++++- src/components/ds18x20/model.h | 15 ++++ src/components/sensor/model.cpp | 123 +++++--------------------- src/components/sensor/model.h | 17 +--- 7 files changed, 127 insertions(+), 124 deletions(-) diff --git a/src/Wippersnapper_V2.h b/src/Wippersnapper_V2.h index 317bac0d4..2f36a245f 100644 --- a/src/Wippersnapper_V2.h +++ b/src/Wippersnapper_V2.h @@ -49,8 +49,8 @@ #endif // Components (API v2) -#include "components/checkin/model.h" #include "components/sensor/model.h" +#include "components/checkin/model.h" #include "components/digitalIO/controller.h" #include "components/analogio/controller.h" #include "components/ds18x20/controller.h" diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index ac7770135..c08a4bbf8 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -91,13 +91,46 @@ void DS18X20Controller::update() { // Create a temporary DS18X20Hardware driver DS18X20Hardware &temp_dsx_driver = _DS18X20_pins[i]; // Check if the driver's timer has not expired yet - if (!temp_dsx_driver.IsTimerExpired()) + if (!temp_dsx_driver.IsTimerExpired()) { continue; + } + // Create a new sensor_event + _DS18X20_model->InitDS18x20EventMsg(); // Are we reading the temperature in Celsius, Fahrenheit, or both? - if (temp_dsx_driver.is_read_temp_c) - temp_dsx_driver.GetTemperatureC(); - if (temp_dsx_driver.is_read_temp_f) - temp_dsx_driver.GetTemperatureF(); - // wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE + if (temp_dsx_driver.is_read_temp_c) { + WS_DEBUG_PRINTLN("Reading temperature in Celsius"); // TODO: Debug remove + float temp_c = temp_dsx_driver.GetTemperatureC(); + _DS18X20_model->addSensorEvent( + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE, + temp_c); + } + if (temp_dsx_driver.is_read_temp_f) { + WS_DEBUG_PRINTLN( + "Reading temperature in Fahrenheit"); // TODO: Debug remove + float temp_f = temp_dsx_driver.GetTemperatureF(); + _DS18X20_model->addSensorEvent( + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT, + temp_f); + } + // Print out the SensorEvent message's contents for debugging + // TODO: After debugging, maybe remove this + wippersnapper_ds18x20_Ds18x20Event event_msg = + *_DS18X20_model->GetDS18x20EventMsg(); + WS_DEBUG_PRINTLN("SensorEvent message:"); + WS_DEBUG_PRINT("Sensor OneWire bus pin: "); + WS_DEBUG_PRINTLN(event_msg.onewire_pin); + WS_DEBUG_PRINT("Sensor events count: "); + WS_DEBUG_PRINTLN(event_msg.sensor_events_count); + + for (int i = 0; + i < _DS18X20_model->GetDS18x20EventMsg()->sensor_events_count; i++) { + WS_DEBUG_PRINT("Sensor type: "); + WS_DEBUG_PRINTLN(event_msg.sensor_events[i].type); + WS_DEBUG_PRINT("Sensor value: "); + WS_DEBUG_PRINTLN(event_msg.sensor_events[i].value.float_value); + WS_DEBUG_PRINT("Sensor value type: "); + WS_DEBUG_PRINTLN(event_msg.sensor_events[i].which_value); + } } + // TODO: Encode and publish the Ds18x20Event message to the broker } \ No newline at end of file diff --git a/src/components/ds18x20/controller.h b/src/components/ds18x20/controller.h index 9309377fc..66faa497c 100644 --- a/src/components/ds18x20/controller.h +++ b/src/components/ds18x20/controller.h @@ -33,6 +33,7 @@ class DS18X20Controller { ~DS18X20Controller(); // Routing bool Handle_Ds18x20Add(pb_istream_t *stream); + // TODO: Implement Handle DS18x20 Remove message! // Polling void update(); diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index 5d0565a53..1cd0c8cd8 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -43,14 +43,54 @@ bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { strcpy(_msg_DS18x20Added.onewire_pin, onewire_pin); // Encode the Ds18x20Added message - size_t sz_aio_event_msg; - if (!pb_get_encoded_size(&sz_aio_event_msg, - wippersnapper_ds18x20_Ds18x20Added_fields, + size_t sz_msg; + if (!pb_get_encoded_size(&sz_msg, wippersnapper_ds18x20_Ds18x20Added_fields, &_msg_DS18x20Added)) return false; - uint8_t buf[sz_aio_event_msg]; + uint8_t buf[sz_msg]; pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); return pb_encode(&msg_stream, wippersnapper_ds18x20_Ds18x20Added_fields, &_msg_DS18x20Added); } + +wippersnapper_ds18x20_Ds18x20Event *DS18X20Model::GetDS18x20EventMsg() { + return &_msg_DS18x20Event; +} + +bool DS18X20Model::EncodeDs18x20Event( + char *onewire_pin, pb_size_t sensor_events_count, + const wippersnapper_sensor_SensorEvent sensor_events[2]) { + // Fill the Ds18x20Event message + _msg_DS18x20Event = wippersnapper_ds18x20_Ds18x20Event_init_zero; + strcpy(_msg_DS18x20Event.onewire_pin, onewire_pin); + _msg_DS18x20Event.sensor_events_count = sensor_events_count; + // Fill with sensor_events + for (int i = 0; i < _msg_DS18x20Event.sensor_events_count; i++) { + _msg_DS18x20Event.sensor_events[i] = sensor_events[i]; + } + // Encode and return the Ds18x20Event message + size_t sz_msg; + if (!pb_get_encoded_size(&sz_msg, wippersnapper_ds18x20_Ds18x20Event_fields, + &_msg_DS18x20Event)) + return false; + uint8_t buf[sz_msg]; + pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); + return pb_encode(&msg_stream, wippersnapper_ds18x20_Ds18x20Event_fields, + &_msg_DS18x20Event); +} + +void DS18X20Model::InitDS18x20EventMsg() { + _msg_DS18x20Event = wippersnapper_ds18x20_Ds18x20Event_init_zero; + _msg_DS18x20Event.sensor_events_count = 0; +} + +void DS18X20Model::addSensorEvent(wippersnapper_sensor_SensorType sensor_type, + float sensor_value) { + _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count].type = + sensor_type; + _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count] + .which_value = wippersnapper_sensor_SensorEvent_float_value_tag; + _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count] + .value.float_value = sensor_value; +} \ No newline at end of file diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index dad1be0f6..85a05e3d6 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -32,11 +32,26 @@ class DS18X20Model { // Ds18x20Remove Message bool EncodeDS18x20Added(char *onewire_pin, bool is_init); wippersnapper_ds18x20_Ds18x20Added *GetDS18x20AddedMsg(); + // Ds18x20Event Message + bool + EncodeDs18x20Event(char *onewire_pin, pb_size_t sensor_events_count, + const wippersnapper_sensor_SensorEvent sensor_events[2]); + wippersnapper_ds18x20_Ds18x20Event *GetDS18x20EventMsg(); + // TODO: move the below to private if we arent using it in controller? + wippersnapper_ds18x20_Ds18x20Event + _msg_DS18x20Event; ///< wippersnapper_ds18x20_Ds18x20Event message + void InitDS18x20EventMsg(); + void addSensorEvent(wippersnapper_sensor_SensorType sensor_type, + float sensor_value); private: wippersnapper_ds18x20_Ds18x20Add _msg_DS18x20Add; ///< wippersnapper_ds18x20_Ds18x20Add message wippersnapper_ds18x20_Ds18x20Added _msg_DS18x20Added; ///< wippersnapper_ds18x20_Ds18x20Added message + wippersnapper_ds18x20_Ds18x20Event + _msg_DS18x20Event; ///< wippersnapper_ds18x20_Ds18x20Event message + wippersnapper_ds18x20_Ds18x20Remove + _msg_DS18x20Remove; ///< wippersnapper_ds18x20_Ds18x20Remove message }; #endif // WS_DIGITALIO_MODEL_H \ No newline at end of file diff --git a/src/components/sensor/model.cpp b/src/components/sensor/model.cpp index fd2343172..a02e4ac8d 100644 --- a/src/components/sensor/model.cpp +++ b/src/components/sensor/model.cpp @@ -20,7 +20,7 @@ */ /***********************************************************************/ SensorModel::SensorModel() { - _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_default; + _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_zero; } /***********************************************************************/ @@ -28,111 +28,34 @@ SensorModel::SensorModel() { @brief SensorModel destructor */ /***********************************************************************/ -SensorModel::~SensorModel() {} - -/***********************************************************************/ -/*! - @brief Decodes a SensorEvent message into a SensorModel object. - @param stream - The input stream - @returns True if the SensorEvent message was successfully decoded, - False otherwise. -*/ -/***********************************************************************/ -bool SensorModel::decodeSensorEvent(pb_istream_t *stream) { - // Decode the stream into theSensorEvent message - if (!pb_decode(stream, wippersnapper_sensor_SensorEvent_fields, - &_msg_sensor_event)) { - return false; - } - return true; -} - -/***********************************************************************/ -/*! - @brief Clears the SensorEvent message. -*/ -/***********************************************************************/ -void SensorModel::clearSensorEvent() { - _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_default; -} - -/***********************************************************************/ -/*! - @brief Returns a SensorEvent message. - @returns The SensorEvent message. -*/ -/***********************************************************************/ -wippersnapper_sensor_SensorEvent *SensorModel::getSensorEvent() { - return &_msg_sensor_event; -} - -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's type. - @returns The type of the SensorEvent message, as a SensorType. -*/ -/***********************************************************************/ -wippersnapper_sensor_SensorType SensorModel::getSensorType() { - return _msg_sensor_event.type; -} - -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's which_value field. - @returns The which_value field of the SensorEvent message. -*/ -/***********************************************************************/ -pb_size_t SensorModel::getSensorEventWhichValue() { - return _msg_sensor_event.which_value; +SensorModel::~SensorModel() { + // Zero-out the SensorEvent message + _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_zero; } -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's float value field. - @returns The float value of the SensorEvent message. -*/ -/***********************************************************************/ -float SensorModel::getValueFloat() { - return _msg_sensor_event.value.float_value; +wippersnapper_sensor_SensorEvent *SensorModel::GetSensorEventMessage() { + return &_msg_sensor_event; } -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's bool value field. - @returns The bool value of the SensorEvent message. -*/ -/***********************************************************************/ -bool SensorModel::getValueBool() { return _msg_sensor_event.value.bool_value; } +bool SensorModel::EncodeSensorEventMessage() { + // Obtain size of the class' SensorEvent message + size_t sz_msg; + if (!pb_get_encoded_size(&sz_msg, wippersnapper_sensor_SensorEvent_fields, &_msg_sensor_event)) + return false; -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's vector value field. - @returns The vector value of the SensorEvent message. -*/ -/***********************************************************************/ -wippersnapper_sensor_SensorEvent_SensorEvent3DVector -SensorModel::getValueVector() { - return _msg_sensor_event.value.vector_value; + // Encode the class' SensorEvent message + uint8_t buf[sz_msg]; + pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); + return pb_encode(&msg_stream, wippersnapper_sensor_SensorEvent_fields, + &_msg_sensor_event); } -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's orientation value field. - @returns The orientation value of the SensorEvent message. -*/ -/***********************************************************************/ -wippersnapper_sensor_SensorEvent_SensorEventOrientation -SensorModel::getValueOrientation() { - return _msg_sensor_event.value.orientation_value; -} -/***********************************************************************/ -/*! - @brief Returns the the SensorEvent message's color value field. - @returns The color value of the SensorEvent message. -*/ -/***********************************************************************/ -wippersnapper_sensor_SensorEvent_SensorEventColor SensorModel::getValueColor() { - return _msg_sensor_event.value.color_value; +void SensorModel::CreateSensorEventFloat(wippersnapper_sensor_SensorType sensor_type, float sensor_value) { + // Zero-out the previous SensorEvent message + _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_zero; + // Fill in the SensorEvent message + _msg_sensor_event.type = sensor_type; + _msg_sensor_event.which_value = wippersnapper_sensor_SensorEvent_float_value_tag; + _msg_sensor_event.value.float_value = sensor_value; } \ No newline at end of file diff --git a/src/components/sensor/model.h b/src/components/sensor/model.h index c6cf1adae..199a9e25c 100644 --- a/src/components/sensor/model.h +++ b/src/components/sensor/model.h @@ -27,19 +27,10 @@ class SensorModel { public: SensorModel(); ~SensorModel(); - bool decodeSensorEvent(pb_istream_t *stream); - void clearSensorEvent(); - - wippersnapper_sensor_SensorEvent *getSensorEvent(); - wippersnapper_sensor_SensorType getSensorType(); - pb_size_t getSensorEventWhichValue(); - - float getValueFloat(); - bool getValueBool(); - wippersnapper_sensor_SensorEvent_SensorEvent3DVector getValueVector(); - wippersnapper_sensor_SensorEvent_SensorEventOrientation getValueOrientation(); - wippersnapper_sensor_SensorEvent_SensorEventColor getValueColor(); - + bool EncodeSensorEventMessage(); + wippersnapper_sensor_SensorEvent *GetSensorEventMessage(); + // These functions create a SensorEvent message + void CreateSensorEventFloat(wippersnapper_sensor_SensorType sensor_type, float sensor_value); private: wippersnapper_sensor_SensorEvent _msg_sensor_event; ///< SensorEvent message }; From c66c97e2210f0bde848dc5cb53c479b33d1a4d2c Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 10 Oct 2024 13:05:03 -0400 Subject: [PATCH 10/21] =?UTF-8?q?=F0=9F=9A=A7=20Remove=20the=20onewire=20b?= =?UTF-8?q?us=20from=20the=20pin=20and=20vec=20erase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 23 +++++++++++++++++++++++ src/components/ds18x20/controller.h | 2 +- src/components/ds18x20/hardware.cpp | 2 ++ src/components/ds18x20/hardware.h | 1 + src/components/ds18x20/model.cpp | 10 ++++++++++ src/components/ds18x20/model.h | 7 ++++--- 6 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index c08a4bbf8..6181afedb 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -81,6 +81,29 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { return true; } +bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { + // Attempt to decode the stream + if (!_DS18X20_model->DecodeDS18x20Remove(stream)) { + WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Remove message"); + return false; + } + // Create a temp. instance of the Ds18x20Remove message + wippersnapper_ds18x20_Ds18x20Remove *msg_remove = + _DS18X20_model->GetDS18x20RemoveMsg(); + uint8_t pin_name = atoi(msg_remove->onewire_pin + 1); + // Destroy the DS18X20Hardware object, remove it from the vector, and release + // it for other uses + for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { + if (_DS18X20_pins[i].GetOneWirePin() == pin_name) { + _DS18X20_pins.erase(_DS18X20_pins.begin() + i); + break; + } + } + WS_DEBUG_PRINT("Removed OneWire Pin: "); + WS_DEBUG_PRINTLN(pin_name); + return true; +} + void DS18X20Controller::update() { // Bail out if there are no OneWire pins to poll if (_DS18X20_pins.empty()) diff --git a/src/components/ds18x20/controller.h b/src/components/ds18x20/controller.h index 66faa497c..2614674ed 100644 --- a/src/components/ds18x20/controller.h +++ b/src/components/ds18x20/controller.h @@ -33,7 +33,7 @@ class DS18X20Controller { ~DS18X20Controller(); // Routing bool Handle_Ds18x20Add(pb_istream_t *stream); - // TODO: Implement Handle DS18x20 Remove message! + bool Handle_Ds18x20Remove(pb_istream_t *stream); // Polling void update(); diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 48cdb538e..43e24c8ca 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -33,6 +33,8 @@ bool DS18X20Hardware::GetSensor() { return ec == OneWireNg::EC_SUCCESS; } +uint8_t DS18X20Hardware::GetOneWirePin() { return _onewire_pin; } + void DS18X20Hardware::SetResolution(int resolution) { // Set the resolution of the DS18X20 sensor driver switch (resolution) { diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 5f433f492..34f69b056 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -34,6 +34,7 @@ class DS18X20Hardware { void SetPeriod(float period); bool IsTimerExpired(); bool GetSensor(); + uint8_t GetOneWirePin(); bool ReadTemperatureC(); bool ReadTemperatureF(); float GetTemperatureC(); diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index 1cd0c8cd8..05f86387a 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -54,6 +54,16 @@ bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { &_msg_DS18x20Added); } +bool DS18X20Model::DecodeDS18x20Remove(pb_istream_t *stream) { + _msg_DS18x20Remove = wippersnapper_ds18x20_Ds18x20Remove_init_zero; + return pb_decode(stream, wippersnapper_ds18x20_Ds18x20Remove_fields, + &_msg_DS18x20Remove); +} + +wippersnapper_ds18x20_Ds18x20Remove *DS18X20Model::GetDS18x20RemoveMsg() { + return &_msg_DS18x20Remove; +} + wippersnapper_ds18x20_Ds18x20Event *DS18X20Model::GetDS18x20EventMsg() { return &_msg_DS18x20Event; } diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index 85a05e3d6..4362c7771 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -29,9 +29,12 @@ class DS18X20Model { // Ds18x20Add Message bool DecodeDS18x20Add(pb_istream_t *stream); wippersnapper_ds18x20_Ds18x20Add *GetDS18x20AddMsg(); - // Ds18x20Remove Message + // DS18x20Added Message bool EncodeDS18x20Added(char *onewire_pin, bool is_init); wippersnapper_ds18x20_Ds18x20Added *GetDS18x20AddedMsg(); + // Ds18x20Remove Message + bool DecodeDS18x20Remove(pb_istream_t *stream); + wippersnapper_ds18x20_Ds18x20Remove *GetDS18x20RemoveMsg(); // Ds18x20Event Message bool EncodeDs18x20Event(char *onewire_pin, pb_size_t sensor_events_count, @@ -49,8 +52,6 @@ class DS18X20Model { _msg_DS18x20Add; ///< wippersnapper_ds18x20_Ds18x20Add message wippersnapper_ds18x20_Ds18x20Added _msg_DS18x20Added; ///< wippersnapper_ds18x20_Ds18x20Added message - wippersnapper_ds18x20_Ds18x20Event - _msg_DS18x20Event; ///< wippersnapper_ds18x20_Ds18x20Event message wippersnapper_ds18x20_Ds18x20Remove _msg_DS18x20Remove; ///< wippersnapper_ds18x20_Ds18x20Remove message }; From 60238ca8c66dfdc2e20d2dbc942dd5ef208d3827 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 10 Oct 2024 15:17:51 -0400 Subject: [PATCH 11/21] =?UTF-8?q?=F0=9F=8E=A8=20WIP,=20dsx=20-=20Doxygen?= =?UTF-8?q?=20and=20remove=20unused=20code=20implemented=20in=20the=20sens?= =?UTF-8?q?or=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/digitalIO/model.cpp | 2 + src/components/ds18x20/controller.cpp | 40 ++++++++++++ src/components/ds18x20/hardware.cpp | 74 +++++++++++++++++++++- src/components/ds18x20/hardware.h | 11 ++-- src/components/ds18x20/model.cpp | 90 +++++++++++++++++++++++++++ src/components/sensor/model.cpp | 27 -------- src/components/sensor/model.h | 4 -- 7 files changed, 210 insertions(+), 38 deletions(-) diff --git a/src/components/digitalIO/model.cpp b/src/components/digitalIO/model.cpp index 49ce105d7..6643b1c49 100644 --- a/src/components/digitalIO/model.cpp +++ b/src/components/digitalIO/model.cpp @@ -46,6 +46,8 @@ wippersnapper_digitalio_DigitalIOAdd *DigitalIOModel::GetDigitalIOAddMsg() { /***********************************************************************/ /*! @brief Parses a DigitalIORemove message. + @param stream + The nanopb input stream. @return DigitalIORemove message object. */ /***********************************************************************/ diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 6181afedb..3bddcb639 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -14,10 +14,34 @@ */ #include "controller.h" +/***********************************************************************/ +/*! + @brief DS18X20Controller constructor +*/ +/***********************************************************************/ DS18X20Controller::DS18X20Controller() { _DS18X20_model = new DS18X20Model(); } +/***********************************************************************/ +/*! + @brief DS18X20Controller destructor +*/ +/***********************************************************************/ DS18X20Controller::~DS18X20Controller() { delete _DS18X20_model; } +/***********************************************************************/ +/*! + @brief Handles a Ds18x20Add message from the broker. Attempts to + initialize a OneWire bus on the requested pin, attempts to + initialize a DSTherm driver on the OneWire bus, adds the + OneWire bus to the controller, and publishes a Ds18x20Added + message to the broker indicating the result of this function. + @param stream + The nanopb input stream. + @return True if the sensor was successfully initialized, + added to the controller, and a response was succesfully + published to the broker. False otherwise. +*/ +/***********************************************************************/ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { // Attempt to decode the incoming message into a Ds18x20Add message if (!_DS18X20_model->DecodeDS18x20Add(stream)) { @@ -81,6 +105,17 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { return true; } +/***********************************************************************/ +/*! + @brief Handles a Ds18x20Remove message from the broker. Attempts to + remove a DS18X20Hardware object from the controller and + release the OneWire pin for other uses. + @param stream + The nanopb input stream. + @return True if the sensor was successfully removed from the + controller, False otherwise. +*/ +/***********************************************************************/ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { // Attempt to decode the stream if (!_DS18X20_model->DecodeDS18x20Remove(stream)) { @@ -104,6 +139,11 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { return true; } +/***********************************************************************/ +/*! + @brief Update/polling loop for the DS18X20 controller. +*/ +/***********************************************************************/ void DS18X20Controller::update() { // Bail out if there are no OneWire pins to poll if (_DS18X20_pins.empty()) diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 43e24c8ca..91554bf9f 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -14,6 +14,13 @@ */ #include "hardware.h" +/***********************************************************************/ +/*! + @brief DS18X20Hardware constructor + @param onewire_pin + The OneWire bus pin to use. +*/ +/***********************************************************************/ DS18X20Hardware::DS18X20Hardware(uint8_t onewire_pin) : _drv_therm(_ow) { is_read_temp_c = false; is_read_temp_f = false; @@ -22,19 +29,44 @@ DS18X20Hardware::DS18X20Hardware(uint8_t onewire_pin) : _drv_therm(_ow) { new (&_ow) OneWireNg_CurrentPlatform(onewire_pin, false); } +/***********************************************************************/ +/*! + @brief DS18X20Hardware destructor +*/ +/***********************************************************************/ DS18X20Hardware::~DS18X20Hardware() { pinMode(_onewire_pin, INPUT); // Set the pin to hi-z and release it for other uses delete &_ow; } +/***********************************************************************/ +/*! + @brief Get the sensor's ID + @returns True if the sensor was successfully identified, False otherwise. +*/ +/***********************************************************************/ bool DS18X20Hardware::GetSensor() { OneWireNg::ErrorCode ec = _ow->readSingleId(_sensorId); return ec == OneWireNg::EC_SUCCESS; } +/***********************************************************************/ +/*! + @brief Gets the pin used as a OneWire bus. + @returns The OneWire bus pin. +*/ +/***********************************************************************/ uint8_t DS18X20Hardware::GetOneWirePin() { return _onewire_pin; } +/*************************************************************************/ +/*! + @brief Sets the DS18X20 sensor's resolution. + @param resolution + The desired resolution of the DS18X20 sensor, in bits (from + 9 to 12). +*/ +/*************************************************************************/ void DS18X20Hardware::SetResolution(int resolution) { // Set the resolution of the DS18X20 sensor driver switch (resolution) { @@ -66,20 +98,51 @@ void DS18X20Hardware::SetResolution(int resolution) { _drv_therm.copyScratchpadAll(false); } +/*************************************************************************/ +/*! + @brief Sets the timer to read from the sensor. + @param period + The desired period to read the sensor, in seconds. +*/ +/*************************************************************************/ void DS18X20Hardware::SetPeriod(float period) { _period = period * 1000; // Convert to milliseconds } -// Get the current time in milliseconds and compare it to the last time -// the sensor was polled +/*************************************************************************/ +/*! + @brief Obtains the current time in milliseconds and compares it to + the last time the sensor was polled. + @returns True if the timer has expired, False otherwise. +*/ +/*************************************************************************/ bool DS18X20Hardware::IsTimerExpired() { return millis() - _prv_period > _period; } +/*************************************************************************/ +/*! + @brief Gets the temperature value last read by the sensor, in Celsius. + @returns The temperature in Celsius. +*/ +/*************************************************************************/ float DS18X20Hardware::GetTemperatureC() { return _temp_c; } +/*************************************************************************/ +/*! + @brief Gets the temperature value last read by the sensor, in Fahrenheit. + @returns The temperature in Fahrenheit. +*/ +/*************************************************************************/ float DS18X20Hardware::GetTemperatureF() { return _temp_f; } +/*************************************************************************/ +/*! + @brief Attempts to obtain the temperature from the sensor, in + degrees Fahrenheit. + @returns True if the temperature was successfully read, False otherwise. +*/ +/*************************************************************************/ bool DS18X20Hardware::ReadTemperatureF() { bool is_success = ReadTemperatureC(); // Did we read the temperature successfully? @@ -93,6 +156,13 @@ bool DS18X20Hardware::ReadTemperatureF() { return true; } +/*************************************************************************/ +/*! + @brief Attempts to obtain the temperature from the sensor, in + degrees Celsius. + @returns True if the temperature was successfully read, False otherwise. +*/ +/*************************************************************************/ bool DS18X20Hardware::ReadTemperatureC() { // Start temperature conversion for the first identified sensor on the OneWire // bus diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 34f69b056..4539e007b 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -39,13 +39,14 @@ class DS18X20Hardware { bool ReadTemperatureF(); float GetTemperatureC(); float GetTemperatureF(); - bool is_read_temp_c; - bool is_read_temp_f; - + bool is_read_temp_c; ///< Flag telling the controller to read the temperature + ///< in degrees Celsius + bool is_read_temp_f; ///< Flag telling the controller to read the temperature + ///< in degrees Fahrenheit private: Placeholder _ow; ///< OneWire bus object - OneWireNg::Id _sensorId; - DSTherm _drv_therm; ///< DS18X20 driver object + OneWireNg::Id _sensorId; ///< Sensor ID + DSTherm _drv_therm; ///< DS18X20 driver object DSTherm::Resolution _resolution; ///< Resolution of the DS18X20 sensor float _temp_c; ///< Temperature in Celsius float _temp_f; ///< Temperature in Fahrenheit diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index 05f86387a..c6d5e6f7c 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -14,13 +14,33 @@ */ #include "model.h" +/***********************************************************************/ +/*! + @brief DS18X20Model constructor +*/ +/***********************************************************************/ DS18X20Model::DS18X20Model() { // Initialize the DS18X20 messages _msg_DS18x20Add = wippersnapper_ds18x20_Ds18x20Add_init_zero; + _msg_DS18x20Added = wippersnapper_ds18x20_Ds18x20Added_init_zero; + _msg_DS18x20Remove = wippersnapper_ds18x20_Ds18x20Remove_init_zero; } +/***********************************************************************/ +/*! + @brief DS18X20Model destructor +*/ +/***********************************************************************/ DS18X20Model::~DS18X20Model() {} +/***********************************************************************/ +/*! + @brief Attempts to decode a Ds18x20Add message from the broker. + @param stream + The nanopb input stream. + @return True if the message was successfully decoded, False otherwise. +*/ +/***********************************************************************/ bool DS18X20Model::DecodeDS18x20Add(pb_istream_t *stream) { _msg_DS18x20Add = wippersnapper_ds18x20_Ds18x20Add_init_zero; // Attempt to decode the stream into a Ds18x20Add message @@ -28,14 +48,38 @@ bool DS18X20Model::DecodeDS18x20Add(pb_istream_t *stream) { &_msg_DS18x20Add); } +/***********************************************************************/ +/*! + @brief Gets a pointer to the Ds18x20Add message. + @return Pointer to the Ds18x20Add message. +*/ +/***********************************************************************/ wippersnapper_ds18x20_Ds18x20Add *DS18X20Model::GetDS18x20AddMsg() { return &_msg_DS18x20Add; } +/***********************************************************************/ +/*! + @brief Returns a pointer to the Ds18x20Added message. + @return Pointer to the Ds18x20Added message. +*/ +/***********************************************************************/ wippersnapper_ds18x20_Ds18x20Added *DS18X20Model::GetDS18x20AddedMsg() { return &_msg_DS18x20Added; } +/***********************************************************************/ +/*! + @brief Encodes a Ds18x20Added message. + @param onewire_pin + The OneWire bus pin to add. + @param is_init + True if the sensor was successfully initialized, + False otherwise. + @return True if the message was successfully encoded, + False otherwise. +*/ +/***********************************************************************/ bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { // Fill the Ds18x20Added message _msg_DS18x20Added = wippersnapper_ds18x20_Ds18x20Added_init_zero; @@ -54,20 +98,52 @@ bool DS18X20Model::EncodeDS18x20Added(char *onewire_pin, bool is_init) { &_msg_DS18x20Added); } +/*************************************************************************/ +/*! + @brief Attempts to decode a Ds18x20Remove message from the broker. + @param stream + The nanopb input stream. + @return True if the message was successfully decoded, False otherwise. +*/ +/*************************************************************************/ bool DS18X20Model::DecodeDS18x20Remove(pb_istream_t *stream) { _msg_DS18x20Remove = wippersnapper_ds18x20_Ds18x20Remove_init_zero; return pb_decode(stream, wippersnapper_ds18x20_Ds18x20Remove_fields, &_msg_DS18x20Remove); } +/*************************************************************************/ +/*! + @brief Gets a pointer to the Ds18x20Remove message. + @return Pointer to the Ds18x20Remove message. +*/ +/*************************************************************************/ wippersnapper_ds18x20_Ds18x20Remove *DS18X20Model::GetDS18x20RemoveMsg() { return &_msg_DS18x20Remove; } +/*************************************************************************/ +/*! + @brief Gets a pointer to the Ds18x20Event message. + @return Pointer to the Ds18x20Event message. +*/ +/*************************************************************************/ wippersnapper_ds18x20_Ds18x20Event *DS18X20Model::GetDS18x20EventMsg() { return &_msg_DS18x20Event; } +/*************************************************************************/ +/*! + @brief Encodes a Ds18x20Event message. + @param onewire_pin + The OneWire bus' pin where the sensor is located. + @param sensor_events_count + The number of sensorevent messages to encode. + @param sensor_events + The sensorevent messages to encode. + @return True if the message was successfully encoded, False otherwise. +*/ +/*************************************************************************/ bool DS18X20Model::EncodeDs18x20Event( char *onewire_pin, pb_size_t sensor_events_count, const wippersnapper_sensor_SensorEvent sensor_events[2]) { @@ -90,11 +166,25 @@ bool DS18X20Model::EncodeDs18x20Event( &_msg_DS18x20Event); } +/*************************************************************************/ +/*! + @brief Initializes the Ds18x20Event message. +*/ +/*************************************************************************/ void DS18X20Model::InitDS18x20EventMsg() { _msg_DS18x20Event = wippersnapper_ds18x20_Ds18x20Event_init_zero; _msg_DS18x20Event.sensor_events_count = 0; } +/*************************************************************************/ +/*! + @brief Adds a "sensor event" to the Ds18x20Event message. + @param sensor_type + The event's SensorType. + @param sensor_value + The event's value. +*/ +/*************************************************************************/ void DS18X20Model::addSensorEvent(wippersnapper_sensor_SensorType sensor_type, float sensor_value) { _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count].type = diff --git a/src/components/sensor/model.cpp b/src/components/sensor/model.cpp index a02e4ac8d..85f1cb3d3 100644 --- a/src/components/sensor/model.cpp +++ b/src/components/sensor/model.cpp @@ -31,31 +31,4 @@ SensorModel::SensorModel() { SensorModel::~SensorModel() { // Zero-out the SensorEvent message _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_zero; -} - -wippersnapper_sensor_SensorEvent *SensorModel::GetSensorEventMessage() { - return &_msg_sensor_event; -} - -bool SensorModel::EncodeSensorEventMessage() { - // Obtain size of the class' SensorEvent message - size_t sz_msg; - if (!pb_get_encoded_size(&sz_msg, wippersnapper_sensor_SensorEvent_fields, &_msg_sensor_event)) - return false; - - // Encode the class' SensorEvent message - uint8_t buf[sz_msg]; - pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); - return pb_encode(&msg_stream, wippersnapper_sensor_SensorEvent_fields, - &_msg_sensor_event); -} - - -void SensorModel::CreateSensorEventFloat(wippersnapper_sensor_SensorType sensor_type, float sensor_value) { - // Zero-out the previous SensorEvent message - _msg_sensor_event = wippersnapper_sensor_SensorEvent_init_zero; - // Fill in the SensorEvent message - _msg_sensor_event.type = sensor_type; - _msg_sensor_event.which_value = wippersnapper_sensor_SensorEvent_float_value_tag; - _msg_sensor_event.value.float_value = sensor_value; } \ No newline at end of file diff --git a/src/components/sensor/model.h b/src/components/sensor/model.h index 199a9e25c..6be8584f8 100644 --- a/src/components/sensor/model.h +++ b/src/components/sensor/model.h @@ -27,10 +27,6 @@ class SensorModel { public: SensorModel(); ~SensorModel(); - bool EncodeSensorEventMessage(); - wippersnapper_sensor_SensorEvent *GetSensorEventMessage(); - // These functions create a SensorEvent message - void CreateSensorEventFloat(wippersnapper_sensor_SensorType sensor_type, float sensor_value); private: wippersnapper_sensor_SensorEvent _msg_sensor_event; ///< SensorEvent message }; From 36226ccb7cadb56ec93bb62e43540a38f41064d0 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 15 Oct 2024 11:28:24 -0400 Subject: [PATCH 12/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Read=20te?= =?UTF-8?q?mperature=20and=20properly=20reset=20all=20counters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio.ini | 3 +- src/Wippersnapper_V2.cpp | 10 ++++++ src/components/ds18x20/controller.cpp | 47 +++++++++++++++++---------- src/components/ds18x20/controller.h | 4 +-- src/components/ds18x20/hardware.cpp | 29 ++++++++++++++++- src/components/ds18x20/hardware.h | 1 + src/components/ds18x20/model.cpp | 1 + 7 files changed, 73 insertions(+), 22 deletions(-) diff --git a/platformio.ini b/platformio.ini index 7377a2f5f..d719875f1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -179,7 +179,8 @@ extends = common:esp32 board = adafruit_feather_esp32s3 build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S3 -DBOARD_HAS_PSRAM ;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1 -board_build.partitions = tinyuf2-partitions-4MB.csv +; board_build.partitions = tinyuf2-partitions-4MB.csv +board_build.partitions = tinyuf2-partitions-4MB-noota.csv extra_scripts = pre:rename_usb_config.py ; Adafruit Feather ESP32-S3 NO PSRAM diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 17ab247ca..1f51326df 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -372,6 +372,13 @@ bool cbDecodeBrokerToDevice(pb_istream_t *stream, const pb_field_t *field, return false; } break; + case wippersnapper_signal_BrokerToDevice_ds18x20_add_tag: + WS_DEBUG_PRINTLN("-> DS18X20 Add Message Type"); + if (!WsV2._ds18x20_controller->Handle_Ds18x20Add(stream)) { + WS_DEBUG_PRINTLN("ERROR: Unable to add DS18X20 sensor!"); + return false; + } + break; default: WS_DEBUG_PRINTLN("ERROR: BrokerToDevice message type not found!"); return false; @@ -1171,6 +1178,9 @@ ws_status_t Wippersnapper_V2::runV2() { // Process all analog inputs WsV2.analogio_controller->update(); + // Process all DS18x20 sensor events + WsV2._ds18x20_controller->update(); + // TODO: Process I2C sensor events // TODO: Process DS18x20 sensor events diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 3bddcb639..664c48ea5 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -59,30 +59,31 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { uint8_t pin_name = atoi(_DS18X20_model->GetDS18x20AddMsg()->onewire_pin + 1); // Initialize the DS18X20Hardware object - DS18X20Hardware new_dsx_driver(pin_name); + auto new_dsx_driver = std::make_unique(pin_name); // Attempt to get the sensor's ID on the OneWire bus to show it's been init'd - bool is_initialized = new_dsx_driver.GetSensor(); - if (!is_initialized) { + bool is_initialized = new_dsx_driver->GetSensor(); + if (is_initialized) { WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); // Set the sensor's resolution - new_dsx_driver.SetResolution( + new_dsx_driver->SetResolution( _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); // Set the sensor's period - new_dsx_driver.SetPeriod(_DS18X20_model->GetDS18x20AddMsg()->period); + new_dsx_driver->SetPeriod(_DS18X20_model->GetDS18x20AddMsg()->period); // Configure the types of sensor reads to perform for (int i = 0; i < _DS18X20_model->GetDS18x20AddMsg()->sensor_types_count; i++) { if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == - wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE) { - new_dsx_driver.is_read_temp_c = true; + wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE) { + new_dsx_driver->is_read_temp_c = true; } else if ( _DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == - wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT) { - new_dsx_driver.is_read_temp_f = true; + wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT) { + new_dsx_driver->is_read_temp_f = true; } } // Add the DS18X20Hardware object to the vector of hardware objects - _DS18X20_pins.push_back(new_dsx_driver); + //_DS18X20_pins.push_back(new_dsx_driver); + _DS18X20_pins.push_back(std::move(new_dsx_driver)); } else { WS_DEBUG_PRINTLN( "ERROR: Unable to get ds18x sensor ID, ds18x sensor not initialized"); @@ -126,12 +127,12 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { wippersnapper_ds18x20_Ds18x20Remove *msg_remove = _DS18X20_model->GetDS18x20RemoveMsg(); uint8_t pin_name = atoi(msg_remove->onewire_pin + 1); - // Destroy the DS18X20Hardware object, remove it from the vector, and release - // it for other uses - for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { - if (_DS18X20_pins[i].GetOneWirePin() == pin_name) { + + // Find the driver/bus in the vector and remove it + for (size_t i = 0; i < _DS18X20_pins.size(); ++i) { + if (_DS18X20_pins[i]->GetOneWirePin() == pin_name) { _DS18X20_pins.erase(_DS18X20_pins.begin() + i); - break; + return true; } } WS_DEBUG_PRINT("Removed OneWire Pin: "); @@ -152,7 +153,7 @@ void DS18X20Controller::update() { // Iterate through the vector for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { // Create a temporary DS18X20Hardware driver - DS18X20Hardware &temp_dsx_driver = _DS18X20_pins[i]; + DS18X20Hardware &temp_dsx_driver = *(_DS18X20_pins[i]); // Check if the driver's timer has not expired yet if (!temp_dsx_driver.IsTimerExpired()) { continue; @@ -162,17 +163,27 @@ void DS18X20Controller::update() { // Are we reading the temperature in Celsius, Fahrenheit, or both? if (temp_dsx_driver.is_read_temp_c) { WS_DEBUG_PRINTLN("Reading temperature in Celsius"); // TODO: Debug remove + // Attempt to read the temperature in Celsius + if (!temp_dsx_driver.ReadTemperatureC()) { + WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Celsius"); + continue; + } float temp_c = temp_dsx_driver.GetTemperatureC(); _DS18X20_model->addSensorEvent( - wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE, + wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE, temp_c); } if (temp_dsx_driver.is_read_temp_f) { WS_DEBUG_PRINTLN( "Reading temperature in Fahrenheit"); // TODO: Debug remove + // Attempt to read the temperature in Fahrenheit + if (!temp_dsx_driver.ReadTemperatureF()) { + WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Fahrenheit"); + continue; + } float temp_f = temp_dsx_driver.GetTemperatureF(); _DS18X20_model->addSensorEvent( - wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT, + wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT, temp_f); } // Print out the SensorEvent message's contents for debugging diff --git a/src/components/ds18x20/controller.h b/src/components/ds18x20/controller.h index 2614674ed..a77182f47 100644 --- a/src/components/ds18x20/controller.h +++ b/src/components/ds18x20/controller.h @@ -17,6 +17,7 @@ #include "Wippersnapper_V2.h" #include "hardware.h" #include "model.h" +#include class Wippersnapper_V2; ///< Forward declaration class DS18X20Model; ///< Forward declaration @@ -39,8 +40,7 @@ class DS18X20Controller { private: DS18X20Model *_DS18X20_model; ///< ds18x20 model - std::vector - _DS18X20_pins; ///< Vector containing multiple DS18X20Hardware objects + std::vector> _DS18X20_pins; }; extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance #endif // WS_DS18X20_CONTROLLER_H \ No newline at end of file diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 91554bf9f..0ec0730a9 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -37,7 +37,32 @@ DS18X20Hardware::DS18X20Hardware(uint8_t onewire_pin) : _drv_therm(_ow) { DS18X20Hardware::~DS18X20Hardware() { pinMode(_onewire_pin, INPUT); // Set the pin to hi-z and release it for other uses - delete &_ow; +} + +void DS18X20Hardware::printErrorCode(OneWireNg::ErrorCode ec) { + switch (ec) { + case OneWireNg::EC_SUCCESS: + WS_DEBUG_PRINTLN("EC_SUCCESS"); + break; + case OneWireNg::EC_NO_DEVS: + WS_DEBUG_PRINTLN("EC_NO_DEVSNo slave devices; search process finished"); + break; + case OneWireNg::EC_BUS_ERROR: + WS_DEBUG_PRINTLN("EC_BUS_ERROR-wire bus error"); + break; + case OneWireNg::EC_CRC_ERROR: + WS_DEBUG_PRINTLN("EC_CRC_ERRORCRC error"); + break; + case OneWireNg::EC_UNSUPPORED: + WS_DEBUG_PRINTLN("EC_UNSUPPOREDService is not supported by the platform"); + break; + case OneWireNg::EC_FULL: + WS_DEBUG_PRINTLN("EC_FULLNo space (e.g. filters table is full)"); + break; + default: + WS_DEBUG_PRINTLN("EC ?!?1 Unknown error"); + break; + } } /***********************************************************************/ @@ -48,6 +73,7 @@ DS18X20Hardware::~DS18X20Hardware() { /***********************************************************************/ bool DS18X20Hardware::GetSensor() { OneWireNg::ErrorCode ec = _ow->readSingleId(_sensorId); + printErrorCode(ec); return ec == OneWireNg::EC_SUCCESS; } @@ -107,6 +133,7 @@ void DS18X20Hardware::SetResolution(int resolution) { /*************************************************************************/ void DS18X20Hardware::SetPeriod(float period) { _period = period * 1000; // Convert to milliseconds + _prv_period = 0; // Also reset the previous period here } /*************************************************************************/ diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 4539e007b..b709e2158 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -30,6 +30,7 @@ class DS18X20Hardware { public: DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); + void printErrorCode(OneWireNg::ErrorCode ec); void SetResolution(int resolution); void SetPeriod(float period); bool IsTimerExpired(); diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index c6d5e6f7c..361125b9d 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -193,4 +193,5 @@ void DS18X20Model::addSensorEvent(wippersnapper_sensor_SensorType sensor_type, .which_value = wippersnapper_sensor_SensorEvent_float_value_tag; _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count] .value.float_value = sensor_value; + _msg_DS18x20Event.sensor_events_count++; } \ No newline at end of file From 57fbe803189d6b128d81b57e17ec9e53c958d791 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 15 Oct 2024 16:17:35 -0400 Subject: [PATCH 13/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx,=20handle=20eve?= =?UTF-8?q?nt/remove?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Wippersnapper_V2.cpp | 13 +++++++++ src/components/ds18x20/controller.cpp | 41 ++++++++++++++++----------- src/components/ds18x20/model.cpp | 15 ++-------- src/components/ds18x20/model.h | 4 +-- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 1f51326df..8dab456c1 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -379,6 +379,13 @@ bool cbDecodeBrokerToDevice(pb_istream_t *stream, const pb_field_t *field, return false; } break; + case wippersnapper_signal_BrokerToDevice_ds18x20_remove_tag: + WS_DEBUG_PRINTLN("-> DS18X20 Remove Message Type"); + if (!WsV2._ds18x20_controller->Handle_Ds18x20Remove(stream)) { + WS_DEBUG_PRINTLN("ERROR: Unable to remove DS18X20 sensor!"); + return false; + } + break; default: WS_DEBUG_PRINTLN("ERROR: BrokerToDevice message type not found!"); return false; @@ -895,6 +902,12 @@ bool Wippersnapper_V2::PublishSignal(pb_size_t which_payload, void *payload) { wippersnapper_signal_DeviceToBroker_ds18x20_added_tag; MsgSignal.payload.ds18x20_added = *(wippersnapper_ds18x20_Ds18x20Added *)payload; break; + case wippersnapper_signal_DeviceToBroker_ds18x20_event_tag: + WS_DEBUG_PRINTLN("DS18X20Event"); + MsgSignal.which_payload = + wippersnapper_signal_DeviceToBroker_ds18x20_event_tag; + MsgSignal.payload.ds18x20_event = *(wippersnapper_ds18x20_Ds18x20Event *)payload; + break; default: WS_DEBUG_PRINTLN("ERROR: Invalid signal payload type, bailing out!"); return false; diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 664c48ea5..d95c45f77 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -118,6 +118,7 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { */ /***********************************************************************/ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { + WS_DEBUG_PRINT("Removing DS18X20 sensor..."); // Attempt to decode the stream if (!_DS18X20_model->DecodeDS18x20Remove(stream)) { WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Remove message"); @@ -135,8 +136,7 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { return true; } } - WS_DEBUG_PRINT("Removed OneWire Pin: "); - WS_DEBUG_PRINTLN(pin_name); + WS_DEBUG_PRINT("Removed!"); return true; } @@ -186,25 +186,34 @@ void DS18X20Controller::update() { wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT, temp_f); } - // Print out the SensorEvent message's contents for debugging - // TODO: After debugging, maybe remove this + // Get and print out the SensorEvent message's contents wippersnapper_ds18x20_Ds18x20Event event_msg = *_DS18X20_model->GetDS18x20EventMsg(); - WS_DEBUG_PRINTLN("SensorEvent message:"); - WS_DEBUG_PRINT("Sensor OneWire bus pin: "); - WS_DEBUG_PRINTLN(event_msg.onewire_pin); - WS_DEBUG_PRINT("Sensor events count: "); - WS_DEBUG_PRINTLN(event_msg.sensor_events_count); + pb_size_t event_count = event_msg.sensor_events_count; - for (int i = 0; - i < _DS18X20_model->GetDS18x20EventMsg()->sensor_events_count; i++) { - WS_DEBUG_PRINT("Sensor type: "); - WS_DEBUG_PRINTLN(event_msg.sensor_events[i].type); + WS_DEBUG_PRINT("Sensor OneWire bus pin: "); + WS_DEBUG_PRINT(temp_dsx_driver.GetOneWirePin()); + WS_DEBUG_PRINT(" got "); + WS_DEBUG_PRINT(event_count); + WS_DEBUG_PRINTLN(" sensor events"); + for (int i = 0; i < event_count; i++) { WS_DEBUG_PRINT("Sensor value: "); WS_DEBUG_PRINTLN(event_msg.sensor_events[i].value.float_value); - WS_DEBUG_PRINT("Sensor value type: "); - WS_DEBUG_PRINTLN(event_msg.sensor_events[i].which_value); } + + // Encode the Ds18x20Event message + if (!_DS18X20_model->EncodeDs18x20Event()) { + WS_DEBUG_PRINTLN("ERROR: Failed to encode Ds18x20Event message"); + continue; + } + // Publish the Ds18x20Event message to the broker + WS_DEBUG_PRINT("Publishing Ds18x20Event message to broker..."); + if (!WsV2.PublishSignal( + wippersnapper_signal_DeviceToBroker_ds18x20_event_tag, + _DS18X20_model->GetDS18x20EventMsg())) { + WS_DEBUG_PRINTLN("ERROR: Failed to publish Ds18x20Event message"); + continue; + } + WS_DEBUG_PRINTLN("Published!"); } - // TODO: Encode and publish the Ds18x20Event message to the broker } \ No newline at end of file diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index 361125b9d..be035befa 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -144,22 +144,13 @@ wippersnapper_ds18x20_Ds18x20Event *DS18X20Model::GetDS18x20EventMsg() { @return True if the message was successfully encoded, False otherwise. */ /*************************************************************************/ -bool DS18X20Model::EncodeDs18x20Event( - char *onewire_pin, pb_size_t sensor_events_count, - const wippersnapper_sensor_SensorEvent sensor_events[2]) { - // Fill the Ds18x20Event message - _msg_DS18x20Event = wippersnapper_ds18x20_Ds18x20Event_init_zero; - strcpy(_msg_DS18x20Event.onewire_pin, onewire_pin); - _msg_DS18x20Event.sensor_events_count = sensor_events_count; - // Fill with sensor_events - for (int i = 0; i < _msg_DS18x20Event.sensor_events_count; i++) { - _msg_DS18x20Event.sensor_events[i] = sensor_events[i]; - } - // Encode and return the Ds18x20Event message +bool DS18X20Model::EncodeDs18x20Event() { + // take the filled _msg_DS18x20Event we built in the controller and encode it size_t sz_msg; if (!pb_get_encoded_size(&sz_msg, wippersnapper_ds18x20_Ds18x20Event_fields, &_msg_DS18x20Event)) return false; + uint8_t buf[sz_msg]; pb_ostream_t msg_stream = pb_ostream_from_buffer(buf, sizeof(buf)); return pb_encode(&msg_stream, wippersnapper_ds18x20_Ds18x20Event_fields, diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index 4362c7771..5d8126e45 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -36,9 +36,7 @@ class DS18X20Model { bool DecodeDS18x20Remove(pb_istream_t *stream); wippersnapper_ds18x20_Ds18x20Remove *GetDS18x20RemoveMsg(); // Ds18x20Event Message - bool - EncodeDs18x20Event(char *onewire_pin, pb_size_t sensor_events_count, - const wippersnapper_sensor_SensorEvent sensor_events[2]); + bool EncodeDs18x20Event(); wippersnapper_ds18x20_Ds18x20Event *GetDS18x20EventMsg(); // TODO: move the below to private if we arent using it in controller? wippersnapper_ds18x20_Ds18x20Event From 6fcd6d6bded56a18fbe0e12af2d27e1c8536ba6a Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 15 Oct 2024 16:40:47 -0400 Subject: [PATCH 14/21] add logging facility for dsx --- src/components/ds18x20/controller.cpp | 74 +++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index d95c45f77..65ad77563 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -43,11 +43,17 @@ DS18X20Controller::~DS18X20Controller() { delete _DS18X20_model; } */ /***********************************************************************/ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { + unsigned long total_start_time = millis(); + // Attempt to decode the incoming message into a Ds18x20Add message + unsigned long decode_start_time = millis(); if (!_DS18X20_model->DecodeDS18x20Add(stream)) { WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Add message"); return false; } + unsigned long decode_end_time = millis(); + WS_DEBUG_PRINT("Decode time: "); + WS_DEBUG_PRINTLN(decode_end_time - decode_start_time); // If we receive no sensor types to configure, bail out if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types_count == 0) { @@ -59,17 +65,26 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { uint8_t pin_name = atoi(_DS18X20_model->GetDS18x20AddMsg()->onewire_pin + 1); // Initialize the DS18X20Hardware object + unsigned long init_start_time = millis(); auto new_dsx_driver = std::make_unique(pin_name); // Attempt to get the sensor's ID on the OneWire bus to show it's been init'd bool is_initialized = new_dsx_driver->GetSensor(); + unsigned long init_end_time = millis(); + WS_DEBUG_PRINT("Initialization time: "); + WS_DEBUG_PRINTLN(init_end_time - init_start_time); + if (is_initialized) { WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); + // Set the sensor's resolution new_dsx_driver->SetResolution( _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); + // Set the sensor's period new_dsx_driver->SetPeriod(_DS18X20_model->GetDS18x20AddMsg()->period); + // Configure the types of sensor reads to perform + unsigned long config_types_start_time = millis(); for (int i = 0; i < _DS18X20_model->GetDS18x20AddMsg()->sensor_types_count; i++) { if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == @@ -81,8 +96,8 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { new_dsx_driver->is_read_temp_f = true; } } + // Add the DS18X20Hardware object to the vector of hardware objects - //_DS18X20_pins.push_back(new_dsx_driver); _DS18X20_pins.push_back(std::move(new_dsx_driver)); } else { WS_DEBUG_PRINTLN( @@ -90,22 +105,35 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { } // Encode and publish a Ds18x20Added message back to the broker + unsigned long encode_start_time = millis(); if (!_DS18X20_model->EncodeDS18x20Added( _DS18X20_model->GetDS18x20AddMsg()->onewire_pin, is_initialized)) { WS_DEBUG_PRINTLN("ERROR: Unable to encode Ds18x20Added message"); return false; } + unsigned long encode_end_time = millis(); + WS_DEBUG_PRINT("Encode message time: "); + WS_DEBUG_PRINTLN(encode_end_time - encode_start_time); // Publish the AnalogIO message to the broker + unsigned long publish_start_time = millis(); if (!WsV2.PublishSignal(wippersnapper_signal_DeviceToBroker_ds18x20_added_tag, _DS18X20_model->GetDS18x20AddedMsg())) { WS_DEBUG_PRINTLN("ERROR: Unable to publish Ds18x20Added message"); return false; } + unsigned long publish_end_time = millis(); + WS_DEBUG_PRINT("Publish message time: "); + WS_DEBUG_PRINTLN(publish_end_time - publish_start_time); + + unsigned long total_end_time = millis(); + WS_DEBUG_PRINT("Total function execution time: "); + WS_DEBUG_PRINTLN(total_end_time - total_start_time); return true; } + /***********************************************************************/ /*! @brief Handles a Ds18x20Remove message from the broker. Attempts to @@ -146,22 +174,31 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { */ /***********************************************************************/ void DS18X20Controller::update() { + unsigned long total_start_time = millis(); + // Bail out if there are no OneWire pins to poll if (_DS18X20_pins.empty()) return; // Iterate through the vector for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { - // Create a temporary DS18X20Hardware driver + unsigned long sensor_start_time = millis(); + + // Create a reference to the DS18X20Hardware object DS18X20Hardware &temp_dsx_driver = *(_DS18X20_pins[i]); + // Check if the driver's timer has not expired yet if (!temp_dsx_driver.IsTimerExpired()) { continue; } + // Create a new sensor_event _DS18X20_model->InitDS18x20EventMsg(); + // Are we reading the temperature in Celsius, Fahrenheit, or both? if (temp_dsx_driver.is_read_temp_c) { + unsigned long temp_c_start_time = millis(); + WS_DEBUG_PRINTLN("Reading temperature in Celsius"); // TODO: Debug remove // Attempt to read the temperature in Celsius if (!temp_dsx_driver.ReadTemperatureC()) { @@ -172,10 +209,15 @@ void DS18X20Controller::update() { _DS18X20_model->addSensorEvent( wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE, temp_c); + + unsigned long temp_c_end_time = millis(); + WS_DEBUG_PRINT("Read temperature Celsius time: "); + WS_DEBUG_PRINTLN(temp_c_end_time - temp_c_start_time); } if (temp_dsx_driver.is_read_temp_f) { - WS_DEBUG_PRINTLN( - "Reading temperature in Fahrenheit"); // TODO: Debug remove + unsigned long temp_f_start_time = millis(); + + WS_DEBUG_PRINTLN("Reading temperature in Fahrenheit"); // TODO: Debug remove // Attempt to read the temperature in Fahrenheit if (!temp_dsx_driver.ReadTemperatureF()) { WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Fahrenheit"); @@ -185,7 +227,12 @@ void DS18X20Controller::update() { _DS18X20_model->addSensorEvent( wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT, temp_f); + + unsigned long temp_f_end_time = millis(); + WS_DEBUG_PRINT("Read temperature Fahrenheit time: "); + WS_DEBUG_PRINTLN(temp_f_end_time - temp_f_start_time); } + // Get and print out the SensorEvent message's contents wippersnapper_ds18x20_Ds18x20Event event_msg = *_DS18X20_model->GetDS18x20EventMsg(); @@ -202,11 +249,17 @@ void DS18X20Controller::update() { } // Encode the Ds18x20Event message + unsigned long encode_start_time = millis(); if (!_DS18X20_model->EncodeDs18x20Event()) { WS_DEBUG_PRINTLN("ERROR: Failed to encode Ds18x20Event message"); continue; } + unsigned long encode_end_time = millis(); + WS_DEBUG_PRINT("Encode event message time: "); + WS_DEBUG_PRINTLN(encode_end_time - encode_start_time); + // Publish the Ds18x20Event message to the broker + unsigned long publish_start_time = millis(); WS_DEBUG_PRINT("Publishing Ds18x20Event message to broker..."); if (!WsV2.PublishSignal( wippersnapper_signal_DeviceToBroker_ds18x20_event_tag, @@ -215,5 +268,16 @@ void DS18X20Controller::update() { continue; } WS_DEBUG_PRINTLN("Published!"); + unsigned long publish_end_time = millis(); + WS_DEBUG_PRINT("Publish event message time: "); + WS_DEBUG_PRINTLN(publish_end_time - publish_start_time); + + unsigned long sensor_end_time = millis(); + WS_DEBUG_PRINT("Total sensor processing time: "); + WS_DEBUG_PRINTLN(sensor_end_time - sensor_start_time); } -} \ No newline at end of file + + unsigned long total_end_time = millis(); + WS_DEBUG_PRINT("Total update() execution time: "); + WS_DEBUG_PRINTLN(total_end_time - total_start_time); +} From 33a72445a55154b9826970765a357e09b7623f5d Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 17 Oct 2024 11:06:39 -0400 Subject: [PATCH 15/21] =?UTF-8?q?=F0=9F=9A=A7=20WIP,=20dsx=20-=20Add=20deb?= =?UTF-8?q?ug=20profile,=20remove=20redundant=20code=20within=20update()?= =?UTF-8?q?=20call?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Wippersnapper_V2.cpp | 33 +++++++++++-- src/Wippersnapper_V2.h | 9 ++-- src/components/ds18x20/controller.cpp | 68 ++++++++++++--------------- src/components/ds18x20/hardware.cpp | 23 ++------- src/components/ds18x20/hardware.h | 1 - src/components/ds18x20/model.cpp | 3 ++ 6 files changed, 68 insertions(+), 69 deletions(-) diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 8dab456c1..f1763d649 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -869,9 +869,15 @@ void Wippersnapper_V2::haltErrorV2(String error, */ /**************************************************************************/ bool Wippersnapper_V2::PublishSignal(pb_size_t which_payload, void *payload) { + + #ifdef DEBUG_PROFILE + unsigned long total_start_time = micros(); + #endif + size_t szMessageBuf; wippersnapper_signal_DeviceToBroker MsgSignal = wippersnapper_signal_DeviceToBroker_init_default; + // Fill generic signal payload with the payload from the args. WS_DEBUG_PRINT("Signal Payload Type: "); switch (which_payload) { @@ -900,13 +906,15 @@ bool Wippersnapper_V2::PublishSignal(pb_size_t which_payload, void *payload) { WS_DEBUG_PRINTLN("DS18X20Added"); MsgSignal.which_payload = wippersnapper_signal_DeviceToBroker_ds18x20_added_tag; - MsgSignal.payload.ds18x20_added = *(wippersnapper_ds18x20_Ds18x20Added *)payload; + MsgSignal.payload.ds18x20_added = + *(wippersnapper_ds18x20_Ds18x20Added *)payload; break; case wippersnapper_signal_DeviceToBroker_ds18x20_event_tag: WS_DEBUG_PRINTLN("DS18X20Event"); MsgSignal.which_payload = wippersnapper_signal_DeviceToBroker_ds18x20_event_tag; - MsgSignal.payload.ds18x20_event = *(wippersnapper_ds18x20_Ds18x20Event *)payload; + MsgSignal.payload.ds18x20_event = + *(wippersnapper_ds18x20_Ds18x20Event *)payload; break; default: WS_DEBUG_PRINTLN("ERROR: Invalid signal payload type, bailing out!"); @@ -934,20 +942,37 @@ bool Wippersnapper_V2::PublishSignal(pb_size_t which_payload, void *payload) { "ERROR: Unable to encode d2b signal message, bailing out!"); return false; } - WS_DEBUG_PRINTLN("Encoded!") + WS_DEBUG_PRINTLN("Encoded!"); - //. Check that we are still connected + // Check that we are still connected runNetFSMV2(); WsV2.feedWDTV2(); + #ifdef DEBUG_PROFILE + unsigned long publish_start_time = micros(); + #endif + // Attempt to publish the signal message to the broker WS_DEBUG_PRINT("Publishing signal message to broker..."); + #ifdef DEBUG_PROFILE + WS_DEBUG_PRINT("Message buffer size: "); + WS_DEBUG_PRINTLN(szMessageBuf); + #endif if (!WsV2._mqttV2->publish(WsV2._topicD2b, msgBuf, szMessageBuf, 1)) { WS_DEBUG_PRINTLN("ERROR: Failed to publish signal message to broker!"); return false; } WS_DEBUG_PRINTLN("Published!"); + #ifdef DEBUG_PROFILE + unsigned long publish_end_time = micros(); + WS_DEBUG_PRINT("Publishing time: "); + WS_DEBUG_PRINTLN(publish_end_time - publish_start_time); + unsigned long total_end_time = micros(); + WS_DEBUG_PRINT("Total PublishSignal() execution time: "); + WS_DEBUG_PRINTLN(total_end_time - total_start_time); + #endif + return true; } diff --git a/src/Wippersnapper_V2.h b/src/Wippersnapper_V2.h index 2f36a245f..a65d34698 100644 --- a/src/Wippersnapper_V2.h +++ b/src/Wippersnapper_V2.h @@ -72,8 +72,6 @@ #include "display/ws_display_ui_helper.h" #endif - - #include "provisioning/ConfigJson.h" #if defined(USE_TINYUSB) #include "provisioning/tinyusb/Wippersnapper_FS_V2.h" @@ -82,6 +80,10 @@ #include "provisioning/littlefs/WipperSnapper_LittleFS.h" #endif +// Debug print macros +// Uncomment the following to enable debug output for function profiling +// #DEBUG_PROFILE 1 + #define WS_VERSION \ "2.0.0-alpha.1" ///< WipperSnapper app. version (semver-formatted) @@ -91,9 +93,6 @@ #define WS_KEEPALIVE_INTERVAL_MS \ 5000 ///< Session keepalive interval time, in milliseconds -#define WS_MQTT_MAX_PAYLOAD_SIZE \ - 512 ///< MAXIMUM expected payload size, in bytes - // Forward declarations (API v1) class Wippersnapper_AnalogIO; class Wippersnapper_FS_V2; diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 65ad77563..72c017851 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -192,52 +192,43 @@ void DS18X20Controller::update() { continue; } - // Create a new sensor_event - _DS18X20_model->InitDS18x20EventMsg(); - - // Are we reading the temperature in Celsius, Fahrenheit, or both? - if (temp_dsx_driver.is_read_temp_c) { - unsigned long temp_c_start_time = millis(); - - WS_DEBUG_PRINTLN("Reading temperature in Celsius"); // TODO: Debug remove // Attempt to read the temperature in Celsius + #ifdef DEBUG_PROFILE + unsigned long temp_c_start_time = millis(); + #endif if (!temp_dsx_driver.ReadTemperatureC()) { WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Celsius"); continue; } + #ifdef DEBUG_PROFILE + unsigned long temp_c_end_time = millis(); + WS_DEBUG_PRINT("Read temperature Celsius time: "); + WS_DEBUG_PRINTLN(temp_c_end_time - temp_c_start_time); + #endif + + // We got a temperature value from the hardware, let's create a new sensor_event + _DS18X20_model->InitDS18x20EventMsg(); + + // Are we reading the temperature in Celsius, Fahrenheit, or both? + if (temp_dsx_driver.is_read_temp_c) { float temp_c = temp_dsx_driver.GetTemperatureC(); _DS18X20_model->addSensorEvent( wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE, temp_c); - - unsigned long temp_c_end_time = millis(); - WS_DEBUG_PRINT("Read temperature Celsius time: "); - WS_DEBUG_PRINTLN(temp_c_end_time - temp_c_start_time); } if (temp_dsx_driver.is_read_temp_f) { - unsigned long temp_f_start_time = millis(); - - WS_DEBUG_PRINTLN("Reading temperature in Fahrenheit"); // TODO: Debug remove - // Attempt to read the temperature in Fahrenheit - if (!temp_dsx_driver.ReadTemperatureF()) { - WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Fahrenheit"); - continue; - } float temp_f = temp_dsx_driver.GetTemperatureF(); _DS18X20_model->addSensorEvent( wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT, temp_f); - - unsigned long temp_f_end_time = millis(); - WS_DEBUG_PRINT("Read temperature Fahrenheit time: "); - WS_DEBUG_PRINTLN(temp_f_end_time - temp_f_start_time); } - // Get and print out the SensorEvent message's contents - wippersnapper_ds18x20_Ds18x20Event event_msg = - *_DS18X20_model->GetDS18x20EventMsg(); - pb_size_t event_count = event_msg.sensor_events_count; + // Get the Ds18x20Event message + wippersnapper_ds18x20_Ds18x20Event* event_msg = _DS18X20_model->GetDS18x20EventMsg(); + pb_size_t event_count = event_msg->sensor_events_count; + + // Print the message's content out for debugging WS_DEBUG_PRINT("Sensor OneWire bus pin: "); WS_DEBUG_PRINT(temp_dsx_driver.GetOneWirePin()); WS_DEBUG_PRINT(" got "); @@ -245,21 +236,16 @@ void DS18X20Controller::update() { WS_DEBUG_PRINTLN(" sensor events"); for (int i = 0; i < event_count; i++) { WS_DEBUG_PRINT("Sensor value: "); - WS_DEBUG_PRINTLN(event_msg.sensor_events[i].value.float_value); + WS_DEBUG_PRINT(event_msg->sensor_events[i].value.float_value); } // Encode the Ds18x20Event message - unsigned long encode_start_time = millis(); if (!_DS18X20_model->EncodeDs18x20Event()) { WS_DEBUG_PRINTLN("ERROR: Failed to encode Ds18x20Event message"); continue; } - unsigned long encode_end_time = millis(); - WS_DEBUG_PRINT("Encode event message time: "); - WS_DEBUG_PRINTLN(encode_end_time - encode_start_time); // Publish the Ds18x20Event message to the broker - unsigned long publish_start_time = millis(); WS_DEBUG_PRINT("Publishing Ds18x20Event message to broker..."); if (!WsV2.PublishSignal( wippersnapper_signal_DeviceToBroker_ds18x20_event_tag, @@ -268,16 +254,20 @@ void DS18X20Controller::update() { continue; } WS_DEBUG_PRINTLN("Published!"); - unsigned long publish_end_time = millis(); - WS_DEBUG_PRINT("Publish event message time: "); - WS_DEBUG_PRINTLN(publish_end_time - publish_start_time); + #ifdef DEBUG_PROFILE unsigned long sensor_end_time = millis(); WS_DEBUG_PRINT("Total sensor processing time: "); WS_DEBUG_PRINTLN(sensor_end_time - sensor_start_time); + #endif } + #ifdef DEBUG_PROFILE unsigned long total_end_time = millis(); - WS_DEBUG_PRINT("Total update() execution time: "); - WS_DEBUG_PRINTLN(total_end_time - total_start_time); + if (total_end_time - total_start_time != 0) { + WS_DEBUG_PRINT("Total update() execution time: "); + WS_DEBUG_PRINTLN(total_end_time - total_start_time); + } + #endif + } diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 0ec0730a9..09d926a6e 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -161,26 +161,9 @@ float DS18X20Hardware::GetTemperatureC() { return _temp_c; } @returns The temperature in Fahrenheit. */ /*************************************************************************/ -float DS18X20Hardware::GetTemperatureF() { return _temp_f; } - -/*************************************************************************/ -/*! - @brief Attempts to obtain the temperature from the sensor, in - degrees Fahrenheit. - @returns True if the temperature was successfully read, False otherwise. -*/ -/*************************************************************************/ -bool DS18X20Hardware::ReadTemperatureF() { - bool is_success = ReadTemperatureC(); - // Did we read the temperature successfully? - if (!is_success) - return false; - // We now have the temperature but it's in in Celsius. Let's convert it to - // Fahrenheit - _temp_f = _temp_c * 9.0 / 5.0 + 32.0; - - _prv_period = millis(); // Update the last time the sensor was polled - return true; +float DS18X20Hardware::GetTemperatureF() { + _temp_f = _temp_c * 9.0 / 5.0 + 32.0; + return _temp_f; } /*************************************************************************/ diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index b709e2158..c76e8b9d7 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -37,7 +37,6 @@ class DS18X20Hardware { bool GetSensor(); uint8_t GetOneWirePin(); bool ReadTemperatureC(); - bool ReadTemperatureF(); float GetTemperatureC(); float GetTemperatureF(); bool is_read_temp_c; ///< Flag telling the controller to read the temperature diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index be035befa..a03dc7c47 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -182,6 +182,9 @@ void DS18X20Model::addSensorEvent(wippersnapper_sensor_SensorType sensor_type, sensor_type; _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count] .which_value = wippersnapper_sensor_SensorEvent_float_value_tag; + + // Convert the float to 2 decimal places + sensor_value = roundf(sensor_value * 100) / 100; _msg_DS18x20Event.sensor_events[_msg_DS18x20Event.sensor_events_count] .value.float_value = sensor_value; _msg_DS18x20Event.sensor_events_count++; From acab0f13324a2f830c5b267d2cb50b9ebb6652d1 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 17 Oct 2024 12:02:48 -0400 Subject: [PATCH 16/21] =?UTF-8?q?=F0=9F=90=9B=20WIP,=20dsx=20-=20Fix=20bug?= =?UTF-8?q?=20where=20two=20sensors=20are=20initd=20but=20only=20the=20fir?= =?UTF-8?q?st=20is=20read?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 72 ++++++++++----------------- src/components/ds18x20/hardware.cpp | 13 +++-- 2 files changed, 36 insertions(+), 49 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 72c017851..40b9263a8 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -43,17 +43,11 @@ DS18X20Controller::~DS18X20Controller() { delete _DS18X20_model; } */ /***********************************************************************/ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { - unsigned long total_start_time = millis(); - // Attempt to decode the incoming message into a Ds18x20Add message - unsigned long decode_start_time = millis(); if (!_DS18X20_model->DecodeDS18x20Add(stream)) { WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Add message"); return false; } - unsigned long decode_end_time = millis(); - WS_DEBUG_PRINT("Decode time: "); - WS_DEBUG_PRINTLN(decode_end_time - decode_start_time); // If we receive no sensor types to configure, bail out if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types_count == 0) { @@ -65,13 +59,9 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { uint8_t pin_name = atoi(_DS18X20_model->GetDS18x20AddMsg()->onewire_pin + 1); // Initialize the DS18X20Hardware object - unsigned long init_start_time = millis(); auto new_dsx_driver = std::make_unique(pin_name); // Attempt to get the sensor's ID on the OneWire bus to show it's been init'd bool is_initialized = new_dsx_driver->GetSensor(); - unsigned long init_end_time = millis(); - WS_DEBUG_PRINT("Initialization time: "); - WS_DEBUG_PRINTLN(init_end_time - init_start_time); if (is_initialized) { WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); @@ -84,7 +74,6 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { new_dsx_driver->SetPeriod(_DS18X20_model->GetDS18x20AddMsg()->period); // Configure the types of sensor reads to perform - unsigned long config_types_start_time = millis(); for (int i = 0; i < _DS18X20_model->GetDS18x20AddMsg()->sensor_types_count; i++) { if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == @@ -111,29 +100,16 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { WS_DEBUG_PRINTLN("ERROR: Unable to encode Ds18x20Added message"); return false; } - unsigned long encode_end_time = millis(); - WS_DEBUG_PRINT("Encode message time: "); - WS_DEBUG_PRINTLN(encode_end_time - encode_start_time); - // Publish the AnalogIO message to the broker - unsigned long publish_start_time = millis(); if (!WsV2.PublishSignal(wippersnapper_signal_DeviceToBroker_ds18x20_added_tag, _DS18X20_model->GetDS18x20AddedMsg())) { WS_DEBUG_PRINTLN("ERROR: Unable to publish Ds18x20Added message"); return false; } - unsigned long publish_end_time = millis(); - WS_DEBUG_PRINT("Publish message time: "); - WS_DEBUG_PRINTLN(publish_end_time - publish_start_time); - - unsigned long total_end_time = millis(); - WS_DEBUG_PRINT("Total function execution time: "); - WS_DEBUG_PRINTLN(total_end_time - total_start_time); return true; } - /***********************************************************************/ /*! @brief Handles a Ds18x20Remove message from the broker. Attempts to @@ -174,7 +150,9 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { */ /***********************************************************************/ void DS18X20Controller::update() { +#ifdef DEBUG_PROFILE unsigned long total_start_time = millis(); +#endif // Bail out if there are no OneWire pins to poll if (_DS18X20_pins.empty()) @@ -182,7 +160,9 @@ void DS18X20Controller::update() { // Iterate through the vector for (uint8_t i = 0; i < _DS18X20_pins.size(); i++) { +#ifdef DEBUG_PROFILE unsigned long sensor_start_time = millis(); +#endif // Create a reference to the DS18X20Hardware object DS18X20Hardware &temp_dsx_driver = *(_DS18X20_pins[i]); @@ -192,21 +172,24 @@ void DS18X20Controller::update() { continue; } - // Attempt to read the temperature in Celsius - #ifdef DEBUG_PROFILE - unsigned long temp_c_start_time = millis(); - #endif - if (!temp_dsx_driver.ReadTemperatureC()) { - WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Celsius"); - continue; - } - #ifdef DEBUG_PROFILE - unsigned long temp_c_end_time = millis(); - WS_DEBUG_PRINT("Read temperature Celsius time: "); - WS_DEBUG_PRINTLN(temp_c_end_time - temp_c_start_time); - #endif +// Attempt to read the temperature in Celsius +#ifdef DEBUG_PROFILE + unsigned long temp_c_start_time = millis(); +#endif - // We got a temperature value from the hardware, let's create a new sensor_event + if (!temp_dsx_driver.ReadTemperatureC()) { + WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Celsius"); + continue; + } + +#ifdef DEBUG_PROFILE + unsigned long temp_c_end_time = millis(); + WS_DEBUG_PRINT("Read temperature Celsius time: "); + WS_DEBUG_PRINTLN(temp_c_end_time - temp_c_start_time); +#endif + + // We got a temperature value from the hardware, let's create a new + // sensor_event _DS18X20_model->InitDS18x20EventMsg(); // Are we reading the temperature in Celsius, Fahrenheit, or both? @@ -224,10 +207,10 @@ void DS18X20Controller::update() { } // Get the Ds18x20Event message - wippersnapper_ds18x20_Ds18x20Event* event_msg = _DS18X20_model->GetDS18x20EventMsg(); + wippersnapper_ds18x20_Ds18x20Event *event_msg = + _DS18X20_model->GetDS18x20EventMsg(); pb_size_t event_count = event_msg->sensor_events_count; - // Print the message's content out for debugging WS_DEBUG_PRINT("Sensor OneWire bus pin: "); WS_DEBUG_PRINT(temp_dsx_driver.GetOneWirePin()); @@ -255,19 +238,18 @@ void DS18X20Controller::update() { } WS_DEBUG_PRINTLN("Published!"); - #ifdef DEBUG_PROFILE +#ifdef DEBUG_PROFILE unsigned long sensor_end_time = millis(); WS_DEBUG_PRINT("Total sensor processing time: "); WS_DEBUG_PRINTLN(sensor_end_time - sensor_start_time); - #endif +#endif } - #ifdef DEBUG_PROFILE +#ifdef DEBUG_PROFILE unsigned long total_end_time = millis(); if (total_end_time - total_start_time != 0) { WS_DEBUG_PRINT("Total update() execution time: "); WS_DEBUG_PRINTLN(total_end_time - total_start_time); } - #endif - +#endif } diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 09d926a6e..7f0330e92 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -161,9 +161,9 @@ float DS18X20Hardware::GetTemperatureC() { return _temp_c; } @returns The temperature in Fahrenheit. */ /*************************************************************************/ -float DS18X20Hardware::GetTemperatureF() { - _temp_f = _temp_c * 9.0 / 5.0 + 32.0; - return _temp_f; +float DS18X20Hardware::GetTemperatureF() { + _temp_f = _temp_c * 9.0 / 5.0 + 32.0; + return _temp_f; } /*************************************************************************/ @@ -178,6 +178,11 @@ bool DS18X20Hardware::ReadTemperatureC() { // bus OneWireNg::ErrorCode ec = _drv_therm.convertTemp(_sensorId, DSTherm::MAX_CONV_TIME, false); + + // TODO: this is extra debug prints, delete all prints and just return for + // final ver. + WS_DEBUG_PRINT("Error Code: "); + WS_DEBUG_PRINTLN(ec); if (ec != OneWireNg::EC_SUCCESS) return false; @@ -185,7 +190,7 @@ bool DS18X20Hardware::ReadTemperatureC() { // sensor id while reissuing readScratchpadSingle() calls. // Note, due to its storage class the placeholder is zero initialized. static Placeholder scrpd; - ec = _drv_therm.readScratchpadSingle(scrpd); + ec = _drv_therm.readScratchpad(_sensorId, scrpd); if (ec != OneWireNg::EC_SUCCESS) return false; From 737428784e56b690e2b2f1eb14e9b0a07716b566 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 17 Oct 2024 13:01:01 -0400 Subject: [PATCH 17/21] =?UTF-8?q?=F0=9F=90=9B=20Fix=20DSx=20bug,=20onewire?= =?UTF-8?q?Pin=20not=20added=20to=20ds18x20Evetn=20messages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 6 +++++- src/components/ds18x20/hardware.cpp | 12 ++++++++---- src/components/ds18x20/hardware.h | 5 ++++- src/components/ds18x20/model.cpp | 3 ++- src/components/ds18x20/model.h | 2 +- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index 40b9263a8..f5554fe0e 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -66,6 +66,10 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { if (is_initialized) { WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); + // Set the sensor's pin name (non-logical) + new_dsx_driver->setOneWirePinName( + _DS18X20_model->GetDS18x20AddMsg()->onewire_pin); + // Set the sensor's resolution new_dsx_driver->SetResolution( _DS18X20_model->GetDS18x20AddMsg()->sensor_resolution); @@ -190,7 +194,7 @@ void DS18X20Controller::update() { // We got a temperature value from the hardware, let's create a new // sensor_event - _DS18X20_model->InitDS18x20EventMsg(); + _DS18X20_model->InitDS18x20EventMsg(temp_dsx_driver.getOneWirePinName()); // Are we reading the temperature in Celsius, Fahrenheit, or both? if (temp_dsx_driver.is_read_temp_c) { diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 7f0330e92..98cad2cd2 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -85,6 +85,14 @@ bool DS18X20Hardware::GetSensor() { /***********************************************************************/ uint8_t DS18X20Hardware::GetOneWirePin() { return _onewire_pin; } +void DS18X20Hardware::setOneWirePinName(const char *prettyOWPinName) { + strncpy(_onewire_pin_name, prettyOWPinName, sizeof(_onewire_pin_name)); + _onewire_pin_name[sizeof(_onewire_pin_name) - 1] = '\0'; +} + +// Return _onewire_pin_name +const char *DS18X20Hardware::getOneWirePinName() { return _onewire_pin_name; } + /*************************************************************************/ /*! @brief Sets the DS18X20 sensor's resolution. @@ -179,10 +187,6 @@ bool DS18X20Hardware::ReadTemperatureC() { OneWireNg::ErrorCode ec = _drv_therm.convertTemp(_sensorId, DSTherm::MAX_CONV_TIME, false); - // TODO: this is extra debug prints, delete all prints and just return for - // final ver. - WS_DEBUG_PRINT("Error Code: "); - WS_DEBUG_PRINTLN(ec); if (ec != OneWireNg::EC_SUCCESS) return false; diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index c76e8b9d7..5df51a877 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -31,11 +31,13 @@ class DS18X20Hardware { DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); void printErrorCode(OneWireNg::ErrorCode ec); + void setOneWirePinName(const char *prettyOWPinName); void SetResolution(int resolution); void SetPeriod(float period); bool IsTimerExpired(); bool GetSensor(); uint8_t GetOneWirePin(); + const char *getOneWirePinName(); bool ReadTemperatureC(); float GetTemperatureC(); float GetTemperatureF(); @@ -52,7 +54,8 @@ class DS18X20Hardware { float _temp_f; ///< Temperature in Fahrenheit // From the PB model uint8_t - _onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing + _onewire_pin; ///< Pin utilized by the OneWire bus, used for addressing + char _onewire_pin_name[5]; ///< Name of the OneWire bus pin float _period; ///< The desired period to read the sensor, in seconds float _prv_period; ///< Last time the sensor was polled, in seconds }; diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index a03dc7c47..9470985cd 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -162,9 +162,10 @@ bool DS18X20Model::EncodeDs18x20Event() { @brief Initializes the Ds18x20Event message. */ /*************************************************************************/ -void DS18X20Model::InitDS18x20EventMsg() { +void DS18X20Model::InitDS18x20EventMsg(const char *ow_pin_name) { _msg_DS18x20Event = wippersnapper_ds18x20_Ds18x20Event_init_zero; _msg_DS18x20Event.sensor_events_count = 0; + strcpy(_msg_DS18x20Event.onewire_pin, ow_pin_name); } /*************************************************************************/ diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index 5d8126e45..133f64c32 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -41,7 +41,7 @@ class DS18X20Model { // TODO: move the below to private if we arent using it in controller? wippersnapper_ds18x20_Ds18x20Event _msg_DS18x20Event; ///< wippersnapper_ds18x20_Ds18x20Event message - void InitDS18x20EventMsg(); + void InitDS18x20EventMsg(const char *ow_pin_name); void addSensorEvent(wippersnapper_sensor_SensorType sensor_type, float sensor_value); From 63385d1170fde817989803ee42c14ded448d3803 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 17 Oct 2024 14:40:27 -0400 Subject: [PATCH 18/21] =?UTF-8?q?=F0=9F=90=9B=20Don't=20allow=20non-object?= =?UTF-8?q?-temp=20SensorTypes=20to=20init=20a=20ds18=20sensor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index f5554fe0e..d6bd12b3a 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -45,13 +45,13 @@ DS18X20Controller::~DS18X20Controller() { delete _DS18X20_model; } bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { // Attempt to decode the incoming message into a Ds18x20Add message if (!_DS18X20_model->DecodeDS18x20Add(stream)) { - WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Add message"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to decode Ds18x20Add message"); return false; } // If we receive no sensor types to configure, bail out if (_DS18X20_model->GetDS18x20AddMsg()->sensor_types_count == 0) { - WS_DEBUG_PRINTLN("ERROR: No ds18x sensor types provided!"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: No ds18x sensor types provided!"); return false; } @@ -87,6 +87,9 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { _DS18X20_model->GetDS18x20AddMsg()->sensor_types[i] == wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT) { new_dsx_driver->is_read_temp_f = true; + } else { + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unknown SensorType, failed to add sensor!"); + return false; } } @@ -94,20 +97,20 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { _DS18X20_pins.push_back(std::move(new_dsx_driver)); } else { WS_DEBUG_PRINTLN( - "ERROR: Unable to get ds18x sensor ID, ds18x sensor not initialized"); + "ERROR | DS18x20: Unable to get sensor ID!"); } // Encode and publish a Ds18x20Added message back to the broker unsigned long encode_start_time = millis(); if (!_DS18X20_model->EncodeDS18x20Added( _DS18X20_model->GetDS18x20AddMsg()->onewire_pin, is_initialized)) { - WS_DEBUG_PRINTLN("ERROR: Unable to encode Ds18x20Added message"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to encode Ds18x20Added message!"); return false; } if (!WsV2.PublishSignal(wippersnapper_signal_DeviceToBroker_ds18x20_added_tag, _DS18X20_model->GetDS18x20AddedMsg())) { - WS_DEBUG_PRINTLN("ERROR: Unable to publish Ds18x20Added message"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to publish Ds18x20Added message!"); return false; } @@ -129,7 +132,7 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { WS_DEBUG_PRINT("Removing DS18X20 sensor..."); // Attempt to decode the stream if (!_DS18X20_model->DecodeDS18x20Remove(stream)) { - WS_DEBUG_PRINTLN("ERROR: Unable to decode Ds18x20Remove message"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to decode Ds18x20Remove message"); return false; } // Create a temp. instance of the Ds18x20Remove message @@ -144,7 +147,7 @@ bool DS18X20Controller::Handle_Ds18x20Remove(pb_istream_t *stream) { return true; } } - WS_DEBUG_PRINT("Removed!"); + WS_DEBUG_PRINTLN("Removed!"); return true; } @@ -182,7 +185,7 @@ void DS18X20Controller::update() { #endif if (!temp_dsx_driver.ReadTemperatureC()) { - WS_DEBUG_PRINTLN("ERROR: Unable to read temperature in Celsius"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to read temperature in Celsius"); continue; } @@ -228,7 +231,7 @@ void DS18X20Controller::update() { // Encode the Ds18x20Event message if (!_DS18X20_model->EncodeDs18x20Event()) { - WS_DEBUG_PRINTLN("ERROR: Failed to encode Ds18x20Event message"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Failed to encode Ds18x20Event message"); continue; } @@ -237,7 +240,7 @@ void DS18X20Controller::update() { if (!WsV2.PublishSignal( wippersnapper_signal_DeviceToBroker_ds18x20_event_tag, _DS18X20_model->GetDS18x20EventMsg())) { - WS_DEBUG_PRINTLN("ERROR: Failed to publish Ds18x20Event message"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Failed to publish Ds18x20Event message"); continue; } WS_DEBUG_PRINTLN("Published!"); From bbf4cad0041992a0d8792f7a6808e329da83579a Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 17 Oct 2024 16:48:33 -0400 Subject: [PATCH 19/21] =?UTF-8?q?=F0=9F=93=9D=20Review=20controller/hardwa?= =?UTF-8?q?re=20classes,=20self-review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/controller.cpp | 37 +++++++++++---------- src/components/ds18x20/hardware.cpp | 46 ++++++++++----------------- src/components/ds18x20/hardware.h | 7 ++-- 3 files changed, 40 insertions(+), 50 deletions(-) diff --git a/src/components/ds18x20/controller.cpp b/src/components/ds18x20/controller.cpp index d6bd12b3a..f24360695 100644 --- a/src/components/ds18x20/controller.cpp +++ b/src/components/ds18x20/controller.cpp @@ -66,7 +66,7 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { if (is_initialized) { WS_DEBUG_PRINTLN("Sensor found on OneWire bus and initialized"); - // Set the sensor's pin name (non-logical) + // Set the sensor's pin name (non-logical name) new_dsx_driver->setOneWirePinName( _DS18X20_model->GetDS18x20AddMsg()->onewire_pin); @@ -88,16 +88,18 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT) { new_dsx_driver->is_read_temp_f = true; } else { - WS_DEBUG_PRINTLN("ERROR | DS18x20: Unknown SensorType, failed to add sensor!"); - return false; + WS_DEBUG_PRINTLN( + "ERROR | DS18x20: Unknown SensorType, failed to add sensor!"); + is_initialized = false; } } - // Add the DS18X20Hardware object to the vector of hardware objects - _DS18X20_pins.push_back(std::move(new_dsx_driver)); + // If the sensor was successfully initialized, add it to the controller + if (is_initialized == true) + _DS18X20_pins.push_back(std::move(new_dsx_driver)); } else { - WS_DEBUG_PRINTLN( - "ERROR | DS18x20: Unable to get sensor ID!"); + WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to get sensor ID!"); + is_initialized = false; } // Encode and publish a Ds18x20Added message back to the broker @@ -110,7 +112,8 @@ bool DS18X20Controller::Handle_Ds18x20Add(pb_istream_t *stream) { if (!WsV2.PublishSignal(wippersnapper_signal_DeviceToBroker_ds18x20_added_tag, _DS18X20_model->GetDS18x20AddedMsg())) { - WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to publish Ds18x20Added message!"); + WS_DEBUG_PRINTLN( + "ERROR | DS18x20: Unable to publish Ds18x20Added message!"); return false; } @@ -185,7 +188,8 @@ void DS18X20Controller::update() { #endif if (!temp_dsx_driver.ReadTemperatureC()) { - WS_DEBUG_PRINTLN("ERROR | DS18x20: Unable to read temperature in Celsius"); + WS_DEBUG_PRINTLN( + "ERROR | DS18x20: Unable to read temperature in Celsius"); continue; } @@ -219,28 +223,27 @@ void DS18X20Controller::update() { pb_size_t event_count = event_msg->sensor_events_count; // Print the message's content out for debugging - WS_DEBUG_PRINT("Sensor OneWire bus pin: "); + WS_DEBUG_PRINT("DS18x20: OneWire pin: "); WS_DEBUG_PRINT(temp_dsx_driver.GetOneWirePin()); - WS_DEBUG_PRINT(" got "); - WS_DEBUG_PRINT(event_count); - WS_DEBUG_PRINTLN(" sensor events"); + WS_DEBUG_PRINT(" got value(s): "); for (int i = 0; i < event_count; i++) { - WS_DEBUG_PRINT("Sensor value: "); WS_DEBUG_PRINT(event_msg->sensor_events[i].value.float_value); } // Encode the Ds18x20Event message if (!_DS18X20_model->EncodeDs18x20Event()) { - WS_DEBUG_PRINTLN("ERROR | DS18x20: Failed to encode Ds18x20Event message"); + WS_DEBUG_PRINTLN( + "ERROR | DS18x20: Failed to encode Ds18x20Event message"); continue; } // Publish the Ds18x20Event message to the broker - WS_DEBUG_PRINT("Publishing Ds18x20Event message to broker..."); + WS_DEBUG_PRINT("DS18x20: Publishing event to broker..."); if (!WsV2.PublishSignal( wippersnapper_signal_DeviceToBroker_ds18x20_event_tag, _DS18X20_model->GetDS18x20EventMsg())) { - WS_DEBUG_PRINTLN("ERROR | DS18x20: Failed to publish Ds18x20Event message"); + WS_DEBUG_PRINTLN( + "ERROR | DS18x20: Failed to publish Ds18x20Event message"); continue; } WS_DEBUG_PRINTLN("Published!"); diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 98cad2cd2..4936d983f 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -39,32 +39,6 @@ DS18X20Hardware::~DS18X20Hardware() { INPUT); // Set the pin to hi-z and release it for other uses } -void DS18X20Hardware::printErrorCode(OneWireNg::ErrorCode ec) { - switch (ec) { - case OneWireNg::EC_SUCCESS: - WS_DEBUG_PRINTLN("EC_SUCCESS"); - break; - case OneWireNg::EC_NO_DEVS: - WS_DEBUG_PRINTLN("EC_NO_DEVSNo slave devices; search process finished"); - break; - case OneWireNg::EC_BUS_ERROR: - WS_DEBUG_PRINTLN("EC_BUS_ERROR-wire bus error"); - break; - case OneWireNg::EC_CRC_ERROR: - WS_DEBUG_PRINTLN("EC_CRC_ERRORCRC error"); - break; - case OneWireNg::EC_UNSUPPORED: - WS_DEBUG_PRINTLN("EC_UNSUPPOREDService is not supported by the platform"); - break; - case OneWireNg::EC_FULL: - WS_DEBUG_PRINTLN("EC_FULLNo space (e.g. filters table is full)"); - break; - default: - WS_DEBUG_PRINTLN("EC ?!?1 Unknown error"); - break; - } -} - /***********************************************************************/ /*! @brief Get the sensor's ID @@ -73,7 +47,6 @@ void DS18X20Hardware::printErrorCode(OneWireNg::ErrorCode ec) { /***********************************************************************/ bool DS18X20Hardware::GetSensor() { OneWireNg::ErrorCode ec = _ow->readSingleId(_sensorId); - printErrorCode(ec); return ec == OneWireNg::EC_SUCCESS; } @@ -85,12 +58,26 @@ bool DS18X20Hardware::GetSensor() { /***********************************************************************/ uint8_t DS18X20Hardware::GetOneWirePin() { return _onewire_pin; } +/***********************************************************************/ +/*! + @brief Sets the name of the OneWire bus pin. + @param prettyOWPinName + The name of the OneWire bus pin (non-logical pin name, + includes the "D" or "A" prefix). +*/ +/***********************************************************************/ void DS18X20Hardware::setOneWirePinName(const char *prettyOWPinName) { strncpy(_onewire_pin_name, prettyOWPinName, sizeof(_onewire_pin_name)); _onewire_pin_name[sizeof(_onewire_pin_name) - 1] = '\0'; } -// Return _onewire_pin_name +/***********************************************************************/ +/*! + @brief Gets the name of the OneWire bus pin. + @returns The name of the OneWire bus pin (non-logical pin name, + includes the "D" or "A" prefix). +*/ +/***********************************************************************/ const char *DS18X20Hardware::getOneWirePinName() { return _onewire_pin_name; } /*************************************************************************/ @@ -141,7 +128,8 @@ void DS18X20Hardware::SetResolution(int resolution) { /*************************************************************************/ void DS18X20Hardware::SetPeriod(float period) { _period = period * 1000; // Convert to milliseconds - _prv_period = 0; // Also reset the previous period here + _prv_period = 0; // Also reset the previous period whenever we set a + // new period } /*************************************************************************/ diff --git a/src/components/ds18x20/hardware.h b/src/components/ds18x20/hardware.h index 5df51a877..0fcb8288c 100644 --- a/src/components/ds18x20/hardware.h +++ b/src/components/ds18x20/hardware.h @@ -30,14 +30,13 @@ class DS18X20Hardware { public: DS18X20Hardware(uint8_t onewire_pin); ~DS18X20Hardware(); - void printErrorCode(OneWireNg::ErrorCode ec); - void setOneWirePinName(const char *prettyOWPinName); + uint8_t GetOneWirePin(); void SetResolution(int resolution); void SetPeriod(float period); + void setOneWirePinName(const char *prettyOWPinName); + const char *getOneWirePinName(); bool IsTimerExpired(); bool GetSensor(); - uint8_t GetOneWirePin(); - const char *getOneWirePinName(); bool ReadTemperatureC(); float GetTemperatureC(); float GetTemperatureF(); From 2cc6c073db1c0a4e8a747b1ebdcc5f1b889d4893 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 18 Oct 2024 10:48:36 -0400 Subject: [PATCH 20/21] =?UTF-8?q?=F0=9F=8E=A8=20Review=20dsx=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ds18x20/model.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/ds18x20/model.h b/src/components/ds18x20/model.h index 133f64c32..0cae22782 100644 --- a/src/components/ds18x20/model.h +++ b/src/components/ds18x20/model.h @@ -26,25 +26,21 @@ class DS18X20Model { public: DS18X20Model(); ~DS18X20Model(); - // Ds18x20Add Message + // Ds18x20Add Message API bool DecodeDS18x20Add(pb_istream_t *stream); wippersnapper_ds18x20_Ds18x20Add *GetDS18x20AddMsg(); - // DS18x20Added Message + // DS18x20Added Message API bool EncodeDS18x20Added(char *onewire_pin, bool is_init); wippersnapper_ds18x20_Ds18x20Added *GetDS18x20AddedMsg(); - // Ds18x20Remove Message + // Ds18x20Remove Message API bool DecodeDS18x20Remove(pb_istream_t *stream); wippersnapper_ds18x20_Ds18x20Remove *GetDS18x20RemoveMsg(); - // Ds18x20Event Message + // Ds18x20Event Message API bool EncodeDs18x20Event(); wippersnapper_ds18x20_Ds18x20Event *GetDS18x20EventMsg(); - // TODO: move the below to private if we arent using it in controller? - wippersnapper_ds18x20_Ds18x20Event - _msg_DS18x20Event; ///< wippersnapper_ds18x20_Ds18x20Event message void InitDS18x20EventMsg(const char *ow_pin_name); void addSensorEvent(wippersnapper_sensor_SensorType sensor_type, float sensor_value); - private: wippersnapper_ds18x20_Ds18x20Add _msg_DS18x20Add; ///< wippersnapper_ds18x20_Ds18x20Add message @@ -52,5 +48,7 @@ class DS18X20Model { _msg_DS18x20Added; ///< wippersnapper_ds18x20_Ds18x20Added message wippersnapper_ds18x20_Ds18x20Remove _msg_DS18x20Remove; ///< wippersnapper_ds18x20_Ds18x20Remove message + wippersnapper_ds18x20_Ds18x20Event + _msg_DS18x20Event; ///< wippersnapper_ds18x20_Ds18x20Event message }; #endif // WS_DIGITALIO_MODEL_H \ No newline at end of file From 6e3d4ccce824a364c59b9e95bed0124733378b82 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 22 Oct 2024 16:21:30 -0400 Subject: [PATCH 21/21] address tyeth review --- src/components/ds18x20/hardware.cpp | 4 +++- src/components/ds18x20/model.cpp | 8 ++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/ds18x20/hardware.cpp b/src/components/ds18x20/hardware.cpp index 4936d983f..2ee871d5c 100644 --- a/src/components/ds18x20/hardware.cpp +++ b/src/components/ds18x20/hardware.cpp @@ -187,8 +187,10 @@ bool DS18X20Hardware::ReadTemperatureC() { return false; // Read the temperature from the sensor + // NOTE: The temperature returned by getTemp2() is the temperature * 16 long temp = scrpd->getTemp2(); - _temp_c = temp / 16.0; // Convert from 16-bit int to float + // Divide the temperature from the getTemp2() call by 16 and assign as a float. + _temp_c = temp / 16.0; _prv_period = millis(); // Update the last time the sensor was polled return true; diff --git a/src/components/ds18x20/model.cpp b/src/components/ds18x20/model.cpp index 9470985cd..17dd039c0 100644 --- a/src/components/ds18x20/model.cpp +++ b/src/components/ds18x20/model.cpp @@ -135,12 +135,6 @@ wippersnapper_ds18x20_Ds18x20Event *DS18X20Model::GetDS18x20EventMsg() { /*************************************************************************/ /*! @brief Encodes a Ds18x20Event message. - @param onewire_pin - The OneWire bus' pin where the sensor is located. - @param sensor_events_count - The number of sensorevent messages to encode. - @param sensor_events - The sensorevent messages to encode. @return True if the message was successfully encoded, False otherwise. */ /*************************************************************************/ @@ -160,6 +154,8 @@ bool DS18X20Model::EncodeDs18x20Event() { /*************************************************************************/ /*! @brief Initializes the Ds18x20Event message. + @param ow_pin_name + The OneWire bus pin name. */ /*************************************************************************/ void DS18X20Model::InitDS18x20EventMsg(const char *ow_pin_name) {