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
|
||||
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
|
||||
|
|
74
src/main.cpp
74
src/main.cpp
|
@ -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();
|
||||
}
|
||||
|
|
98
src/main.h
98
src/main.h
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue