Skip to content

Commit

Permalink
Rewrite LORAWAN Arduino Cloud driver for better clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
aentinger committed Jul 23, 2020
1 parent b33b5f9 commit 9121759
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 85 deletions.
28 changes: 0 additions & 28 deletions src/ArduinoIoTCloud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,38 +172,10 @@ Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, i
* PROTECTED MEMBER FUNCTIONS
******************************************************************************/

NetworkConnectionState ArduinoIoTCloudClass::checkPhyConnection()
{
NetworkConnectionState const connect_state = _connection->check();

if (_connection->check() != NetworkConnectionState::CONNECTED)
{
if (_iot_status == ArduinoIoTConnectionStatus::CONNECTED)
{
disconnect();
}
}

return connect_state;
}

void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const event)
{
OnCloudEventCallback callback = _cloud_event_callback[static_cast<size_t>(event)];
if (callback) {
(*callback)();
}
}

void ArduinoIoTCloudClass::printConnectionStatus(ArduinoIoTConnectionStatus status)
{
switch (status)
{
case ArduinoIoTConnectionStatus::IDLE: DBG_INFO ("Arduino IoT Cloud Connection status: IDLE"); break;
case ArduinoIoTConnectionStatus::ERROR: DBG_ERROR("Arduino IoT Cloud Connection status: ERROR"); break;
case ArduinoIoTConnectionStatus::CONNECTING: DBG_INFO ("Arduino IoT Cloud Connection status: CONNECTING"); break;
case ArduinoIoTConnectionStatus::RECONNECTING: DBG_INFO ("Arduino IoT Cloud Connection status: RECONNECTING"); break;
case ArduinoIoTConnectionStatus::CONNECTED: DBG_INFO ("Arduino IoT Cloud Connection status: CONNECTED"); break;
case ArduinoIoTConnectionStatus::DISCONNECTED: DBG_ERROR("Arduino IoT Cloud Connection status: DISCONNECTED"); break;
}
}
15 changes: 6 additions & 9 deletions src/ArduinoIoTCloud.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "property/types/CloudWrapperInt.h"
#include "property/types/CloudWrapperString.h"

#include "utility/time/TimeService.h"

/******************************************************************************
TYPEDEF
******************************************************************************/
Expand Down Expand Up @@ -91,6 +93,8 @@ class ArduinoIoTCloudClass

inline ConnectionHandler * getConnection() { return _connection; }

inline unsigned long getTime() { return _time_service.getTime(); }

void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback);

#define addProperty( v, ...) addPropertyReal(v, #v, __VA_ARGS__)
Expand Down Expand Up @@ -131,18 +135,11 @@ class ArduinoIoTCloudClass

protected:

virtual int connect () = 0;
virtual void disconnect() = 0;

inline ArduinoIoTConnectionStatus getIoTStatus() { return _iot_status; }

ConnectionHandler * _connection = nullptr;
PropertyContainer _property_container;
ArduinoIoTConnectionStatus _iot_status = ArduinoIoTConnectionStatus::IDLE;
TimeService _time_service;

NetworkConnectionState checkPhyConnection();
void execCloudEventCallback(ArduinoIoTCloudEvent const event);
static void printConnectionStatus(ArduinoIoTConnectionStatus status);
void execCloudEventCallback(ArduinoIoTCloudEvent const event);

private:

Expand Down
104 changes: 62 additions & 42 deletions src/ArduinoIoTCloudLPWAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,22 @@

static size_t const CBOR_LORA_MSG_MAX_SIZE = 255;

/******************************************************************************
LOCAL MODULE FUNCTIONS
******************************************************************************/

extern "C" unsigned long getTime()
{
return ArduinoCloud.getTime();
}

