Skip to content
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
b784f3f
Initial Commit - Hooks for MQTT topics and decoders
brentru Aug 14, 2025
209abea
Track WipperSnapper_Protobuf add-display-v1 commit
brentru Aug 14, 2025
71cb68d
Add deserializer hooks
brentru Aug 14, 2025
967650e
Add display component, start handleAdd
brentru Aug 15, 2025
14ef634
Update for Protobuf 23abc52..c83b680
brentru Aug 15, 2025
c308694
Routing epd begin thru
brentru Aug 15, 2025
fc41a7d
Add beginEPD full implementation with safety concerns and a better in…
brentru Aug 15, 2025
37904f3
Almost full circle display add
brentru Aug 15, 2025
ab55789
Implement HandleDisplayRemove
brentru Aug 15, 2025
cf617c5
Refactor out hardware file
brentru Aug 18, 2025
2743edc
last bit of optimization to allow a factory map within hardware.cpp a…
brentru Aug 18, 2025
ca75bf0
Match 711bf14..000802e
brentru Aug 18, 2025
12d2354
Route DisplayWrite throughout MVC
brentru Aug 19, 2025
e8fbd87
Checkin Display Write handler code
brentru Aug 19, 2025
cfb893d
debugging failed to subscribe err
brentru Aug 19, 2025
0242373
Speed up writeMessage
brentru Aug 20, 2025
b5e5334
Doxygen across new sections
brentru Aug 20, 2025
05db092
Implement publishing back to IO, T5 driver for pre-2025
brentru Aug 20, 2025
49cf9cc
Detect SSD1680 automatically
brentru Aug 21, 2025
1b9b634
bump ver
brentru Aug 21, 2025
82476b8
Clang format
brentru Aug 22, 2025
3f9d054
doxy2
brentru Aug 22, 2025
0663d1d
Putback existing Doxyfile
brentru Aug 22, 2025
3636761
checkin 615ef8c..fbc883c
brentru Aug 25, 2025
bf68aed
Update for PB
brentru Aug 25, 2025
6d5f951
Update to match fbc883c..b7e6d06
brentru Aug 25, 2025
41598d9
Cleanup and share parsePin between beginTft and beginEpd
brentru Aug 25, 2025
5c42673
Pull in ST7789
brentru Aug 25, 2025
6c1666e
Expose more funcs in drvBase
brentru Aug 25, 2025
33e43d5
fix linker complaint
brentru Aug 25, 2025
098edaa
Fix text size, DisplayWrite not showing up yet
brentru Aug 25, 2025
437b091
Fix init for ST7789
brentru Aug 26, 2025
7be4cad
Set text size via new setter
brentru Aug 26, 2025
c896159
Add Doxygen
brentru Aug 26, 2025
1c265a1
Clang!
brentru Aug 26, 2025
5efe8ce
Address @tyeth review
brentru Aug 27, 2025
a4d9e8e
Removing LVGL display/ in favor of components/display approach
brentru Sep 3, 2025
f1a4e87
Remove LVGL from build tools
brentru Sep 3, 2025
2fd7b8c
Merge branch 'main' into add-spi-tft
brentru Sep 3, 2025
c3f38e6
Fix CI for TFT
brentru Sep 3, 2025
0aea2c0
Add Adafruit AS5600 Library
brentru Sep 3, 2025
cc42fbb
Add Adafruit BMP5xx Library
brentru Sep 3, 2025
4996780
Add Adafruit MLX90632 Library
brentru Sep 3, 2025
bfb1d3a
Clang ST7789
brentru Sep 3, 2025
8022edd
Add preemptive driver for ssd1306, no refactoring yet
brentru Sep 4, 2025
6a233fb
Refactor out i2c_output work, bring in new display elements as i2c ou…
brentru Sep 4, 2025
9c34298
Match 6eae897..1065c87
brentru Sep 4, 2025
bd2ce40
Add driver for sh1107, not hooked into hw yet
brentru Sep 4, 2025
80800ee
hook
brentru Sep 4, 2025
f601d4d
Add driver for 7seg
brentru Sep 5, 2025
9b5da3d
Add driver for quadalphanum
brentru Sep 5, 2025
8d03bdb
Revert all changes after bfb1d3a
brentru Sep 5, 2025
3a98977
Run debug, add splashscreen for ePD
brentru Sep 8, 2025
564959b
Briefly show splash, add more epd modes, add feed for wdt so it doesn…
brentru Sep 9, 2025
bf1e68c
Update PBs
brentru Sep 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@ data/

# Misc. Data
tests/
venv/
venv/

