Feature/motion (#49)
* New Feature: Add Motion Sensor via GPIO - Use PIR Motion Sensor (HC-SR501) or Radar Sensor (RCWL-0516) * New Feature Fork WifiSettings and use that for constant portal Co-authored-by: Stefan Knaak <stefan@knaak.org>
This commit is contained in:
parent
2a5dc7eeec
commit
028b592109
|
@ -16,7 +16,7 @@ lib_deps_external =
|
||||||
haimoz/SoftFilters@^0.1.0
|
haimoz/SoftFilters@^0.1.0
|
||||||
marvinroger/AsyncMqttClient@^0.9.0
|
marvinroger/AsyncMqttClient@^0.9.0
|
||||||
bblanchon/ArduinoJson@^6.17.3
|
bblanchon/ArduinoJson@^6.17.3
|
||||||
juerd/ESP-WiFiSettings@^3.7.2
|
https://github.com/ESPresense/ESP-WiFiSettings.git
|
||||||
h2zero/NimBLE-Arduino@^1.3.1
|
h2zero/NimBLE-Arduino@^1.3.1
|
||||||
me-no-dev/AsyncTCP@^1.1.1
|
me-no-dev/AsyncTCP@^1.1.1
|
||||||
bbx10/DNSServer@^1.1.0
|
bbx10/DNSServer@^1.1.0
|
||||||
|
|
72
src/main.cpp
72
src/main.cpp
|
@ -4,7 +4,7 @@ bool sendTelemetry(int totalSeen = -1, int totalReported = -1, int totalAdverts
|
||||||
{
|
{
|
||||||
if (!online)
|
if (!online)
|
||||||
{
|
{
|
||||||
if (sendOnline() && sendDiscoveryConnectivity() && sendDiscoveryMaxDistance())
|
if (sendOnline() && sendDiscoveryConnectivity() && sendDiscoveryMaxDistance() && sendDiscoveryMotion())
|
||||||
{
|
{
|
||||||
online = true;
|
online = true;
|
||||||
reconnectTries = 0;
|
reconnectTries = 0;
|
||||||
|
@ -82,7 +82,8 @@ void connectToWifi()
|
||||||
Display.connecting();
|
Display.connecting();
|
||||||
return 150;
|
return 150;
|
||||||
};
|
};
|
||||||
WiFiSettings.onPortalWaitLoop = []() {
|
WiFiSettings.onPortalWaitLoop = []()
|
||||||
|
{
|
||||||
if (getUptimeSeconds() > 600)
|
if (getUptimeSeconds() > 600)
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
};
|
};
|
||||||
|
@ -101,6 +102,8 @@ void connectToWifi()
|
||||||
publishRooms = WiFiSettings.checkbox("pub_rooms", true, "Send to rooms topic");
|
publishRooms = WiFiSettings.checkbox("pub_rooms", true, "Send to rooms topic");
|
||||||
publishDevices = WiFiSettings.checkbox("pub_devices", true, "Send to devices topic");
|
publishDevices = WiFiSettings.checkbox("pub_devices", true, "Send to devices topic");
|
||||||
discovery = WiFiSettings.checkbox("discovery", true, "Hass Discovery");
|
discovery = WiFiSettings.checkbox("discovery", true, "Hass Discovery");
|
||||||
|
pirPin = WiFiSettings.integer("pir_pin", 0, "PIR Motion Sensor pin (0 for disable)");
|
||||||
|
radarPin = WiFiSettings.integer("radar_pin", 0, "Radar Motion pin (0 for disable)");
|
||||||
maxDistance = WiFiSettings.integer("max_dist", DEFAULT_MAX_DISTANCE, "Maximum distance to report (in meters)");
|
maxDistance = WiFiSettings.integer("max_dist", DEFAULT_MAX_DISTANCE, "Maximum distance to report (in meters)");
|
||||||
|
|
||||||
WiFiSettings.hostname = "espresense-" + room;
|
WiFiSettings.hostname = "espresense-" + room;
|
||||||
|
@ -128,6 +131,10 @@ void connectToWifi()
|
||||||
Serial.print("Discovery: ");
|
Serial.print("Discovery: ");
|
||||||
Serial.println(discovery ? "enabled" : "disabled");
|
Serial.println(discovery ? "enabled" : "disabled");
|
||||||
Serial.printf("Max Distance: %d\n", maxDistance);
|
Serial.printf("Max Distance: %d\n", maxDistance);
|
||||||
|
Serial.print("PIR Sensor: ");
|
||||||
|
Serial.println(pirPin ? "enabled" : "disabled");
|
||||||
|
Serial.print("Radar Sensor: ");
|
||||||
|
Serial.println(radarPin ? "enabled" : "disabled");
|
||||||
|
|
||||||
localIp = WiFi.localIP().toString();
|
localIp = WiFi.localIP().toString();
|
||||||
roomsTopic = CHANNEL + "/rooms/" + room;
|
roomsTopic = CHANNEL + "/rooms/" + room;
|
||||||
|
@ -139,7 +146,7 @@ void connectToWifi()
|
||||||
void onMqttConnect(bool sessionPresent)
|
void onMqttConnect(bool sessionPresent)
|
||||||
{
|
{
|
||||||
xTimerStop(reconnectTimer, 0);
|
xTimerStop(reconnectTimer, 0);
|
||||||
uint16_t packetIdSub = mqttClient.subscribe(subTopic.c_str(), 2);
|
mqttClient.subscribe(subTopic.c_str(), 2);
|
||||||
Display.connected(true, true);
|
Display.connected(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +163,15 @@ void onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties
|
||||||
char new_payload[len + 1];
|
char new_payload[len + 1];
|
||||||
new_payload[len] = '\0';
|
new_payload[len] = '\0';
|
||||||
strncpy(new_payload, payload, len);
|
strncpy(new_payload, payload, len);
|
||||||
String pay = String(new_payload);
|
|
||||||
|
|
||||||
Serial.printf("%s: %s\n", topic, new_payload);
|
Serial.printf("%s: %s\n", topic, new_payload);
|
||||||
|
|
||||||
|
String top = String(topic);
|
||||||
|
String pay = String(new_payload);
|
||||||
|
if (top == roomsTopic + "/max_distance/set")
|
||||||
|
{
|
||||||
maxDistance = pay.toInt();
|
maxDistance = pay.toInt();
|
||||||
spurt("/max_dist", String(new_payload));
|
spurt("/max_dist", pay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reconnect(TimerHandle_t xTimer)
|
void reconnect(TimerHandle_t xTimer)
|
||||||
|
@ -276,6 +287,8 @@ void setup()
|
||||||
#endif
|
#endif
|
||||||
spiffsInit();
|
spiffsInit();
|
||||||
connectToWifi();
|
connectToWifi();
|
||||||
|
if (pirPin) pinMode(pirPin, INPUT);
|
||||||
|
if (radarPin) pinMode(radarPin, INPUT);
|
||||||
#if NTP
|
#if NTP
|
||||||
setClock();
|
setClock();
|
||||||
#endif
|
#endif
|
||||||
|
@ -284,9 +297,56 @@ void setup()
|
||||||
configureOTA();
|
configureOTA();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pirLoop()
|
||||||
|
{
|
||||||
|
if (!pirPin) return;
|
||||||
|
int pirValue = digitalRead(pirPin);
|
||||||
|
|
||||||
|
if (pirValue != lastPirValue)
|
||||||
|
{
|
||||||
|
if (pirValue == HIGH)
|
||||||
|
{
|
||||||
|
mqttClient.publish((roomsTopic + "/motion").c_str(), 0, 1, "on");
|
||||||
|
Serial.println("PIR MOTION DETECTED!!!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mqttClient.publish((roomsTopic + "/motion").c_str(), 0, 1, "off");
|
||||||
|
Serial.println("NO PIR MOTION DETECTED!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPirValue = pirValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void radarLoop()
|
||||||
|
{
|
||||||
|
if (!radarPin) return;
|
||||||
|
int radarValue = digitalRead(radarPin);
|
||||||
|
|
||||||
|
if (radarValue != lastRadarValue)
|
||||||
|
{
|
||||||
|
if (radarValue == HIGH)
|
||||||
|
{
|
||||||
|
mqttClient.publish((roomsTopic + "/motion").c_str(), 0, 1, "on");
|
||||||
|
Serial.println("Radar MOTION DETECTED!!!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mqttClient.publish((roomsTopic + "/motion").c_str(), 0, 1, "off");
|
||||||
|
Serial.println("NO Radar MOTION DETECTED!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRadarValue = radarValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
ArduinoOTA.handle();
|
ArduinoOTA.handle();
|
||||||
firmwareUpdate();
|
firmwareUpdate();
|
||||||
Display.update();
|
Display.update();
|
||||||
|
pirLoop();
|
||||||
|
radarLoop();
|
||||||
|
WiFiSettings.httpLoop();
|
||||||
}
|
}
|
||||||
|
|
46
src/main.h
46
src/main.h
|
@ -46,6 +46,11 @@ bool publishRooms;
|
||||||
bool publishDevices;
|
bool publishDevices;
|
||||||
bool discovery;
|
bool discovery;
|
||||||
int maxDistance;
|
int maxDistance;
|
||||||
|
int pirPin;
|
||||||
|
int radarPin;
|
||||||
|
|
||||||
|
int lastPirValue = -1;
|
||||||
|
int lastRadarValue = -1;
|
||||||
|
|
||||||
BleFingerprintCollection fingerprints(MAX_MAC_ADDRESSES);
|
BleFingerprintCollection fingerprints(MAX_MAC_ADDRESSES);
|
||||||
|
|
||||||
|
@ -113,23 +118,27 @@ void setClock()
|
||||||
void configureOTA()
|
void configureOTA()
|
||||||
{
|
{
|
||||||
ArduinoOTA
|
ArduinoOTA
|
||||||
.onStart([]() {
|
.onStart([]()
|
||||||
|
{
|
||||||
Serial.println("OTA Start");
|
Serial.println("OTA Start");
|
||||||
updateInProgress = true;
|
updateInProgress = true;
|
||||||
fingerprints.setDisable(updateInProgress);
|
fingerprints.setDisable(updateInProgress);
|
||||||
})
|
})
|
||||||
.onEnd([]() {
|
.onEnd([]()
|
||||||
|
{
|
||||||
updateInProgress = false;
|
updateInProgress = false;
|
||||||
fingerprints.setDisable(updateInProgress);
|
fingerprints.setDisable(updateInProgress);
|
||||||
Display.updateEnd();
|
Display.updateEnd();
|
||||||
Serial.println("\n\rEnd");
|
Serial.println("\n\rEnd");
|
||||||
})
|
})
|
||||||
.onProgress([](unsigned int progress, unsigned int total) {
|
.onProgress([](unsigned int progress, unsigned int total)
|
||||||
|
{
|
||||||
byte percent = (progress / (total / 100));
|
byte percent = (progress / (total / 100));
|
||||||
Serial.printf("Progress: %u\r\n", percent);
|
Serial.printf("Progress: %u\r\n", percent);
|
||||||
Display.updateProgress(progress);
|
Display.updateProgress(progress);
|
||||||
})
|
})
|
||||||
.onError([](ota_error_t error) {
|
.onError([](ota_error_t error)
|
||||||
|
{
|
||||||
Serial.printf("Error[%u]: ", error);
|
Serial.printf("Error[%u]: ", error);
|
||||||
if (error == OTA_AUTH_ERROR)
|
if (error == OTA_AUTH_ERROR)
|
||||||
Serial.println("Auth Failed");
|
Serial.println("Auth Failed");
|
||||||
|
@ -289,6 +298,35 @@ bool sendDiscoveryConnectivity()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sendDiscoveryMotion()
|
||||||
|
{
|
||||||
|
if (!discovery) return true;
|
||||||
|
if (!pirPin && !radarPin) return true;
|
||||||
|
|
||||||
|
String discoveryTopic = "homeassistant/binary_sensor/espresense_" + room + "/motion/config";
|
||||||
|
|
||||||
|
DynamicJsonDocument doc(1200);
|
||||||
|
char buffer[1200];
|
||||||
|
|
||||||
|
doc["~"] = roomsTopic;
|
||||||
|
doc["name"] = "ESPresense " + room + " Motion";
|
||||||
|
doc["unique_id"] = WiFi.macAddress() + "_motion";
|
||||||
|
doc["availability_topic"] = "~/status";
|
||||||
|
doc["stat_t"] = "~/motion";
|
||||||
|
doc["dev_cla"] = "motion";
|
||||||
|
|
||||||
|
commonDiscovery(&doc);
|
||||||
|
serializeJson(doc, buffer);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if (mqttClient.publish(discoveryTopic.c_str(), 0, true, buffer))
|
||||||
|
return true;
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool sendDiscoveryMaxDistance()
|
bool sendDiscoveryMaxDistance()
|
||||||
{
|
{
|
||||||
if (!discovery) return true;
|
if (!discovery) return true;
|
||||||
|
|
Loading…
Reference in New Issue