mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-12-22 23:12:36 +01:00
First test
This commit is contained in:
@@ -87,6 +87,11 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
|
|||||||
#define I2C_SCL_PIN 6
|
#define I2C_SCL_PIN 6
|
||||||
#define OLED_I2C_ADDR 0x3C
|
#define OLED_I2C_ADDR 0x3C
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
|
||||||
|
static NimBLEServer *pServer;
|
||||||
|
|
||||||
/** Power pin */
|
/** Power pin */
|
||||||
#define GPIO_POWER_MODULE_PIN 5
|
#define GPIO_POWER_MODULE_PIN 5
|
||||||
#define GPIO_EXPANSION_CARD_POWER 4
|
#define GPIO_EXPANSION_CARD_POWER 4
|
||||||
@@ -100,21 +105,15 @@ static Configuration configuration(Serial);
|
|||||||
static Measurements measurements(configuration);
|
static Measurements measurements(configuration);
|
||||||
static AirGradient *ag;
|
static AirGradient *ag;
|
||||||
static OledDisplay oledDisplay(configuration, measurements, Serial);
|
static OledDisplay oledDisplay(configuration, measurements, Serial);
|
||||||
static StateMachine stateMachine(oledDisplay, Serial, measurements,
|
static StateMachine stateMachine(oledDisplay, Serial, measurements, configuration);
|
||||||
configuration);
|
static WifiConnector wifiConnector(oledDisplay, Serial, stateMachine, configuration);
|
||||||
static WifiConnector wifiConnector(oledDisplay, Serial, stateMachine,
|
|
||||||
configuration);
|
|
||||||
static OpenMetrics openMetrics(measurements, configuration, wifiConnector);
|
static OpenMetrics openMetrics(measurements, configuration, wifiConnector);
|
||||||
static LocalServer localServer(Serial, openMetrics, measurements, configuration,
|
static LocalServer localServer(Serial, openMetrics, measurements, configuration, wifiConnector);
|
||||||
wifiConnector);
|
|
||||||
static AgSerial *agSerial;
|
static AgSerial *agSerial;
|
||||||
static CellularModule *cellularCard;
|
static CellularModule *cellularCard;
|
||||||
static AirgradientClient *agClient;
|
static AirgradientClient *agClient;
|
||||||
|
|
||||||
enum NetworkOption {
|
enum NetworkOption { UseWifi, UseCellular };
|
||||||
UseWifi,
|
|
||||||
UseCellular
|
|
||||||
};
|
|
||||||
NetworkOption networkOption;
|
NetworkOption networkOption;
|
||||||
TaskHandle_t handleNetworkTask = NULL;
|
TaskHandle_t handleNetworkTask = NULL;
|
||||||
static bool firmwareUpdateInProgress = false;
|
static bool firmwareUpdateInProgress = false;
|
||||||
@@ -162,8 +161,7 @@ static void networkSignalCheck();
|
|||||||
static void networkingTask(void *args);
|
static void networkingTask(void *args);
|
||||||
|
|
||||||
AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, updateDisplayAndLedBar);
|
AgSchedule dispLedSchedule(DISP_UPDATE_INTERVAL, updateDisplayAndLedBar);
|
||||||
AgSchedule configSchedule(WIFI_SERVER_CONFIG_SYNC_INTERVAL,
|
AgSchedule configSchedule(WIFI_SERVER_CONFIG_SYNC_INTERVAL, configurationUpdateSchedule);
|
||||||
configurationUpdateSchedule);
|
|
||||||
AgSchedule transmissionSchedule(WIFI_TRANSMISSION_INTERVAL, sendDataToServer);
|
AgSchedule transmissionSchedule(WIFI_TRANSMISSION_INTERVAL, sendDataToServer);
|
||||||
AgSchedule measurementSchedule(WIFI_MEASUREMENT_INTERVAL, newMeasurementCycle);
|
AgSchedule measurementSchedule(WIFI_MEASUREMENT_INTERVAL, newMeasurementCycle);
|
||||||
AgSchedule co2Schedule(SENSOR_CO2_UPDATE_INTERVAL, co2Update);
|
AgSchedule co2Schedule(SENSOR_CO2_UPDATE_INTERVAL, co2Update);
|
||||||
@@ -175,6 +173,8 @@ AgSchedule checkForUpdateSchedule(FIRMWARE_CHECK_FOR_UPDATE_MS, checkForFirmware
|
|||||||
AgSchedule networkSignalCheckSchedule(10000, networkSignalCheck);
|
AgSchedule networkSignalCheckSchedule(10000, networkSignalCheck);
|
||||||
AgSchedule printMeasurementsSchedule(6000, printMeasurements);
|
AgSchedule printMeasurementsSchedule(6000, printMeasurements);
|
||||||
|
|
||||||
|
static void setupBLE();
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
/** Serial for print debug message */
|
/** Serial for print debug message */
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
@@ -221,21 +221,24 @@ void setup() {
|
|||||||
boardInit();
|
boardInit();
|
||||||
setMeasurementMaxPeriod();
|
setMeasurementMaxPeriod();
|
||||||
|
|
||||||
|
setupBLE();
|
||||||
|
oledDisplay.setText("BT", "ON", "");
|
||||||
|
Serial.println("Bluetooth server ready");
|
||||||
|
while(1) {delay(100);}
|
||||||
|
|
||||||
bool connectToNetwork = true;
|
bool connectToNetwork = true;
|
||||||
if (ag->isOne()) { // Offline mode only available for indoor monitor
|
if (ag->isOne()) { // Offline mode only available for indoor monitor
|
||||||
/** Show message confirm offline mode, should me perform if LED bar button
|
/** Show message confirm offline mode, should me perform if LED bar button
|
||||||
* test pressed */
|
* test pressed */
|
||||||
if (ledBarButtonTest == false) {
|
if (ledBarButtonTest == false) {
|
||||||
oledDisplay.setText(
|
oledDisplay.setText("Press now for",
|
||||||
"Press now for",
|
|
||||||
configuration.isOfflineMode() ? "online mode" : "offline mode", "");
|
configuration.isOfflineMode() ? "online mode" : "offline mode", "");
|
||||||
uint32_t startTime = millis();
|
uint32_t startTime = millis();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (ag->button.getState() == ag->button.BUTTON_PRESSED) {
|
if (ag->button.getState() == ag->button.BUTTON_PRESSED) {
|
||||||
configuration.setOfflineMode(!configuration.isOfflineMode());
|
configuration.setOfflineMode(!configuration.isOfflineMode());
|
||||||
|
|
||||||
oledDisplay.setText(
|
oledDisplay.setText("Offline Mode",
|
||||||
"Offline Mode",
|
|
||||||
configuration.isOfflineMode() ? " = True" : " = False", "");
|
configuration.isOfflineMode() ? " = True" : " = False", "");
|
||||||
delay(1000);
|
delay(1000);
|
||||||
break;
|
break;
|
||||||
@@ -274,7 +277,6 @@ void setup() {
|
|||||||
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (networkOption == UseCellular) {
|
if (networkOption == UseCellular) {
|
||||||
// If using cellular re-set scheduler interval
|
// If using cellular re-set scheduler interval
|
||||||
configSchedule.setPeriod(CELLULAR_SERVER_CONFIG_SYNC_INTERVAL);
|
configSchedule.setPeriod(CELLULAR_SERVER_CONFIG_SYNC_INTERVAL);
|
||||||
@@ -302,11 +304,9 @@ void setup() {
|
|||||||
// Log monitor mode for debugging purpose
|
// Log monitor mode for debugging purpose
|
||||||
if (configuration.isOfflineMode()) {
|
if (configuration.isOfflineMode()) {
|
||||||
Serial.println("Running monitor in offline mode");
|
Serial.println("Running monitor in offline mode");
|
||||||
}
|
} else if (configuration.isCloudConnectionDisabled()) {
|
||||||
else if (configuration.isCloudConnectionDisabled()) {
|
|
||||||
Serial.println("Running monitor without connection to AirGradient server");
|
Serial.println("Running monitor without connection to AirGradient server");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
@@ -353,7 +353,7 @@ void loop() {
|
|||||||
static bool pmsConnected = false;
|
static bool pmsConnected = false;
|
||||||
if (pmsConnected != ag->pms5003.connected()) {
|
if (pmsConnected != ag->pms5003.connected()) {
|
||||||
pmsConnected = ag->pms5003.connected();
|
pmsConnected = ag->pms5003.connected();
|
||||||
Serial.printf("PMS sensor %s \n", pmsConnected?"connected":"removed");
|
Serial.printf("PMS sensor %s \n", pmsConnected ? "connected" : "removed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -392,9 +392,7 @@ static void co2Update(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printMeasurements() {
|
void printMeasurements() { measurements.printCurrentAverage(); }
|
||||||
measurements.printCurrentAverage();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mdnsInit(void) {
|
static void mdnsInit(void) {
|
||||||
if (!MDNS.begin(localServer.getHostname().c_str())) {
|
if (!MDNS.begin(localServer.getHostname().c_str())) {
|
||||||
@@ -403,8 +401,7 @@ static void mdnsInit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MDNS.addService("_airgradient", "_tcp", 80);
|
MDNS.addService("_airgradient", "_tcp", 80);
|
||||||
MDNS.addServiceTxt("_airgradient", "_tcp", "model",
|
MDNS.addServiceTxt("_airgradient", "_tcp", "model", AgFirmwareModeName(fwMode));
|
||||||
AgFirmwareModeName(fwMode));
|
|
||||||
MDNS.addServiceTxt("_airgradient", "_tcp", "serialno", ag->deviceId());
|
MDNS.addServiceTxt("_airgradient", "_tcp", "serialno", ag->deviceId());
|
||||||
MDNS.addServiceTxt("_airgradient", "_tcp", "fw_ver", ag->getVersion());
|
MDNS.addServiceTxt("_airgradient", "_tcp", "fw_ver", ag->getVersion());
|
||||||
MDNS.addServiceTxt("_airgradient", "_tcp", "vendor", "AirGradient");
|
MDNS.addServiceTxt("_airgradient", "_tcp", "vendor", "AirGradient");
|
||||||
@@ -428,8 +425,7 @@ static void createMqttTask(void) {
|
|||||||
String payload = measurements.toString(true, fwMode, wifiConnector.RSSI());
|
String payload = measurements.toString(true, fwMode, wifiConnector.RSSI());
|
||||||
String topic = "airgradient/readings/" + ag->deviceId();
|
String topic = "airgradient/readings/" + ag->deviceId();
|
||||||
|
|
||||||
if (mqttClient.publish(topic.c_str(), payload.c_str(),
|
if (mqttClient.publish(topic.c_str(), payload.c_str(), payload.length())) {
|
||||||
payload.length())) {
|
|
||||||
Serial.println("MQTT sync success");
|
Serial.println("MQTT sync success");
|
||||||
} else {
|
} else {
|
||||||
Serial.println("MQTT sync failure");
|
Serial.println("MQTT sync failure");
|
||||||
@@ -447,8 +443,7 @@ static void createMqttTask(void) {
|
|||||||
static void initMqtt(void) {
|
static void initMqtt(void) {
|
||||||
String mqttUri = configuration.getMqttBrokerUri();
|
String mqttUri = configuration.getMqttBrokerUri();
|
||||||
if (mqttUri.isEmpty()) {
|
if (mqttUri.isEmpty()) {
|
||||||
Serial.println(
|
Serial.println("MQTT is not configured, skipping initialization of MQTT client");
|
||||||
"MQTT is not configured, skipping initialization of MQTT client");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +504,7 @@ static void factoryConfigReset(void) {
|
|||||||
Serial.println("Factory reset successful");
|
Serial.println("Factory reset successful");
|
||||||
}
|
}
|
||||||
delay(3000);
|
delay(3000);
|
||||||
oledDisplay.setText("","","");
|
oledDisplay.setText("", "", "");
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,8 +709,7 @@ static void sendDataToAg() {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
// ledSmHandler();
|
// ledSmHandler();
|
||||||
stateMachine.handleLeds();
|
stateMachine.handleLeds();
|
||||||
if (stateMachine.getLedState() !=
|
if (stateMachine.getLedState() != AgStateMachineWiFiOkServerConnecting) {
|
||||||
AgStateMachineWiFiOkServerConnecting) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delay(LED_BAR_ANIMATION_PERIOD);
|
delay(LED_BAR_ANIMATION_PERIOD);
|
||||||
@@ -761,8 +755,7 @@ static void oneIndoorInit(void) {
|
|||||||
/** Show boot display */
|
/** Show boot display */
|
||||||
Serial.println("Firmware Version: " + ag->getVersion());
|
Serial.println("Firmware Version: " + ag->getVersion());
|
||||||
|
|
||||||
oledDisplay.setText("AirGradient ONE",
|
oledDisplay.setText("AirGradient ONE", "FW Version: ", ag->getVersion().c_str());
|
||||||
"FW Version: ", ag->getVersion().c_str());
|
|
||||||
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
||||||
|
|
||||||
ag->ledBar.begin();
|
ag->ledBar.begin();
|
||||||
@@ -793,9 +786,9 @@ static void oneIndoorInit(void) {
|
|||||||
WiFi.begin("airgradient", "cleanair");
|
WiFi.begin("airgradient", "cleanair");
|
||||||
oledDisplay.setText("Configure WiFi", "connect to", "\'airgradient\'");
|
oledDisplay.setText("Configure WiFi", "connect to", "\'airgradient\'");
|
||||||
delay(2500);
|
delay(2500);
|
||||||
oledDisplay.setText("Rebooting...", "","");
|
oledDisplay.setText("Rebooting...", "", "");
|
||||||
delay(2500);
|
delay(2500);
|
||||||
oledDisplay.setText("","","");
|
oledDisplay.setText("", "", "");
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -921,8 +914,7 @@ static void openAirInit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fwMode == FW_MODE_O_1PP) {
|
if (fwMode == FW_MODE_O_1PP) {
|
||||||
int count = (configuration.hasSensorPMS1 ? 1 : 0) +
|
int count = (configuration.hasSensorPMS1 ? 1 : 0) + (configuration.hasSensorPMS2 ? 1 : 0);
|
||||||
(configuration.hasSensorPMS2 ? 1 : 0);
|
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
fwMode = FW_MODE_O_1P;
|
fwMode = FW_MODE_O_1P;
|
||||||
}
|
}
|
||||||
@@ -1070,15 +1062,13 @@ void initializeNetwork() {
|
|||||||
}
|
}
|
||||||
stateMachine.handleLeds(AgStateMachineWiFiOkServerOkSensorConfigFailed);
|
stateMachine.handleLeds(AgStateMachineWiFiOkServerOkSensorConfigFailed);
|
||||||
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
delay(DISPLAY_DELAY_SHOW_CONTENT_MS);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
ledBarEnabledUpdate();
|
ledBarEnabledUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void configurationUpdateSchedule(void) {
|
static void configurationUpdateSchedule(void) {
|
||||||
if (configuration.getConfigurationControl() ==
|
if (configuration.getConfigurationControl() == ConfigurationControl::ConfigurationControlLocal) {
|
||||||
ConfigurationControl::ConfigurationControlLocal) {
|
|
||||||
Serial.println("Ignore fetch server configuration, configurationControl set to local");
|
Serial.println("Ignore fetch server configuration, configurationControl set to local");
|
||||||
agClient->resetFetchConfigurationStatus();
|
agClient->resetFetchConfigurationStatus();
|
||||||
return;
|
return;
|
||||||
@@ -1112,8 +1102,7 @@ static void configUpdateHandle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (configuration.hasSensorSGP) {
|
if (configuration.hasSensorSGP) {
|
||||||
if (configuration.noxLearnOffsetChanged() ||
|
if (configuration.noxLearnOffsetChanged() || configuration.tvocLearnOffsetChanged()) {
|
||||||
configuration.tvocLearnOffsetChanged()) {
|
|
||||||
ag->sgp41.end();
|
ag->sgp41.end();
|
||||||
|
|
||||||
int oldTvocOffset = ag->sgp41.getTvocLearningOffset();
|
int oldTvocOffset = ag->sgp41.getTvocLearningOffset();
|
||||||
@@ -1124,14 +1113,12 @@ static void configUpdateHandle() {
|
|||||||
resultStr = "failure";
|
resultStr = "failure";
|
||||||
}
|
}
|
||||||
if (oldTvocOffset != configuration.getTvocLearningOffset()) {
|
if (oldTvocOffset != configuration.getTvocLearningOffset()) {
|
||||||
Serial.printf("Setting tvocLearningOffset from %d to %d hours %s\r\n",
|
Serial.printf("Setting tvocLearningOffset from %d to %d hours %s\r\n", oldTvocOffset,
|
||||||
oldTvocOffset, configuration.getTvocLearningOffset(),
|
configuration.getTvocLearningOffset(), resultStr);
|
||||||
resultStr);
|
|
||||||
}
|
}
|
||||||
if (oldNoxOffset != configuration.getNoxLearningOffset()) {
|
if (oldNoxOffset != configuration.getNoxLearningOffset()) {
|
||||||
Serial.printf("Setting noxLearningOffset from %d to %d hours %s\r\n",
|
Serial.printf("Setting noxLearningOffset from %d to %d hours %s\r\n", oldNoxOffset,
|
||||||
oldNoxOffset, configuration.getNoxLearningOffset(),
|
configuration.getNoxLearningOffset(), resultStr);
|
||||||
resultStr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1153,7 +1140,7 @@ static void configUpdateHandle() {
|
|||||||
if (configuration.getLedBarBrightness() == 0) {
|
if (configuration.getLedBarBrightness() == 0) {
|
||||||
ag->ledBar.setEnable(false);
|
ag->ledBar.setEnable(false);
|
||||||
} else {
|
} else {
|
||||||
if(configuration.getLedBarMode() == LedBarMode::LedBarModeOff) {
|
if (configuration.getLedBarMode() == LedBarMode::LedBarModeOff) {
|
||||||
ag->ledBar.setEnable(false);
|
ag->ledBar.setEnable(false);
|
||||||
} else {
|
} else {
|
||||||
ag->ledBar.setEnable(true);
|
ag->ledBar.setEnable(true);
|
||||||
@@ -1191,8 +1178,7 @@ static void updateDisplayAndLedBar(void) {
|
|||||||
stateMachine.handleLeds(AgStateMachineWiFiLost);
|
stateMachine.handleLeds(AgStateMachineWiFiLost);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else if (networkOption == UseCellular) {
|
||||||
else if (networkOption == UseCellular) {
|
|
||||||
if (agClient->isClientReady() == false) {
|
if (agClient->isClientReady() == false) {
|
||||||
// Same action as wifi
|
// Same action as wifi
|
||||||
stateMachine.displayHandle(AgStateMachineWiFiLost);
|
stateMachine.displayHandle(AgStateMachineWiFiLost);
|
||||||
@@ -1390,8 +1376,8 @@ void postUsingWifi() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* forcePost to force post without checking transmit cycle
|
* forcePost to force post without checking transmit cycle
|
||||||
*/
|
*/
|
||||||
void postUsingCellular(bool forcePost) {
|
void postUsingCellular(bool forcePost) {
|
||||||
// Aquire queue mutex to get queue size
|
// Aquire queue mutex to get queue size
|
||||||
xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY);
|
xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY);
|
||||||
@@ -1531,7 +1517,6 @@ int calculateMaxPeriod(int updateInterval) {
|
|||||||
return (WIFI_MEASUREMENT_INTERVAL - (WIFI_MEASUREMENT_INTERVAL * 0.8)) / updateInterval;
|
return (WIFI_MEASUREMENT_INTERVAL - (WIFI_MEASUREMENT_INTERVAL * 0.8)) / updateInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void networkSignalCheck() {
|
void networkSignalCheck() {
|
||||||
if (networkOption == UseWifi) {
|
if (networkOption == UseWifi) {
|
||||||
Serial.printf("WiFi RSSI %d\n", wifiConnector.RSSI());
|
Serial.printf("WiFi RSSI %d\n", wifiConnector.RSSI());
|
||||||
@@ -1557,12 +1542,11 @@ void networkSignalCheck() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If in 2 hours cellular client still not ready, then restart system
|
* If in 2 hours cellular client still not ready, then restart system
|
||||||
*/
|
*/
|
||||||
void restartIfCeClientIssueOverTwoHours() {
|
void restartIfCeClientIssueOverTwoHours() {
|
||||||
if (agCeClientProblemDetectedTime > 0 &&
|
if (agCeClientProblemDetectedTime > 0 &&
|
||||||
(MINUTES() - agCeClientProblemDetectedTime) >
|
(MINUTES() - agCeClientProblemDetectedTime) > TIMEOUT_WAIT_FOR_CELLULAR_MODULE_READY) {
|
||||||
TIMEOUT_WAIT_FOR_CELLULAR_MODULE_READY) {
|
|
||||||
// Give up wait
|
// Give up wait
|
||||||
Serial.println("Rebooting because CE client issues for 2 hours detected");
|
Serial.println("Rebooting because CE client issues for 2 hours detected");
|
||||||
int i = 3;
|
int i = 3;
|
||||||
@@ -1613,8 +1597,7 @@ void networkingTask(void *args) {
|
|||||||
delay(1000);
|
delay(1000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
} else if (networkOption == UseCellular) {
|
||||||
else if (networkOption == UseCellular) {
|
|
||||||
if (agClient->isClientReady() == false) {
|
if (agClient->isClientReady() == false) {
|
||||||
// Start time if value still default
|
// Start time if value still default
|
||||||
if (agCeClientProblemDetectedTime == 0) {
|
if (agCeClientProblemDetectedTime == 0) {
|
||||||
@@ -1695,3 +1678,62 @@ void newMeasurementCycle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ServerCallbacks : public NimBLEServerCallbacks {
|
||||||
|
void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override {
|
||||||
|
Serial.printf("Client address: %s\n", connInfo.getAddress().toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override {
|
||||||
|
Serial.printf("Client disconnected - start advertising\n");
|
||||||
|
NimBLEDevice::startAdvertising();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onAuthenticationComplete(NimBLEConnInfo &connInfo) override {
|
||||||
|
Serial.println("\n========== PAIRING COMPLETE ==========");
|
||||||
|
Serial.printf("Peer Address: %s\n", connInfo.getAddress().toString().c_str());
|
||||||
|
|
||||||
|
Serial.printf("Encrypted: %s\n", connInfo.isEncrypted() ? "YES" : "NO");
|
||||||
|
Serial.printf("Authenticated: %s\n", connInfo.isAuthenticated() ? "YES" : "NO");
|
||||||
|
Serial.printf("Key Size: %d bits\n", connInfo.getSecKeySize() * 8);
|
||||||
|
|
||||||
|
Serial.println("======================================\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Handler class for characteristic actions */
|
||||||
|
class CharacteristicCallbacks : public NimBLECharacteristicCallbacks {
|
||||||
|
void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override {
|
||||||
|
Serial.printf("%s : onRead(), value: %s\n", pCharacteristic->getUUID().toString().c_str(),
|
||||||
|
pCharacteristic->getValue().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override {
|
||||||
|
Serial.printf("%s : onWrite(), value: %s\n", pCharacteristic->getUUID().toString().c_str(),
|
||||||
|
pCharacteristic->getValue().c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setupBLE() {
|
||||||
|
NimBLEDevice::init("AirGradient");
|
||||||
|
NimBLEDevice::setPower(3); /** +3db */
|
||||||
|
|
||||||
|
/** bonding, MITM, don't need BLE secure connections as we are using passkey pairing */
|
||||||
|
NimBLEDevice::setSecurityAuth(false, false, true);
|
||||||
|
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_NO_INPUT_OUTPUT);
|
||||||
|
|
||||||
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
|
pServer->setCallbacks(new ServerCallbacks());
|
||||||
|
|
||||||
|
NimBLEService *pService = pServer->createService("acbcfea8-e541-4c40-9bfd-17820f16c95c");
|
||||||
|
NimBLECharacteristic *pSecureCharacteristic =
|
||||||
|
pService->createCharacteristic("703fa252-3d2a-4da9-a05c-83b0d9cacb8e",
|
||||||
|
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC |
|
||||||
|
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_ENC);
|
||||||
|
pSecureCharacteristic->setCallbacks(new CharacteristicCallbacks());
|
||||||
|
|
||||||
|
pService->start();
|
||||||
|
|
||||||
|
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
|
pAdvertising->addServiceUUID(pService->getUUID());
|
||||||
|
pAdvertising->start();
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ lib_deps =
|
|||||||
WiFiClientSecure
|
WiFiClientSecure
|
||||||
Update
|
Update
|
||||||
DNSServer
|
DNSServer
|
||||||
|
h2zero/NimBLE-Arduino@^2.1.0
|
||||||
|
|
||||||
[env:esp8266]
|
[env:esp8266]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
|
|||||||
Reference in New Issue
Block a user