Merge branch 'release/v0.0.1'

This commit is contained in:
jptrsn 2018-10-13 17:50:59 -04:00
commit 83716b00b4
11 changed files with 163 additions and 76 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
Settings_local.h
.pioenvs
.piolibdeps
lib
.clang_complete
.gcc-flags.json
.idea

View File

@ -1,36 +1,42 @@
/*
Major thank you to the following contributors for their efforts:
pcbreflux for the original version of this code, as well as the eddystone handlers.
Andreis Speiss for his work on YouTube and his invaluable github at sensorsiot
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include <AsyncTCP.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <AsyncMqttClient.h>
#include <ArduinoJSON.h>
#include "BLEBeacon.h"
#include "BLEEddystoneTLM.h"
#include "BLEEddystoneURL.h"
#include "Settings_local.h"
BLEScan* pBLEScan;
int scanTime = 5; //In seconds
int scanTime = 10; //In seconds
int waitTime = scanInterval; //In seconds
uint16_t beconUUID = 0xFEAA;
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8))
WiFiClient espClient;
PubSubClient client(espClient);
AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
TaskHandle_t CoreZeroTask;
@ -83,27 +89,71 @@ float calculateDistance(int rssi, int txPower) {
}
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
void connectToWifi() {
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
WiFi.setHostname(hostname);
}
if (client.connect(uint64_to_string(ESP.getEfuseMac()), mqttUser, mqttPassword )) {
Serial.print("connected with client id ");
Serial.println(uint64_to_string(ESP.getEfuseMac()));
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
void connectToMqtt() {
Serial.println("Connecting to MQTT");
mqttClient.setCredentials(mqttUser, mqttPassword);
mqttClient.connect();
}
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %d\n", event);
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
connectToMqtt();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("WiFi lost connection");
xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
xTimerStart(wifiReconnectTimer, 0);
break;
}
}
void onMqttConnect(bool sessionPresent) {
Serial.println("Connected to MQTT.");
Serial.print("Session present: ");
Serial.println(sessionPresent);
String publishTopic = String(channel) + "/" + room;
if (mqttClient.publish((char *)publishTopic.c_str(), 0, 0, "Hello from ESP32") == true) {
Serial.println("Success sending message to topic");
} else {
Serial.println("Error sending message");
}
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println("Disconnected from MQTT.");
if (WiFi.isConnected()) {
xTimerStart(mqttReconnectTimer, 0);
}
}
void onMqttPublish(uint16_t packetId) {
Serial.println("Publish acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
unsigned long started = millis();
Serial.printf("\n\n");
Serial.println("onResult started");
StaticJsonBuffer<500> JSONbuffer;
JsonObject& JSONencoder = JSONbuffer.createObject();
@ -116,14 +166,18 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
JSONencoder["uuid"] = mac_address;
JSONencoder["rssi"] = rssi;
Serial.println("Parsed id");
if (advertisedDevice.haveName()){
String nameBLE = String(advertisedDevice.getName().c_str());
Serial.print("Name: ");
Serial.println(nameBLE);
JSONencoder["name"] = nameBLE;
} else {
JSONencoder["name"] = "unknown";
}
Serial.printf("\n\n");
// Serial.printf("\n\n");
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
std::string strServiceData = advertisedDevice.getServiceData();
uint8_t cServiceData[100];
@ -153,7 +207,7 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
} else {
if (advertisedDevice.haveManufacturerData()==true) {
std::string strManufacturerData = advertisedDevice.getManufacturerData();
Serial.println("Got manufacturer data");
uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
@ -198,10 +252,7 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
Serial.printf("strManufacturerData: %d \n",strManufacturerData.length());
// TODO: parse manufacturer data
// for (int i=0;i<strManufacturerData.length();i++) {
// Serial.printf("[%X]",cManufacturerData[i]);
// }
// Serial.printf("\n");
}
} else {
@ -218,28 +269,24 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
}
}
Serial.println("wdt");
vTaskDelay(500); // watchdog timer
unsigned long started = millis();
char JSONmessageBuffer[500];
char JSONmessageBuffer[512];
JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
String publishTopic = String(channel) + "/" + room;
if (client.publish((char *)publishTopic.c_str(), JSONmessageBuffer) == true) {
if (mqttClient.publish((char *)publishTopic.c_str(), 0, 0, JSONmessageBuffer) == true) {
Serial.print("Success sending message to topic: "); Serial.println(publishTopic);
unsigned long duration = millis() - started;
Serial.print("duration ");
Serial.println(duration);
// Serial.print("Message: "); Serial.println(JSONmessageBuffer);
} else {
Serial.print("Error sending message: "); Serial.println(publishTopic);
Serial.print("Message: "); Serial.println(JSONmessageBuffer);
}
unsigned long duration = millis() - started;
Serial.print("duration ");
Serial.println(duration);
}
};
@ -256,55 +303,44 @@ void createTaskOnCoreZero() {
void setup() {
Serial.begin(115200);
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);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(mqttHost, mqttPort);
connectToWifi();
createTaskOnCoreZero();
WiFi.begin(ssid, password);
WiFi.setHostname(hostname);
Serial.print("Connecting to WiFi..");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected to the WiFi network as ");
Serial.println(hostname);
client.setServer(mqttServer, mqttPort);
reconnect();
String publishTopic = String(channel) + "/" + room;
if (client.publish((char *)publishTopic.c_str(), "Hello from ESP32") == true) {
Serial.println("Success sending message to topic");
} else {
Serial.println("Error sending message");
}
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
}
unsigned long last = 0;
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (millis() - last > (waitTime * 1000)) {
vTaskDelay(10); // watchdog timer
if (millis() - last > (waitTime * 1000) || last == 0) {
Serial.println("Scanning...");
BLEScanResults foundDevices = pBLEScan->start(scanTime);
Serial.printf("\nScan done! Devices found: %d\n",foundDevices.getCount());
last = millis();
}
vTaskDelay(10); // watchdog timer
}
char *uint64_to_string(uint64_t input) {

View File

@ -4,7 +4,10 @@ An ESP32 based presence detection node for use with the Home Assistant mqtt_room
This depends heavily on the hard work done by [pcbreflux](https://github.com/pcbreflux) and [nkolban](https://github.com/nkolban) both on GitHub and on their YouTube Channels. Specifically, it is a modified version of pcbreflux's [ESP32_BLE_beaconscan](https://github.com/pcbreflux/espressif/tree/master/esp32/arduino/sketchbook/ESP32_BLE_beaconscan).
## Getting Started
1. You can get started by cloning this repository to your local machine using git. Alternatively, you can [download the zip](https://github.com/jptrsn/ESP32-mqtt-room/archive/master.zip).
You can get started by cloning this repository to your local machine using git. Alternatively, you can [download the zip](https://github.com/jptrsn/ESP32-mqtt-room/archive/master.zip). To get the code onto your device, you can load it via the Arduino IDE or, thanks to some great work by [kylegordon](https://github.com/kylegordon), you can now build and upload using PlatformIO.
2. Make a copy of the `Settings.h` file, and rename it `Settings_local.h`. Fill in the required information in your local settings file (the local file is ignored by GitHub, so you won't upload your sensitive information).
### Configuration

View File

@ -7,8 +7,8 @@
//Replace with a human-friendly host name.
#define hostname "esp32_room_presence"
//Replace with your MQTT Broker address; example: #define mqttServer "192.168.0.112"
#define mqttServer "$MQTT_BROKER_ADDRESS$"
//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 $MQTT_PORT$

View File

@ -1,7 +1,7 @@
#define ssid "Travis"
#define password "123456789"
#define hostname "esp32_room_presence"
#define mqttServer "192.168.1.1"
#define mqttHost IPAddress(192, 168, 1, 195)
#define mqttPort 1883
#define mqttUser "homeassistant"
#define mqttPassword "123456789"

View File

@ -3,6 +3,7 @@
*
* Created on: Mar 12, 2018
* Author: pcbreflux
* See original repository at https://github.com/pcbreflux/espressif/tree/master/esp32/arduino/sketchbook/ESP32_BLE_beaconscan
*/
#include "Arduino.h"
#include "sdkconfig.h"
@ -57,27 +58,27 @@ std::string BLEEddystoneTLM::toString() {
std::string out = "";
String buff;
uint32_t rawsec;
out += "Version ";
buff = String(m_eddystoneData.version, DEC);
out += buff.c_str();
out += "\n";
out += "Battery Voltage ";
buff = String(ENDIAN_CHANGE_U16(m_eddystoneData.volt), DEC);
out += buff.c_str();
out += " mV\n";
out += "Temperature ";
buff = String((float)m_eddystoneData.temp, 1);
out += buff.c_str();
out += " °C\n";
out += "Adv. Count ";
buff = String(ENDIAN_CHANGE_U32(m_eddystoneData.advCount), DEC);
out += buff.c_str();
out += "\n";
out += "Time ";
rawsec = ENDIAN_CHANGE_U32(m_eddystoneData.tmil);
buff = "0000"+String(rawsec/864000, DEC);

View File

@ -3,6 +3,7 @@
*
* Created on: Mar 12, 2018
* Author: pcbreflux
* See original repository at https://github.com/pcbreflux/espressif/tree/master/esp32/arduino/sketchbook/ESP32_BLE_beaconscan
*/
#ifndef _BLEEddystoneTLM_H_

View File

@ -3,6 +3,7 @@
*
* Created on: Mar 12, 2018
* Author: pcbreflux
* See original repository at https://github.com/pcbreflux/espressif/tree/master/esp32/arduino/sketchbook/ESP32_BLE_beaconscan
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

View File

@ -3,6 +3,7 @@
*
* Created on: Mar 12, 2018
* Author: pcbreflux
* See original repository at https://github.com/pcbreflux/espressif/tree/master/esp32/arduino/sketchbook/ESP32_BLE_beaconscan
*/
#ifndef _BLEEddystoneURL_H_

41
lib/readme.txt Normal file
View File

@ -0,0 +1,41 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link them to executable files.
The source code of each library should be placed in separate directories, like
"lib/private_lib/[here are source files]".
For example, see the structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- readme.txt --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Then in `src/main.c` you should use:
#include <Foo.h>
#include <Bar.h>
// rest H/C/CPP code
PlatformIO will find your libraries automatically, configure preprocessor's
include paths and build them.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@ -15,5 +15,6 @@ src_dir = .
platform = espressif32
framework = arduino
board = esp32dev
lib_deps = PubSubClient, ArduinoJSON
lib_deps = ArduinoJSON@5.13.2, ESP32 BLE Arduino, AsyncMqttClient@0.8.2, AsyncTCP@1.0.1
board_build.partitions = partitions_singleapp.csv
upload_port = COM13