Skip to content

Commit

Permalink
Merge pull request #1 from Heisenberg2980/Add-Wifi-and-OTA
Browse files Browse the repository at this point in the history
Add wifi and ota
  • Loading branch information
heisenberg2980 authored Jul 13, 2022
2 parents c2e5fce + 6d9f1c9 commit 6398210
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
Settings.h
Settings.h
platformio.ini
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"*.tcc": "cpp"
}
}
7 changes: 7 additions & 0 deletions partitions_singleapp.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1E0000,
app1, app, ota_1, 0x1F0000,0x1E0000,
eeprom, data, 0x99, 0x3F0000,0x1000,
spiffs, data, spiffs, 0x3F1000,0xF000,
6 changes: 6 additions & 0 deletions partitions_singleapp2.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1E0000,
app1, app, ota_1, 0x1F0000, 0x1E0000,
spiffs, data, spiffs, 0x3D0000, 0x30000,
20 changes: 18 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,25 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:nodemcu-32s]
[env:esp32]
platform = espressif32
board = nodemcu-32s
framework = arduino
lib_deps = t-vk/ESP32 BLE Mouse@^0.3.1
lib_deps =
# t-vk/ESP32 BLE Mouse@^0.3.1
# h2zero/esp-nimble-cpp@^1.3.3
# https://github.com/h2zero/esp-nimble-cpp.git #master
# wakwak-koba/ESP32-NimBLE-Mouse@^0.3.1
# https://github.com/wakwak-koba/ESP32-NimBLE-Mouse.git #master
# Heisenberg2980/ESP32-NimBLE-Mouse@^0.3.0
https://github.com/Heisenberg2980/ESP32-NimBLE-Mouse.git#v0.3.2
h2zero/NimBLE-Arduino@^1.4.0
AsyncMqttClient@^0.8.2
ArduinoJson@^6
AsyncTCP
lib_ignore = ESPAsyncTCP
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
#upload_protocol = espota
#upload_port = 192.168.0.128
#upload_flags = -p 8266
42 changes: 42 additions & 0 deletions src/Settings-rename.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//Replace with the name of the mouse
#define deviceName "my BT mouse"
#define deviceNameNoSpaces "my_BT_mouse"

//Replace with the room name where the node will be placed; example: #define room "living-room"
#define room "living-room"



//Replace with your Wifi SSID; example: #define ssid "MyWifi"
#define ssid "MyWifi"


//Replace with your Wifi password; example: #define password "12345678"
#define password "12345678"

//Replace with a human-friendly host name. Must not contain spaces or special characters and be unique on your network
#define hostname "esp32_unicorn_mouse_" room

//Replace with your MQTT Broker address; example: #define mqttHost IPAddress(192, 168, 1, 195)
#define mqttHost IPAddress(192, 168, 1, 195)

//Replace with your MQTT Broker port; example: #define mqttPort 1883
#define mqttPort 1883

//Replace with your MQTT Broker user; example: #define mqttUser "homeassistant"
#define mqttUser "mqtt_user"

//Replace with your MQTT Broker password; example: #define mqttPassword "12345678"
#define mqttPassword "mqtt_password"

// Logic level for turning the led on. Most boards use active low, meaning LED_ON should be set to 0
#define LED_ON 0

//Define the topic for publishing availability
#define availabilityTopic "mouse_nodes/" room

//Define the topic for publishing JSON attributes
#define telemetryTopic "mouse_nodes/tele/" room

//Define the base topic for room detection. Usually "room_presence"
#define channel availabilityTopic deviceNameNoSpaces
250 changes: 249 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,271 @@
/**
* This example turns the ESP32 into a Bluetooth LE mouse that continuously moves the mouse.
*/
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"

#include <BleMouse.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <AsyncMqttClient.h>
#include <ArduinoJson.h>
#include <ArduinoOTA.h>
#include "Settings.h"

#define LED_GPIO LED_BUILTIN

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
bool updateInProgress = false;
String localIp;
byte retryAttemptsWifi = 0;
byte retryAttemptsMqtt = 0;

//BleMouse bleMouse;
BleMouse bleMouse("Unicorn mouse", "Unicorn enterprise", 100);
BleMouse bleMouse(deviceName " " room, deviceName " enterprise", 100);

bool sendTelemetry(int ble_connected = -1) {
StaticJsonDocument<256> tele;
tele["room"] = room;
tele["ip"] = localIp;
tele["hostname"] = WiFi.getHostname();

if (ble_connected > -1) {
Serial.printf("connected: %d\n\r",ble_connected);
tele["BLE_connected"] = ble_connected;
}

char teleMessageBuffer[258];
serializeJson(tele, teleMessageBuffer);

if (mqttClient.publish(telemetryTopic, 0, 0, teleMessageBuffer) == true) {
Serial.println("Telemetry sent");
return true;
} else {
Serial.println("Error sending telemetry");
return false;
}
}

void connectToWifi() {
Serial.println("Connecting to WiFi...");
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.setHostname(hostname);
WiFi.begin(ssid, password);
}

bool handleWifiDisconnect() {
Serial.println("WiFi has been disconnected.");
if (WiFi.isConnected()) {
Serial.println("WiFi appears to be connected. Not retrying.");
return true;
}
// if (retryAttemptsWifi > 10) {
// Serial.println("Too many retries. Restarting");
// ESP.restart();
// } else {
retryAttemptsWifi++;
// }
if (mqttClient.connected()) {
mqttClient.disconnect();
}
if (xTimerIsTimerActive(mqttReconnectTimer) != pdFALSE) {
xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
}

if (xTimerReset(wifiReconnectTimer, 0) == pdFAIL) {
Serial.println("failed to restart wifi");
xTimerStart(wifiReconnectTimer, 0);
return false;
} else {
Serial.println("wifi restarted");
return true;
}
}

