mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-07-29 16:37:17 +02:00
Better network mode representation
Handle wifi network reconnection if measurementCycleQueue empty, skip transmission Move agclient implementation on initializeNetwork function
This commit is contained in:
@ -97,8 +97,14 @@ static AgSerial *agSerial;
|
|||||||
static CellularModule *cell;
|
static CellularModule *cell;
|
||||||
static AirgradientClient *agClient;
|
static AirgradientClient *agClient;
|
||||||
|
|
||||||
|
enum NetworkOption {
|
||||||
|
UseWifi,
|
||||||
|
UseCellular
|
||||||
|
};
|
||||||
|
NetworkOption networkOption;
|
||||||
TaskHandle_t handleNetworkTask = NULL;
|
TaskHandle_t handleNetworkTask = NULL;
|
||||||
|
|
||||||
|
|
||||||
static uint32_t factoryBtnPressTime = 0;
|
static uint32_t factoryBtnPressTime = 0;
|
||||||
static AgFirmwareMode fwMode = FW_MODE_I_9PSL;
|
static AgFirmwareMode fwMode = FW_MODE_I_9PSL;
|
||||||
|
|
||||||
@ -109,7 +115,7 @@ SemaphoreHandle_t mutexMeasurementCycleQueue;
|
|||||||
static std::vector<Measurements::MeasurementCycle> measurementCycleQueue;
|
static std::vector<Measurements::MeasurementCycle> measurementCycleQueue;
|
||||||
|
|
||||||
static void boardInit(void);
|
static void boardInit(void);
|
||||||
static void initializeNetwork(bool useWifi);
|
static void initializeNetwork();
|
||||||
static void failedHandler(String msg);
|
static void failedHandler(String msg);
|
||||||
static void configurationUpdateSchedule(void);
|
static void configurationUpdateSchedule(void);
|
||||||
static void configUpdateHandle(void);
|
static void configUpdateHandle(void);
|
||||||
@ -194,33 +200,6 @@ void setup() {
|
|||||||
// Comment below line to disable debug measurement readings
|
// Comment below line to disable debug measurement readings
|
||||||
measurements.setDebug(false);
|
measurements.setDebug(false);
|
||||||
|
|
||||||
// Check if cellular module available
|
|
||||||
bool cellularFound = false;
|
|
||||||
agSerial = new AgSerial(Wire);
|
|
||||||
agSerial->init(GPIO_IIC_RESET);
|
|
||||||
if (agSerial->open()) {
|
|
||||||
Serial.println("Cellular module found");
|
|
||||||
// Initialize cellular module and use cellular as agClient
|
|
||||||
cell = new CellularModuleA7672XX(agSerial, GPIO_POWER_MODULE_PIN);
|
|
||||||
agClient = new AirgradientCellularClient(cell);
|
|
||||||
cellularFound = true;
|
|
||||||
|
|
||||||
//! NOTE: TMP
|
|
||||||
configuration.setOfflineModeWithoutSave(false);
|
|
||||||
} else {
|
|
||||||
Serial.println("Cellular module not available, using wifi");
|
|
||||||
delete agSerial;
|
|
||||||
agSerial = nullptr;
|
|
||||||
// Use wifi as agClient
|
|
||||||
agClient = new AirgradientWifiClient;
|
|
||||||
cellularFound = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!agClient->begin()) {
|
|
||||||
// TODO: Need to do retry when agclient already in other task
|
|
||||||
Serial.println("Failed start Airgradient Client FAILED");
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bool connectToWifi = false;
|
// bool connectToWifi = false;
|
||||||
bool connectToNetwork = true;
|
bool connectToNetwork = true;
|
||||||
@ -250,17 +229,17 @@ void setup() {
|
|||||||
connectToNetwork = !configuration.isOfflineMode();
|
connectToNetwork = !configuration.isOfflineMode();
|
||||||
} else {
|
} else {
|
||||||
configuration.setOfflineModeWithoutSave(true);
|
configuration.setOfflineModeWithoutSave(true);
|
||||||
|
connectToNetwork = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize networking configuration
|
// Initialize networking configuration
|
||||||
if (connectToNetwork) {
|
if (connectToNetwork) {
|
||||||
bool useWifi = !cellularFound;
|
initializeNetwork();
|
||||||
initializeNetwork(useWifi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set offline mode without saving, cause wifi is not configured */
|
/** Set offline mode without saving, cause wifi is not configured */
|
||||||
if (wifiConnector.hasConfigurated() == false && !cellularFound) {
|
if (wifiConnector.hasConfigurated() == false && networkOption == UseWifi) {
|
||||||
Serial.println("Set offline mode cause wifi is not configurated");
|
Serial.println("Set offline mode cause wifi is not configurated");
|
||||||
configuration.setOfflineModeWithoutSave(true);
|
configuration.setOfflineModeWithoutSave(true);
|
||||||
}
|
}
|
||||||
@ -276,6 +255,8 @@ void setup() {
|
|||||||
|
|
||||||
// Allocate queue memory to avoid always reallocation
|
// Allocate queue memory to avoid always reallocation
|
||||||
measurementCycleQueue.reserve(10);
|
measurementCycleQueue.reserve(10);
|
||||||
|
// Initialize mutex to access mesurementCycleQueue
|
||||||
|
mutexMeasurementCycleQueue = xSemaphoreCreateMutex();
|
||||||
|
|
||||||
BaseType_t xReturned =
|
BaseType_t xReturned =
|
||||||
xTaskCreate(networkingTask, "WD", 4096, null, 5, &handleNetworkTask);
|
xTaskCreate(networkingTask, "WD", 4096, null, 5, &handleNetworkTask);
|
||||||
@ -286,8 +267,13 @@ void setup() {
|
|||||||
// TODO: What to do here?
|
// TODO: What to do here?
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize mutex to access mesurementCycleQueue
|
// Log monitor mode for debugging purpose
|
||||||
mutexMeasurementCycleQueue = xSemaphoreCreateMutex();
|
if (configuration.isOfflineMode()) {
|
||||||
|
Serial.println("Running monitor in offline mode");
|
||||||
|
}
|
||||||
|
else if (configuration.isCloudConnectionDisabled()) {
|
||||||
|
Serial.println("Running monitor without connection to AirGradient server");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
@ -295,8 +281,13 @@ void loop() {
|
|||||||
dispLedSchedule.run();
|
dispLedSchedule.run();
|
||||||
// Schedule to feed external watchdog
|
// Schedule to feed external watchdog
|
||||||
watchdogFeedSchedule.run();
|
watchdogFeedSchedule.run();
|
||||||
// Schedule to take new measurement cycle
|
|
||||||
measurementSchedule.run();
|
// No need to run measurement cycle schedule when mode is offline or connection to AG disabled
|
||||||
|
if (configuration.isOfflineMode() == false ||
|
||||||
|
configuration.isCloudConnectionDisabled() == false) {
|
||||||
|
// Schedule to take new measurement cycle
|
||||||
|
measurementSchedule.run();
|
||||||
|
}
|
||||||
|
|
||||||
if (configuration.hasSensorS8) {
|
if (configuration.hasSensorS8) {
|
||||||
co2Schedule.run();
|
co2Schedule.run();
|
||||||
@ -897,8 +888,32 @@ static void failedHandler(String msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeNetwork(bool useWifi) {
|
void initializeNetwork() {
|
||||||
if (useWifi) {
|
// Check if cellular module available
|
||||||
|
agSerial = new AgSerial(Wire);
|
||||||
|
agSerial->init(GPIO_IIC_RESET);
|
||||||
|
if (agSerial->open()) {
|
||||||
|
Serial.println("Cellular module found");
|
||||||
|
// Initialize cellular module and use cellular as agClient
|
||||||
|
cell = new CellularModuleA7672XX(agSerial, GPIO_POWER_MODULE_PIN);
|
||||||
|
agClient = new AirgradientCellularClient(cell);
|
||||||
|
networkOption = UseCellular;
|
||||||
|
} else {
|
||||||
|
Serial.println("Cellular module not available, using wifi");
|
||||||
|
delete agSerial;
|
||||||
|
agSerial = nullptr;
|
||||||
|
// Use wifi as agClient
|
||||||
|
agClient = new AirgradientWifiClient;
|
||||||
|
networkOption = UseWifi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!agClient->begin()) {
|
||||||
|
// TODO: Need to do retry when agclient already in other task
|
||||||
|
Serial.println("Failed start Airgradient Client FAILED");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkOption == UseWifi) {
|
||||||
if (!wifiConnector.connect()) {
|
if (!wifiConnector.connect()) {
|
||||||
Serial.println("Cannot initiate wifi connection");
|
Serial.println("Cannot initiate wifi connection");
|
||||||
return;
|
return;
|
||||||
@ -928,6 +943,10 @@ void initializeNetwork(bool useWifi) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (networkOption == UseCellular) {
|
||||||
|
// TODO: check if cellular ready
|
||||||
|
// Display something on display if error, and ignore the rest of the function just like wifi
|
||||||
|
}
|
||||||
|
|
||||||
// Send data for the first time to AG server at boot
|
// Send data for the first time to AG server at boot
|
||||||
sendDataToAg();
|
sendDataToAg();
|
||||||
@ -962,10 +981,9 @@ void initializeNetwork(bool useWifi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void configurationUpdateSchedule(void) {
|
static void configurationUpdateSchedule(void) {
|
||||||
if (configuration.isOfflineMode() || configuration.isCloudConnectionDisabled() ||
|
if (configuration.getConfigurationControl() ==
|
||||||
configuration.getConfigurationControl() == ConfigurationControl::ConfigurationControlLocal) {
|
ConfigurationControl::ConfigurationControlLocal) {
|
||||||
Serial.println("Ignore fetch server configuration. Either mode is offline or cloud connection "
|
Serial.println("Ignore fetch server configuration, configurationControl set to local");
|
||||||
"disabled or configurationControl set to local");
|
|
||||||
agClient->resetFetchConfigurationStatus();
|
agClient->resetFetchConfigurationStatus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1251,27 +1269,30 @@ static void updatePm(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sendDataToServer(void) {
|
void sendDataToServer(void) {
|
||||||
if (configuration.isOfflineMode() || configuration.isCloudConnectionDisabled() ||
|
if (configuration.isPostDataToAirGradient() == false) {
|
||||||
!configuration.isPostDataToAirGradient()) {
|
Serial.println("Skipping transmission of data to AG server, post data to server disabled");
|
||||||
Serial.println("Skipping transmission of data to AG server. Either mode is offline or cloud connection is "
|
agClient->resetPostMeasuresStatus();
|
||||||
"disabled or post data to server disabled");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (wifiConnector.isConnected() == false) {
|
|
||||||
// Serial.println("WiFi not connected, skipping data transmission to AG server");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: Loop through measurementCycleQueue size
|
// TODO: Loop through measurementCycleQueue size
|
||||||
|
|
||||||
|
|
||||||
// Aquire queue mutex
|
// Aquire queue mutex
|
||||||
if (xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY) == pdFALSE) {
|
if (xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY) == pdFALSE) {
|
||||||
// Sanity check to just release mutex
|
// Sanity check to just release mutex
|
||||||
xSemaphoreGive(mutexMeasurementCycleQueue);
|
xSemaphoreGive(mutexMeasurementCycleQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure measurement cycle available
|
||||||
|
int queueSize = measurementCycleQueue.size();
|
||||||
|
if (queueSize == 0) {
|
||||||
|
Serial.println("Skipping transmission, measurementCycle empty");
|
||||||
|
xSemaphoreGive(mutexMeasurementCycleQueue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the oldest queue
|
// Get the oldest queue
|
||||||
auto mc = measurementCycleQueue.front();
|
auto mc = measurementCycleQueue.front();
|
||||||
|
|
||||||
@ -1290,7 +1311,6 @@ static void sendDataToServer(void) {
|
|||||||
xSemaphoreGive(mutexMeasurementCycleQueue);
|
xSemaphoreGive(mutexMeasurementCycleQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tempHumUpdate(void) {
|
static void tempHumUpdate(void) {
|
||||||
@ -1364,27 +1384,32 @@ int calculateMaxPeriod(int updateInterval) {
|
|||||||
|
|
||||||
void networkingTask(void *args) {
|
void networkingTask(void *args) {
|
||||||
while (1) {
|
while (1) {
|
||||||
// First check if offline mode or disableCloudConnection
|
|
||||||
// If yes, don't continue. Even, don't create the task, but only if offline mode don't create the task
|
|
||||||
// So in configSchedule and transmission schedule only check for if that feature is disabled
|
|
||||||
|
|
||||||
// Handle reconnection based on mode
|
// Handle reconnection based on mode
|
||||||
|
if (networkOption == UseWifi) {
|
||||||
/// Handle reconnection cellular here
|
wifiConnector.handle();
|
||||||
/// If failed fetch config or transmission it is an indication that the module might have a problem
|
if (wifiConnector.isConnected() == false) {
|
||||||
/// cellular-client or the cell module it self need an inteface for last operation success or not
|
// NOTE: If not connect while mode is not offline, skip the rest of code
|
||||||
/// For example, httpGet() failed, then there's a state like isLastOperationSuccess
|
delay(1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (networkOption == UseCellular) {
|
||||||
|
/// Handle reconnection cellular here
|
||||||
|
/// If failed fetch config or transmission it is an indication that the module might have a problem
|
||||||
|
/// cellular-client or the cell module it self need an inteface for last operation success or not
|
||||||
|
/// For example, httpGet() failed, then there's a state like isLastOperationSuccess
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle WiFi reconnection when disconnect
|
// If connection to AirGradient server disable don't run config and transmission schedule
|
||||||
// wifiConnector.handle();
|
if (configuration.isCloudConnectionDisabled()) {
|
||||||
// if (wifiConnector.isConnected() == false) {
|
delay(1000);
|
||||||
// // NOTE: If not connect while mode is not offline, skip the rest of code
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
// Run scheduler
|
||||||
configSchedule.run();
|
configSchedule.run();
|
||||||
transmissionSchedule.run();
|
transmissionSchedule.run();
|
||||||
|
|
||||||
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user