/******************************************************************************
CTOR/DTOR
******************************************************************************/

ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN()
: _retryEnable{false}
: _state{State::ConnectPhy}
, _retryEnable{false}
, _maxNumRetry{5}
, _intervalRetry{1000}
{
Expand All @@ -58,45 +68,21 @@ int ArduinoIoTCloudLPWAN::begin(ConnectionHandler& connection, bool retry)
{
_connection = &connection;
_retryEnable = retry;
_time_service.begin(nullptr);
return 1;
}

void ArduinoIoTCloudLPWAN::update()
{
// Check if a primitive property wrapper is locally changed
updateTimestampOnLocallyChangedProperties(_property_container);

ArduinoIoTConnectionStatus next_iot_status = _iot_status;

/* Since we do not have a direct connection to the Arduino IoT Cloud servers
* there is no such thing is a 'cloud connection state' since the LoRa
* board connection state to the gateway is all the information we have.
*/
NetworkConnectionState const net_con_state = checkPhyConnection();
if (net_con_state == NetworkConnectionState::CONNECTED) { next_iot_status = ArduinoIoTConnectionStatus::CONNECTED; execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); }
else if(net_con_state == NetworkConnectionState::CONNECTING) { next_iot_status = ArduinoIoTConnectionStatus::CONNECTING; }
else if(net_con_state == NetworkConnectionState::DISCONNECTED) { next_iot_status = ArduinoIoTConnectionStatus::DISCONNECTED; execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); }

if(next_iot_status != _iot_status)
/* Run through the state machine. */
State next_state = _state;
switch (_state)
{
printConnectionStatus(next_iot_status);
_iot_status = next_iot_status;
}

if(net_con_state != NetworkConnectionState::CONNECTED) return;

if (_connection->available()) {
uint8_t msgBuf[CBOR_LORA_MSG_MAX_SIZE];
uint8_t i = 0;
while (_connection->available()) {
msgBuf[i++] = _connection->read();
}

CBORDecoder::decode(_property_container, msgBuf, sizeof(msgBuf));
case State::ConnectPhy: next_state = handle_ConnectPhy(); break;
case State::SyncTime: next_state = handle_SyncTime(); break;
case State::Connected: next_state = handle_Connected(); break;
}

sendPropertiesToCloud();
execCloudEventCallback(ArduinoIoTCloudEvent::SYNC);
_state = next_state;
}

void ArduinoIoTCloudLPWAN::printDebugInfo()
Expand All @@ -106,23 +92,57 @@ void ArduinoIoTCloudLPWAN::printDebugInfo()
}

/******************************************************************************
* PROTECTED MEMBER FUNCTIONS
* PRIVATE MEMBER FUNCTIONS
******************************************************************************/

int ArduinoIoTCloudLPWAN::connect()
ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy()
{
_connection->connect();
return 1;
if (_connection->check() == NetworkConnectionState::CONNECTED)
return State::SyncTime;
else
return State::ConnectPhy;
}

void ArduinoIoTCloudLPWAN::disconnect()
ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime()
{
_connection->disconnect();
unsigned long const internal_posix_time = _time_service.getTime();
DBG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time);
return State::Connected;
}

/******************************************************************************
* PRIVATE MEMBER FUNCTIONS
******************************************************************************/
ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected()
{
if (!connected())
{
DBG_ERROR("ArduinoIoTCloudLPWAN::%s connection to gateway lost", __FUNCTION__);
return State::ConnectPhy;
}

/* Check if a primitive property wrapper is locally changed. */
updateTimestampOnLocallyChangedProperties(_property_container);

/* Decode available data. */
if (_connection->available())
decodePropertiesFromCloud();

/* If properties need updating sent them to the cloud. */
sendPropertiesToCloud();

return State::Connected;
}

void ArduinoIoTCloudLPWAN::decodePropertiesFromCloud()
{
uint8_t lora_msg_buf[CBOR_LORA_MSG_MAX_SIZE];
size_t bytes_received;
for (bytes_received = 0;
_connection->available() && (bytes_received < CBOR_LORA_MSG_MAX_SIZE);
bytes_received++)
{
lora_msg_buf[bytes_received] = _connection->read();
}
CBORDecoder::decode(_property_container, lora_msg_buf, bytes_received);
}

void ArduinoIoTCloudLPWAN::sendPropertiesToCloud()
{
Expand Down
19 changes: 13 additions & 6 deletions src/ArduinoIoTCloudLPWAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,25 @@ class ArduinoIoTCloudLPWAN : public ArduinoIoTCloudClass
inline void setIntervalRetry(long val) { _intervalRetry = val; }


protected:

virtual int connect () override;
virtual void disconnect () override;


private:

enum class State
{
ConnectPhy,
SyncTime,
Connected,
};

State _state;
bool _retryEnable;
int _maxNumRetry;
long _intervalRetry;

State handle_ConnectPhy();
State handle_SyncTime();
State handle_Connected();

void decodePropertiesFromCloud();
void sendPropertiesToCloud();
int writeProperties(const byte data[], int length);
};
Expand Down

0 comments on commit 9121759

Please sign in to comment.