void connectToMqtt() {
Serial.print("Connecting to MQTT with ClientId ");
Serial.println(hostname);
if (WiFi.isConnected() && !updateInProgress) {
mqttClient.setServer(mqttHost, mqttPort);
mqttClient.setWill(availabilityTopic, 0, 1, "DISCONNECTED");
mqttClient.setKeepAlive(60);
mqttClient.setCredentials(mqttUser, mqttPassword);
mqttClient.setClientId(hostname);
mqttClient.connect();
} else {
Serial.println("Cannot reconnect MQTT - WiFi error");
handleWifiDisconnect();
}
}

bool handleMqttDisconnect() {
Serial.println("MQTT has been disconnected.");
if (updateInProgress) {
Serial.println("Not retrying MQTT connection - OTA update in progress");
return true;
}
retryAttemptsMqtt++;
if (WiFi.isConnected() && !updateInProgress) {
Serial.println("Starting MQTT reconnect timer");
if (xTimerReset(mqttReconnectTimer, 0) == pdFAIL) {
Serial.println("failed to restart mqtt");
xTimerStart(mqttReconnectTimer, 0);
} else {
Serial.println("mqtt restarted");
}
} else {
Serial.print("Disconnected from WiFi; starting WiFi reconnect timiler\t");
handleWifiDisconnect();
}
return true;
}

void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %x\n\r", event);
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:
//digitalWrite(LED_GPIO, !LED_ON);
Serial.print("IP address: \t");
Serial.println(WiFi.localIP());
localIp = WiFi.localIP().toString().c_str();
Serial.print("Hostname: \t");
Serial.println(WiFi.getHostname());
connectToMqtt();
if (xTimerIsTimerActive(wifiReconnectTimer) != pdFALSE) {
Serial.println("Stopping wifi reconnect timer");
xTimerStop(wifiReconnectTimer, 0);
}
retryAttemptsWifi = 0;
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
//digitalWrite(LED_GPIO, LED_ON);
Serial.println("WiFi lost connection, resetting timer\t");
handleWifiDisconnect();
break;
case SYSTEM_EVENT_WIFI_READY:
Serial.println("Wifi Ready");
handleWifiDisconnect();
break;
case SYSTEM_EVENT_STA_START:
Serial.println("STA Start");
tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname);
if (xTimerIsTimerActive(wifiReconnectTimer) != pdFALSE) {
TickType_t xRemainingTime = xTimerGetExpiryTime( wifiReconnectTimer ) - xTaskGetTickCount();
Serial.print("WiFi Time remaining: ");
Serial.println(xRemainingTime);
} else {
Serial.println("WiFi Timer is inactive; resetting\t");
handleWifiDisconnect();
}
break;
case SYSTEM_EVENT_STA_STOP:
Serial.println("STA Stop");
handleWifiDisconnect();
break;
default:
Serial.println("Event not considered");
handleWifiDisconnect();
break;
}
}

void onMqttConnect(bool sessionPresent) {
Serial.println("Connected to MQTT.");
retryAttemptsMqtt = 0;

if (mqttClient.publish(availabilityTopic, 0, 1, "CONNECTED") == true) {
//Serial.print("Success sending message to topic:\t");
//Serial.println(availabilityTopic);
} else {
Serial.println("Error sending message");
}

//sendTelemetry();

}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.print("Disconnected from MQTT. Reason: ");
Serial.println(static_cast<uint8_t>(reason));
handleMqttDisconnect();
}

void configureOTA() {
ArduinoOTA
.onStart([]() {
Serial.println("OTA Start");
updateInProgress = true;
mqttClient.disconnect(true);
xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
})
.onEnd([]() {
updateInProgress = false;
//digitalWrite(LED_GPIO, !LED_ON);
Serial.println("\n\rEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
byte percent = (progress / (total / 100));
Serial.printf("Progress: %u", percent);
Serial.println("");
//digitalWrite(LED_GPIO, percent % 2);
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
//ESP.restart();
});
ArduinoOTA.setHostname(hostname);
ArduinoOTA.setPort(8266);
ArduinoOTA.begin();
}

void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleMouse.begin();
//pinMode(LED_BUILTIN, OUTPUT);

mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));

WiFi.onEvent(WiFiEvent);

mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);

connectToWifi();

configureOTA();
}

void loop() {

TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
ArduinoOTA.handle();

static long mouseTick = millis();
static long resetTick = millis();
static int ble_connected;

if(bleMouse.isConnected()) {

ble_connected = 1;
sendTelemetry(ble_connected);

Serial.println("Move mouse pointer up");
bleMouse.move(0,-1);
//digitalWrite(LED_BUILTIN, LOW);
Expand All @@ -41,6 +287,8 @@ void loop() {
if (millis() - mouseTick > 10000) {
mouseTick = millis();
Serial.println("BLE not connected");
ble_connected = 0;
sendTelemetry(ble_connected);
if (millis() - resetTick > 60000) {
resetTick = millis();
Serial.println("Restarting ESP");
Expand Down

0 comments on commit 6398210

Please sign in to comment.