Skip to content

Commit

Permalink
Merge pull request #147 from adafruit/fix-reg-polling-2
Browse files Browse the repository at this point in the history
Registration workflow refactoring and bugfixes
  • Loading branch information
brentru authored Sep 7, 2021
2 parents a2c8634 + 52a7915 commit 6d0bb46
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 322 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ PROJECT_VER_MAJOR := 1
PROJECT_VER_MINOR := 0
PROJECT_VER_PATCH := 0
PROJECT_VER_BUILD := beta
PROJECT_VER_BUILD_NUM := 8
PROJECT_VER_BUILD_NUM := 9

BOARD_PYPORTAL := samd51-pyportal
BOARD_METRO_AIRLIFT := samd51-metro-airlift
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=Adafruit WipperSnapper
version=1.0.0-beta.8
version=1.0.0-beta.9
author=Adafruit
maintainer=Adafruit <[email protected]>
sentence=Arduino library to access WipperSnapper
Expand Down
6 changes: 6 additions & 0 deletions src/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"C_Cpp.dimInactiveRegions": false,
"files.associations": {
"__config": "cpp"
}
}
136 changes: 113 additions & 23 deletions src/Wippersnapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,14 @@ bool cbSignalMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) {
// decode each ConfigurePinRequest sub-message
if (!pb_decode(stream, wippersnapper_pin_v1_ConfigurePinRequests_fields,
&msg)) {
WS_DEBUG_PRINTLN("ERROR: Could not decode CreateSign2alRequest")
WS_DEBUG_PRINTLN("ERROR: Could not decode CreateSignalRequest")
is_success = false;
WS.pinCfgCompleted = false;
}
// If this is the initial configuration
if (!WS.pinCfgCompleted) {
WS_DEBUG_PRINTLN("Initial Pin Configuration Complete!");
WS.pinCfgCompleted = true;
}
} else if (field->tag ==
wippersnapper_signal_v1_CreateSignalRequest_pin_events_tag) {
Expand Down Expand Up @@ -503,11 +509,12 @@ bool Wippersnapper::encodePinEvent(
/**************************************************************************/
/*!
@brief Called when broker responds to a device's publish across
the registration topic.
the registration topic.
*/
/**************************************************************************/
void cbRegistrationStatus(char *data, uint16_t len) {
WS._registerBoard->decodeRegMsg(data, len);
// call decoder for registration response msg
WS.decodeRegistrationResp(data, len);
}

/**************************************************************************/
Expand Down Expand Up @@ -734,6 +741,18 @@ bool Wippersnapper::buildWSTopics() {
strlen(_device_uid) + strlen(TOPIC_DESCRIPTION) + strlen("status") +
strlen("broker") + 1);

// Registration status completion topic
WS._topic_description_status_complete = (char *)malloc(
sizeof(char) * strlen(WS._username) + +strlen("/wprsnpr/") +
strlen(_device_uid) + strlen(TOPIC_DESCRIPTION) + strlen("status") +
strlen("/device/complete") + 1);

// Topic to signal pin configuration complete from device to broker
WS._topic_device_pin_config_complete = (char *)malloc(
sizeof(char) * strlen(WS._username) + +strlen("/") + strlen(_device_uid) +
strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) +
strlen("device/pinConfigComplete") + 1);

// Topic for signals from device to broker
WS._topic_signal_device = (char *)malloc(
sizeof(char) * strlen(WS._username) + +strlen("/") + strlen(_device_uid) +
Expand Down Expand Up @@ -768,6 +787,19 @@ bool Wippersnapper::buildWSTopics() {
is_success = false;
}

// Create registration status complete topic
if (WS._topic_description_status_complete) {
strcpy(WS._topic_description_status_complete, WS._username);
strcat(WS._topic_description_status_complete, "/wprsnpr/");
strcat(WS._topic_description_status_complete, _device_uid);
strcat(WS._topic_description_status_complete, TOPIC_DESCRIPTION);
strcat(WS._topic_description_status_complete, "status");
strcat(WS._topic_description_status_complete, "/device/complete");
} else { // malloc failed
WS._topic_description_status_complete = 0;
is_success = false;
}

// Create device-to-broker signal topic
if (WS._topic_signal_device) {
strcpy(WS._topic_signal_device, WS._username);
Expand All @@ -780,6 +812,18 @@ bool Wippersnapper::buildWSTopics() {
is_success = false;
}

// Create device-to-broker signal topic
if (WS._topic_device_pin_config_complete) {
strcpy(WS._topic_device_pin_config_complete, WS._username);
strcat(WS._topic_device_pin_config_complete, "/wprsnpr/");
strcat(WS._topic_device_pin_config_complete, _device_uid);
strcat(WS._topic_device_pin_config_complete, TOPIC_SIGNALS);
strcat(WS._topic_device_pin_config_complete, "device/pinConfigComplete");
} else { // malloc failed
WS._topic_device_pin_config_complete = 0;
is_success = false;
}

// Create broker-to-device signal topic
if (WS._topic_signal_brkr) {
strcpy(WS._topic_signal_brkr, WS._username);
Expand Down Expand Up @@ -892,20 +936,27 @@ void Wippersnapper::haltError(String error) {

/**************************************************************************/
/*!
@brief Sends board description message to Wippersnapper
@param retries
Amount of times to retry registration process.
@brief Attempts to register hardware with Adafruit.io WipperSnapper.
@returns True if successful, False otherwise.
*/
/**************************************************************************/
bool Wippersnapper::registerBoard(uint8_t retries = 10) {
bool Wippersnapper::registerBoard() {
bool is_success = false;
WS_DEBUG_PRINTLN("registerBoard()");
// Create new board
_registerBoard = new Wippersnapper_Registration();
// Run the FSM for the registration process
is_success = _registerBoard->processRegistration();
return is_success;
WS_DEBUG_PRINTLN("Registering hardware with IO...");

// Encode and publish registration request message to broker
runNetFSM();
feedWDT();
WS_DEBUG_PRINT("Encoding registration request...");
if (!encodePubRegistrationReq())
return false;

// Blocking, attempt to obtain broker's response message
runNetFSM();
feedWDT();
pollRegistrationResp();

return true;
}

/**************************************************************************/
Expand Down Expand Up @@ -1034,17 +1085,60 @@ void Wippersnapper::connect() {
setStatusLEDColor(LED_CONNECTED);

// Register hardware with Wippersnapper
WS_DEBUG_PRINTLN("Registering Board...")
WS_DEBUG_PRINTLN("Registering hardware with WipperSnapper...")
setStatusLEDColor(LED_IO_REGISTER_HW);
if (!registerBoard(10)) {
haltError("Unable to register board with Wippersnapper.");

if (!registerBoard()) {
haltError("Unable to register with WipperSnapper.");
}
feedWDT(); // Hardware registered with IO, feed WDT
feedWDT(); // Hardware registered with IO, feed WDT */
WS_DEBUG_PRINTLN("Registered with WipperSnapper.");

WS_DEBUG_PRINTLN("Polling for configuration message...");
WS._mqtt->processPackets(2000);

// did we get and process the registration message?
if (!WS.pinCfgCompleted)
haltError("Did not get configuration message from broker, resetting...");

// Publish that we have completed the configuration workflow
feedWDT();
runNetFSM();
publishPinConfigComplete();

WS_DEBUG_PRINTLN("Registered board with Wippersnapper.");
// Run application
statusLEDBlink(WS_LED_STATUS_CONNECTED);
WS_DEBUG_PRINTLN(
"Registration and configuration complete!\nRunning application...");
}

WS._mqtt->processPackets(1000);
void Wippersnapper::publishPinConfigComplete() {
// Publish that we've set up the pins and are ready to run
wippersnapper_signal_v1_SignalResponse msg =
wippersnapper_signal_v1_SignalResponse_init_zero;
msg.which_payload =
wippersnapper_signal_v1_SignalResponse_configuration_complete_tag;
msg.payload.configuration_complete = true;

// encode registration request message
uint8_t _message_buffer[128];
pb_ostream_t _msg_stream =
pb_ostream_from_buffer(_message_buffer, sizeof(_message_buffer));

bool _status =
pb_encode(&_msg_stream,
wippersnapper_description_v1_RegistrationComplete_fields, &msg);
size_t _message_len = _msg_stream.bytes_written;

// verify message encoded correctly
if (!_status)
haltError("Could not encode, resetting...");

// Publish message
WS_DEBUG_PRINTLN("Publishing to pin config complete...");
WS.publish(WS._topic_device_pin_config_complete, _message_buffer,
_message_len, 1);
WS_DEBUG_PRINTLN("Completed registration process, configuration next!");
}

/**************************************************************************/
Expand All @@ -1055,12 +1149,8 @@ void Wippersnapper::connect() {
/**************************************************************************/
ws_status_t Wippersnapper::run() {
// Check networking
// TODO: Handle MQTT errors within the new netcode, or bring them outwards to
// another fsm
runNetFSM();
feedWDT();

// keepalive
pingBroker();

// Process all incoming packets from Wippersnapper MQTT Broker
Expand Down
30 changes: 18 additions & 12 deletions src/Wippersnapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

// Wippersnapper API Helpers
#include "Wippersnapper_Boards.h"
#include "Wippersnapper_Registration.h"
#include "components/statusLED/Wippersnapper_StatusLED_Colors.h"

// Wippersnapper GPIO Components
Expand All @@ -49,9 +48,10 @@
#include "Adafruit_SleepyDog.h"
#endif

// Uncomment to use the staging IO server staging builds
// #define IO_MQTT_SERVER "io.adafruit.us" ///< Adafruit IO MQTT Server
// (Staging)
// Uncomment the following use the staging IO server //
//#define USE_STAGING
//#define IO_MQTT_SERVER "io.adafruit.us" ///< Adafruit IO MQTT Server

#define IO_MQTT_SERVER \
"io.adafruit.com" ///< Adafruit IO MQTT Server (Production)

Expand All @@ -64,7 +64,7 @@
#endif

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

// Reserved Adafruit IO MQTT topics
#define TOPIC_IO_THROTTLE "/throttle" ///< Adafruit IO Throttle MQTT Topic
Expand Down Expand Up @@ -154,9 +154,8 @@ typedef enum {
4000 ///< Session keepalive interval time, in milliseconds

#define WS_MQTT_MAX_PAYLOAD_SIZE \
256 ///< MAXIMUM expected payload size, in bytes
300 ///< MAXIMUM expected payload size, in bytes

class Wippersnapper_Registration;
class Wippersnapper_DigitalGPIO;
class Wippersnapper_AnalogIO;
class Wippersnapper_FS;
Expand Down Expand Up @@ -207,8 +206,13 @@ class Wippersnapper {
bool buildErrorTopics();
void subscribeErrorTopics();

// Performs board registration FSM
bool registerBoard(uint8_t retries);
// Registration API
bool registerBoard();
bool encodePubRegistrationReq();
void decodeRegistrationResp(char *data, uint16_t len);
void pollRegistrationResp();
// Configuration API
void publishPinConfigComplete();

// run() loop
ws_status_t run();
Expand Down Expand Up @@ -249,8 +253,6 @@ class Wippersnapper {

ws_board_status_t _boardStatus; ///< Hardware's registration status

Wippersnapper_Registration *_registerBoard =
NULL; ///< Instance of registration class
Wippersnapper_DigitalGPIO *_digitalGPIO; ///< Instance of digital gpio class
Wippersnapper_AnalogIO *_analogIO; ///< Instance of analog io class
Wippersnapper_FS *_fileSystem; ///< Instance of filesystem class
Expand Down Expand Up @@ -280,6 +282,8 @@ class Wippersnapper {
wippersnapper_signal_v1_CreateSignalRequest
_incomingSignalMsg; /*!< Incoming signal message from broker */

bool pinCfgCompleted = false;

private:
void _init();

Expand All @@ -299,7 +303,9 @@ class Wippersnapper {
// MQTT topics
char *_topic_description_status; /*!< MQTT subtopic carrying the description
status resp. from the broker */
char *_topic_signal_brkr; /*!< Wprsnpr->Device messages */
char *_topic_description_status_complete;
char *_topic_device_pin_config_complete;
char *_topic_signal_brkr; /*!< Wprsnpr->Device messages */

Adafruit_MQTT_Subscribe
*_topic_description_sub; /*!< Subscription for registration topic. */
Expand Down
Loading

0 comments on commit 6d0bb46

Please sign in to comment.