Doxyfile
13 changes: 12 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
{
"files.associations": {
"limits": "c",
"type_traits": "c"
"type_traits": "c",
"array": "cpp",
"deque": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"string_view": "cpp",
"format": "cpp",
"initializer_list": "cpp",
"span": "cpp"
},
"C_Cpp.dimInactiveRegions": true,
"dotnet.defaultSolution": "disable",
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -2451,4 +2451,4 @@ GENERATE_LEGEND = YES
# plantuml temporary files.
# The default value is: YES.

DOT_CLEANUP = YES
DOT_CLEANUP = YES
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name=Adafruit WipperSnapper
version=1.0.0-beta.110
version=1.0.0-beta.112
author=Adafruit
maintainer=Adafruit <adafruitio@adafruit.com>
sentence=Arduino application for Adafruit.io WipperSnapper
paragraph=Arduino application for Adafruit.io WipperSnapper
category=Communication
url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino
architectures=*
depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306
depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD
11 changes: 6 additions & 5 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,18 @@ lib_deps =
https://github.com/tyeth/omron-devhub_d6t-arduino.git
https://github.com/pstolarz/OneWireNg.git
; COMMENT OUT FOR RP2040/RP2350 BOARDS
https://github.com/milesburton/Arduino-Temperature-Control-Library.git
;https://github.com/milesburton/Arduino-Temperature-Control-Library.git
; AND UNCOMMENT FOR RP2040/RP2350 BOARDS
; https://github.com/pstolarz/Arduino-Temperature-Control-Library.git
https://github.com/pstolarz/Arduino-Temperature-Control-Library.git
https://github.com/Sensirion/arduino-sht.git
https://github.com/Sensirion/arduino-i2c-scd4x.git
https://github.com/Sensirion/arduino-i2c-sen5x.git
https://github.com/Sensirion/arduino-i2c-sen66.git
https://github.com/adafruit/WiFiNINA.git
https://github.com/Starmbi/hp_BH1750.git
https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git

Adafruit EPD
Adafruit ST7735 and ST7789 Library


; Common build environment for ESP32 platform
Expand Down Expand Up @@ -211,7 +212,7 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_feather_esp32s2_tft
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT -DBOARD_HAS_PSRAM
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-S2 Reverse TFT
Expand Down Expand Up @@ -265,7 +266,7 @@ extends = common:esp32
board = adafruit_magtag29_esp32s2
build_flags = -DARDUINO_MAGTAG29_ESP32S2 -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-noota.csv
extra_scripts = pre:rename_usb_config.py

; Adafruit Metro ESP32-S2
Expand Down
186 changes: 186 additions & 0 deletions src/Wippersnapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ Wippersnapper::Wippersnapper() {

// DallasSemi (OneWire)
WS._ds18x20Component = new ws_ds18x20();

// Display controller
WS._displayController = new DisplayController();
};

/**************************************************************************/
Expand Down Expand Up @@ -1655,6 +1658,124 @@ void cbSignalUARTReq(char *data, uint16_t len) {
WS_DEBUG_PRINTLN("ERROR: Unable to decode UART Signal message");
}

/*!
@brief Deserializes a DisplayRequest message and sends it to the display
component.
@param stream
Incoming data stream from buffer.
@param field
Protobuf message's tag type.
@param arg
Optional arguments from decoder calling function.
@returns True if decoded successfully, False otherwise.
*/
bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field,
void **arg) {
if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_add_tag) {

// Decode message into a DisplayAddRequest
wippersnapper_display_v1_DisplayAddOrReplace msgAddReq =
wippersnapper_display_v1_DisplayAddOrReplace_init_zero;
if (!ws_pb_decode(stream,
wippersnapper_display_v1_DisplayAddOrReplace_fields,
&msgAddReq)) {
WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayAddOrReplace message!");
return false;
}

// Attempt to add or replace a display component
bool did_add =
WS._displayController->Handle_Display_AddOrReplace(&msgAddReq);

// Create a DisplayResponse message
wippersnapper_signal_v1_DisplayResponse msgResp =
wippersnapper_signal_v1_DisplayResponse_init_zero;
msgResp.which_payload =
wippersnapper_signal_v1_DisplayResponse_display_added_tag;
msgResp.payload.display_added.did_add = did_add;
strncpy(msgResp.payload.display_added.name, msgAddReq.name,
sizeof(msgResp.payload.display_added.name));

// 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_DisplayResponse_fields,
&msgResp)) {
WS_DEBUG_PRINTLN("ERROR: Unable to encode display response message!");
return false;
}

