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:
Darrell 2021-09-21 13:55:41 -04:00 committed by GitHub
parent 2a5dc7eeec
commit 028b592109
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 136 additions and 38 deletions

View File

@ -16,7 +16,7 @@ lib_deps_external =
haimoz/SoftFilters@^0.1.0
marvinroger/AsyncMqttClient@^0.9.0
bblanchon/ArduinoJson@^6.17.3
juerd/ESP-WiFiSettings@^3.7.2
https://github.com/ESPresense/ESP-WiFiSettings.git
h2zero/NimBLE-Arduino@^1.3.1
me-no-dev/AsyncTCP@^1.1.1
bbx10/DNSServer@^1.1.0

View File

@ -4,7 +4,7 @@ bool sendTelemetry(int totalSeen = -1, int totalReported = -1, int totalAdverts
{
if (!online)
{
if (sendOnline() && sendDiscoveryConnectivity() && sendDiscoveryMaxDistance())
if (sendOnline() && sendDiscoveryConnectivity() && sendDiscoveryMaxDistance() && sendDiscoveryMotion())
{
online = true;
reconnectTries = 0;
@ -82,7 +82,8 @@ void connectToWifi()
Display.connecting();
return 150;
};
WiFiSettings.onPortalWaitLoop = []() {
WiFiSettings.onPortalWaitLoop = []()
{
if (getUptimeSeconds() > 600)
ESP.restart();
};
@ -101,6 +102,8 @@ void connectToWifi()
publishRooms = WiFiSettings.checkbox("pub_rooms", true, "Send to rooms topic");
publishDevices = WiFiSettings.checkbox("pub_devices", true, "Send to devices topic");
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)");
WiFiSettings.hostname = "espresense-" + room;
@ -128,6 +131,10 @@ void connectToWifi()
Serial.print("Discovery: ");
Serial.println(discovery ? "enabled" : "disabled");
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();
roomsTopic = CHANNEL + "/rooms/" + room;
@ -139,7 +146,7 @@ void connectToWifi()
void onMqttConnect(bool sessionPresent)
{
xTimerStop(reconnectTimer, 0);
uint16_t packetIdSub = mqttClient.subscribe(subTopic.c_str(), 2);
mqttClient.subscribe(subTopic.c_str(), 2);
Display.connected(true, true);
}
@ -156,11 +163,15 @@ void onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties
char new_payload[len + 1];
new_payload[len] = '\0';
strncpy(new_payload, payload, len);
String pay = String(new_payload);
Serial.printf("%s: %s\n", topic, new_payload);
maxDistance = pay.toInt();
spurt("/max_dist", String(new_payload));
String top = String(topic);
String pay = String(new_payload);
if (top == roomsTopic + "/max_distance/set")
{
maxDistance = pay.toInt();
spurt("/max_dist", pay);
}
}
void reconnect(TimerHandle_t xTimer)
@ -276,6 +287,8 @@ void setup()
#endif
spiffsInit();
connectToWifi();
if (pirPin) pinMode(pirPin, INPUT);
if (radarPin) pinMode(radarPin, INPUT);
#if NTP
setClock();
#endif
@ -284,9 +297,56 @@ void setup()
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()
{
ArduinoOTA.handle();
firmwareUpdate();
Display.update();
pirLoop();
radarLoop();
WiFiSettings.httpLoop();
}

View File

@ -46,6 +46,11 @@ bool publishRooms;
bool publishDevices;
bool discovery;
int maxDistance;
int pirPin;
int radarPin;
int lastPirValue = -1;
int lastRadarValue = -1;
BleFingerprintCollection fingerprints(MAX_MAC_ADDRESSES);
@ -113,36 +118,40 @@ void setClock()
void configureOTA()
{
ArduinoOTA
.onStart([]() {
Serial.println("OTA Start");
updateInProgress = true;
fingerprints.setDisable(updateInProgress);
})
.onEnd([]() {
updateInProgress = false;
fingerprints.setDisable(updateInProgress);
Display.updateEnd();
Serial.println("\n\rEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
byte percent = (progress / (total / 100));
Serial.printf("Progress: %u\r\n", percent);
Display.updateProgress(progress);
})
.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");
updateInProgress = false;
});
.onStart([]()
{
Serial.println("OTA Start");
updateInProgress = true;
fingerprints.setDisable(updateInProgress);
})
.onEnd([]()
{
updateInProgress = false;
fingerprints.setDisable(updateInProgress);
Display.updateEnd();
Serial.println("\n\rEnd");
})
.onProgress([](unsigned int progress, unsigned int total)
{
byte percent = (progress / (total / 100));
Serial.printf("Progress: %u\r\n", percent);
Display.updateProgress(progress);
})
.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");
updateInProgress = false;
});
ArduinoOTA.setHostname(WiFi.getHostname());
ArduinoOTA.setPort(3232);
ArduinoOTA.begin();
@ -289,6 +298,35 @@ bool sendDiscoveryConnectivity()
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()
{
if (!discovery) return true;