size_t msgSz;
pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_DisplayResponse_fields,
&msgResp);
WS_DEBUG_PRINT("Publishing DisplayResponse Message...");
if (!WS._mqtt->publish(WS._topic_signal_display_device, WS._buffer_outgoing,
msgSz, 1)) {
WS_DEBUG_PRINTLN("ERROR: Failed to DisplayResponse Response!");
} else {
WS_DEBUG_PRINTLN("Published!");
}
} else if (field->tag ==
wippersnapper_signal_v1_DisplayRequest_display_write_tag) {
// Decode message into a DisplayAddRequest
wippersnapper_display_v1_DisplayWrite msgWrite =
wippersnapper_display_v1_DisplayWrite_init_zero;
if (!ws_pb_decode(stream, wippersnapper_display_v1_DisplayWrite_fields,
&msgWrite)) {
WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayWrite message!");
return false;
}
// Attempt to write to a display
WS._displayController->Handle_Display_Write(&msgWrite);
} else if (field->tag ==
wippersnapper_signal_v1_DisplayRequest_display_remove_tag) {
// Decode message into a DisplayRemoveRequest
wippersnapper_display_v1_DisplayRemove msgRemove =
wippersnapper_display_v1_DisplayRemove_init_zero;
if (!ws_pb_decode(stream, wippersnapper_display_v1_DisplayRemove_fields,
&msgRemove)) {
WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayRemove message!");
return false;
}
// Attempt to remove a display
WS._displayController->Handle_Display_Remove(&msgRemove);
} else {
WS_DEBUG_PRINTLN("ERROR: Display message type not found!");
return false;
}
return true;
}

/*!
@brief Called when the device receives a new message from the
/display/ topic.
@param data
Incoming data from MQTT broker.
@param len
Length of incoming data.
*/
void cbDisplayMessage(char *data, uint16_t len) {
WS_DEBUG_PRINTLN("* NEW MESSAGE [Topic: Display]: ");
WS_DEBUG_PRINT(len);
WS_DEBUG_PRINTLN(" bytes.");
// zero-out current buffer
memset(WS._buffer, 0, sizeof(WS._buffer));
// copy mqtt data into buffer
memcpy(WS._buffer, data, len);
WS.bufSize = len;

// Set up the payload callback, which will set up the callbacks for
// each oneof payload field once the field tag is known
WS.msgSignalDisplay.cb_payload.funcs.decode = cbDecodeDisplayMsg;

// Decode pixel message from buffer
pb_istream_t istream = pb_istream_from_buffer(WS._buffer, WS.bufSize);
if (!ws_pb_decode(&istream, wippersnapper_signal_v1_DisplayRequest_fields,
&WS.msgSignalDisplay))
WS_DEBUG_PRINTLN("ERROR: Unable to decode display message");
}

/****************************************************************************/
/*!
@brief Handles MQTT messages on signal topic until timeout.
Expand Down Expand Up @@ -2344,6 +2465,63 @@ bool Wippersnapper::generateWSTopics() {
WS_DEBUG_PRINTLN("FATAL ERROR: Failed to allocate memory for UART topic!");
return false;
}

// /display topic //

// Pre-determine topic size
topicLen = strlen(WS._config.aio_user) + strlen("/") + strlen(_device_uid) +
strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("broker") +
strlen(TOPIC_DISPLAY) + 1;

// Pre-allocate memory for topic
#ifdef USE_PSRAM
WS._topic_signal_display_brkr = (char *)ps_malloc(topicLen);
#else
WS._topic_signal_display_brkr = (char *)malloc(topicLen);
#endif

// Generate the topic
if (WS._topic_signal_display_brkr != NULL) {
snprintf(WS._topic_signal_display_brkr, topicLen, "%s/wprsnpr/%s%sbroker%s",
WS._config.aio_user, _device_uid, TOPIC_SIGNALS, TOPIC_DISPLAY);
} else {
WS_DEBUG_PRINTLN(
"FATAL ERROR: Failed to allocate memory for DISPLAY topic!");
return false;
}

// Subscribe to signal's DISPLAY sub-topic and set callback
_topic_signal_display_sub =
new Adafruit_MQTT_Subscribe(WS._mqtt, WS._topic_signal_display_brkr, 1);
WS_DEBUG_PRINTLN("Subscribing to DISPLAY topic: ");
WS_DEBUG_PRINTLN(WS._topic_signal_display_brkr);
WS._mqtt->subscribe(_topic_signal_display_sub);
WS_DEBUG_PRINTLN("Subscribed to DISPLAY topic!");
_topic_signal_display_sub->setCallback(cbDisplayMessage);

// Calculate length of the topic for device-to-broker DISPLAY topic
topicLen = strlen(WS._config.aio_user) + strlen("/") + strlen(_device_uid) +
strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("device") +
strlen(TOPIC_DISPLAY) + 1;

// Allocate memory for dynamic MQTT topic
#ifdef USE_PSRAM
WS._topic_signal_display_device = (char *)ps_malloc(topicLen);
#else
WS._topic_signal_display_device = (char *)malloc(topicLen);
#endif

// Generate the topic if memory was allocated successfully
if (WS._topic_signal_display_device != NULL) {
snprintf(WS._topic_signal_display_device, topicLen,
"%s/wprsnpr/%s%sdevice%s", WS._config.aio_user, _device_uid,
TOPIC_SIGNALS, TOPIC_DISPLAY);
} else {
WS_DEBUG_PRINTLN(
"FATAL ERROR: Failed to allocate memory for DISPLAY topic!");
return false;
}

return true;
}

Expand Down Expand Up @@ -2837,6 +3015,14 @@ void Wippersnapper::connect() {
WS._ui_helper->build_scr_monitor();
#endif

WS.pinCfgCompleted = true;

// Initialize Digital IO class
WS._digitalGPIO = new Wippersnapper_DigitalGPIO(20);
// Initialize Analog IO class
WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3);
WS._boardStatus = WS_BOARD_DEF_OK;

// Configure hardware
while (!WS.pinCfgCompleted) {
WS_DEBUG_PRINTLN(
Expand Down
16 changes: 15 additions & 1 deletion src/Wippersnapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
#include "display/ws_display_ui_helper.h"
#endif

#include "components/display/controller.h"
#include "components/ds18x20/ws_ds18x20.h"
#include "components/pixels/ws_pixels.h"
#include "components/pwm/ws_pwm.h"
Expand All @@ -142,7 +143,7 @@
#endif

#define WS_VERSION \
"1.0.0-beta.110" ///< WipperSnapper app. version (semver-formatted)
"1.0.0-beta.112" ///< WipperSnapper app. version (semver-formatted)

// Reserved Adafruit IO MQTT topics
#define TOPIC_IO_THROTTLE "/throttle" ///< Adafruit IO Throttle MQTT Topic
Expand All @@ -153,6 +154,7 @@
#define TOPIC_INFO "/info/" ///< Registration sub-topic
#define TOPIC_SIGNALS "/signals/" ///< Signals sub-topic
#define TOPIC_I2C "/i2c" ///< I2C sub-topic
#define TOPIC_DISPLAY "/display" ///< Display sub-topic (EPD, OLED, TFT, etc.)
#define MQTT_TOPIC_PIXELS_DEVICE \
"/signals/device/pixel" ///< Pixels device->broker topic
#define MQTT_TOPIC_PIXELS_BROKER \
Expand Down Expand Up @@ -245,6 +247,7 @@ class ws_pwm;
class ws_ds18x20;
class ws_pixels;
class ws_uart;
class DisplayController;

/**************************************************************************/
/*!
Expand Down Expand Up @@ -368,6 +371,8 @@ class Wippersnapper {
ws_servo *_servoComponent; ///< Instance of servo class
ws_ds18x20 *_ds18x20Component; ///< Instance of DS18x20 class
ws_uart *_uartComponent; ///< Instance of UART class
DisplayController
*_displayController; ///< Instance of display controller class

// TODO: does this really need to be global?
uint8_t _macAddr[6]; /*!< Unique network iface identifier */
Expand Down Expand Up @@ -404,6 +409,10 @@ class Wippersnapper {
char *_topic_signal_pixels_device = NULL; /*!< Topic carries pixel messages */
char *_topic_signal_uart_brkr = NULL; /*!< Topic carries UART messages */
char *_topic_signal_uart_device = NULL; /*!< Topic carries UART messages */
char *_topic_signal_display_brkr =
NULL; /*!< Topic carries messages from a device to a broker. */
char *_topic_signal_display_device =
NULL; /*!< Topic carries messages from a broker to a device. */

wippersnapper_signal_v1_CreateSignalRequest
_incomingSignalMsg; /*!< Incoming signal message from broker */
Expand All @@ -430,6 +439,9 @@ class Wippersnapper {
wippersnapper_signal_v1_UARTRequest
msgSignalUART; ///< UARTReq wrapper message

wippersnapper_signal_v1_DisplayRequest
msgSignalDisplay; ///< DisplayRequest wrapper message

char *throttleMessage; /*!< Pointer to throttle message data. */
int throttleTime; /*!< Total amount of time to throttle the device, in
milliseconds. */
Expand Down Expand Up @@ -490,6 +502,8 @@ class Wippersnapper {
*_topic_signal_pixels_sub; /*!< Subscribes to pixel device topic. */
Adafruit_MQTT_Subscribe
*_topic_signal_uart_sub; /*!< Subscribes to signal's UART topic. */
Adafruit_MQTT_Subscribe *_topic_signal_display_sub; /*!< Subscription callback
for display topic. */

Adafruit_MQTT_Subscribe
*_err_sub; /*!< Subscription to Adafruit IO Error topic. */
Expand Down
Loading
Loading