|
|
@@ -40,7 +40,7 @@ Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
|
|
|
|
|
|
|
|
|
|
|
|
enum class Mode { scan, enroll, wificonfig, maintenance, cooldown };
|
|
|
|
enum class Mode { scan, enroll, wificonfig, maintenance, cooldown };
|
|
|
|
|
|
|
|
|
|
|
|
const char* VersionInfo = "0.5";
|
|
|
|
const char* VersionInfo = "0.6";
|
|
|
|
|
|
|
|
|
|
|
|
// ===================================================================================================================
|
|
|
|
// ===================================================================================================================
|
|
|
|
// Caution: below are not the credentials for connecting to your home network, they are for the Access Point mode!!!
|
|
|
|
// Caution: below are not the credentials for connecting to your home network, they are for the Access Point mode!!!
|
|
|
@@ -53,7 +53,7 @@ const int buzzerOutputPin = 8; // pin connected to the buzzer (when using hardwa
|
|
|
|
const int doorOpenerOutputPin = 9; //USE 6 HERE pin connected to the door opener (when using hardware connection instead of mqtt to open the door)
|
|
|
|
const int doorOpenerOutputPin = 9; //USE 6 HERE pin connected to the door opener (when using hardware connection instead of mqtt to open the door)
|
|
|
|
const int doorbellOutputPin = 10; // pin connected to the doorbell (when using hardware connection instead of mqtt to ring the bell)
|
|
|
|
const int doorbellOutputPin = 10; // pin connected to the doorbell (when using hardware connection instead of mqtt to ring the bell)
|
|
|
|
const int KeyboardPin = 4; //pin connected to an analog keyboard (see voltage ranges for the nubers in seperate array)
|
|
|
|
const int KeyboardPin = 4; //pin connected to an analog keyboard (see voltage ranges for the nubers in seperate array)
|
|
|
|
const int KEY_POLLING_MS = 25;
|
|
|
|
const int KEY_POLLING_MS = 50;
|
|
|
|
const uint8_t NUM_PIN_MAX_DIGITS = {10};
|
|
|
|
const uint8_t NUM_PIN_MAX_DIGITS = {10};
|
|
|
|
#ifdef CUSTOM_GPIOS
|
|
|
|
#ifdef CUSTOM_GPIOS
|
|
|
|
const int customOutput1 = 18; // not used internally, but can be set over MQTT
|
|
|
|
const int customOutput1 = 18; // not used internally, but can be set over MQTT
|
|
|
@@ -121,7 +121,7 @@ String getLogMessagesAsHtml() {
|
|
|
|
|
|
|
|
|
|
|
|
String getTimestampString(){
|
|
|
|
String getTimestampString(){
|
|
|
|
struct tm timeinfo;
|
|
|
|
struct tm timeinfo;
|
|
|
|
if(!getLocalTime(&timeinfo)){
|
|
|
|
if(!getLocalTime(&timeinfo, 1000)){
|
|
|
|
Serial.println("Failed to obtain time");
|
|
|
|
Serial.println("Failed to obtain time");
|
|
|
|
return "no time";
|
|
|
|
return "no time";
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -251,14 +251,83 @@ bool checkPairingValid() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t WiFi_scanNetworks(void ){
|
|
|
|
|
|
|
|
uint32_t _numNetworks = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int8_t res;
|
|
|
|
|
|
|
|
res = WiFi.scanNetworks();
|
|
|
|
|
|
|
|
if(res == WIFI_SCAN_FAILED){
|
|
|
|
|
|
|
|
addLogMessage(F("NetworkScanFailed"));
|
|
|
|
|
|
|
|
}else if(res == WIFI_SCAN_RUNNING){
|
|
|
|
|
|
|
|
while(WiFi.scanComplete() == WIFI_SCAN_RUNNING){
|
|
|
|
|
|
|
|
delay(100);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_numNetworks = WiFi.scanComplete();
|
|
|
|
|
|
|
|
}else if(res >=0 ) {
|
|
|
|
|
|
|
|
_numNetworks = res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return _numNetworks;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool initWifi() {
|
|
|
|
bool initWifi() {
|
|
|
|
|
|
|
|
uint32_t _numNetworks = 0;
|
|
|
|
// Connect to Wi-Fi
|
|
|
|
// Connect to Wi-Fi
|
|
|
|
WifiSettings wifiSettings = settingsManager.getWifiSettings();
|
|
|
|
WifiSettings wifiSettings = settingsManager.getWifiSettings();
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
|
|
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
|
|
|
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
|
|
|
|
|
|
|
WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL);
|
|
|
|
|
|
|
|
WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN);
|
|
|
|
|
|
|
|
WiFi.persistent(false);
|
|
|
|
|
|
|
|
WiFi.mode(WIFI_OFF);
|
|
|
|
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
|
|
|
|
|
|
WiFi.disconnect(true); // delete old config
|
|
|
|
|
|
|
|
WiFi.begin();
|
|
|
|
|
|
|
|
delay(500); // 500ms seems to work in most cases, may depend on AP
|
|
|
|
|
|
|
|
WiFi.disconnect(true); // delete old config
|
|
|
|
|
|
|
|
|
|
|
|
WiFi.setHostname(wifiSettings.hostname.c_str()); //define hostname
|
|
|
|
WiFi.setHostname(wifiSettings.hostname.c_str()); //define hostname
|
|
|
|
WiFi.begin(wifiSettings.ssid.c_str(), wifiSettings.password.c_str());
|
|
|
|
_numNetworks = WiFi_scanNetworks(); // scan in case this gets called before any scans
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (_numNetworks == 0) {
|
|
|
|
|
|
|
|
addLogMessage(F("No networks found"));
|
|
|
|
|
|
|
|
WiFi.begin(wifiSettings.ssid.c_str(), wifiSettings.password.c_str());
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
#ifdef WM_DEBUG_LEVEL
|
|
|
|
|
|
|
|
DEBUG_WM(n, F("networks found"));
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int bestConnection = -1;
|
|
|
|
|
|
|
|
// Find best RSSI AP for given SSID
|
|
|
|
|
|
|
|
for (int i = 0; i < _numNetworks; i++) {
|
|
|
|
|
|
|
|
if (wifiSettings.ssid == WiFi.SSID(i)) {
|
|
|
|
|
|
|
|
addLogMessage(String(F("SSID ")) + wifiSettings.ssid + String(F(" found with RSSI: ")) +
|
|
|
|
|
|
|
|
String(WiFi.RSSI(i)) + String(F("(")) +
|
|
|
|
|
|
|
|
String(constrain((100.0 + WiFi.RSSI(i)) * 2, 0, 100)) +
|
|
|
|
|
|
|
|
String(F(" %) and BSSID: ")) + WiFi.BSSIDstr(i) +
|
|
|
|
|
|
|
|
String(F(" and channel: ")) + String(WiFi.channel(i)));
|
|
|
|
|
|
|
|
if (bestConnection == -1) {
|
|
|
|
|
|
|
|
bestConnection = i;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (WiFi.RSSI(i) > WiFi.RSSI(bestConnection)) {
|
|
|
|
|
|
|
|
bestConnection = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestConnection == -1) {
|
|
|
|
|
|
|
|
addLogMessage(String(F("No network found with SSID: "))+wifiSettings.ssid.c_str());
|
|
|
|
|
|
|
|
WiFi.begin(wifiSettings.ssid.c_str(), wifiSettings.password.c_str());
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
addLogMessage(String(F("Trying to connect to SSID ")) + wifiSettings.ssid + String(F(" found with RSSI: ")) +
|
|
|
|
|
|
|
|
String(WiFi.RSSI(bestConnection)) + String(F("(")) +
|
|
|
|
|
|
|
|
String(constrain((100.0 + WiFi.RSSI(bestConnection)) * 2, 0, 100)) +
|
|
|
|
|
|
|
|
String(F(" %) and BSSID: ")) + WiFi.BSSIDstr(bestConnection) +
|
|
|
|
|
|
|
|
String(F(" and channel: ")) + String(WiFi.channel(bestConnection)));
|
|
|
|
|
|
|
|
WiFi.begin(wifiSettings.ssid.c_str(), wifiSettings.password.c_str(), 0,
|
|
|
|
|
|
|
|
WiFi.BSSID(bestConnection));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//WiFi.begin(wifiSettings.ssid.c_str(), wifiSettings.password.c_str());
|
|
|
|
int counter = 0;
|
|
|
|
int counter = 0;
|
|
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
|
|
delay(1000);
|
|
|
|
delay(1000);
|
|
|
@@ -270,7 +339,7 @@ bool initWifi() {
|
|
|
|
Serial.println("Connected!");
|
|
|
|
Serial.println("Connected!");
|
|
|
|
setenv("TZ", TZ_INFO, 1); // Zeitzone muss nach dem reset neu eingestellt werden
|
|
|
|
setenv("TZ", TZ_INFO, 1); // Zeitzone muss nach dem reset neu eingestellt werden
|
|
|
|
tzset();
|
|
|
|
tzset();
|
|
|
|
configTzTime(TZ_INFO, settingsManager.getAppSettings().ntpServer.c_str(), "pool.ntp.org"); // ESP32 Systemzeit mit NTP Synchronisieren
|
|
|
|
configTzTime(TZ_INFO, settingsManager.getAppSettings().ntpServer.c_str(),"nas.local","fritz.box"); // ESP32 Systemzeit mit NTP Synchronisieren
|
|
|
|
// Print ESP32 Local IP Address
|
|
|
|
// Print ESP32 Local IP Address
|
|
|
|
Serial.println(WiFi.localIP());
|
|
|
|
Serial.println(WiFi.localIP());
|
|
|
|
|
|
|
|
|
|
|
@@ -719,7 +788,6 @@ void doScan()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ScanResult::matchFound:
|
|
|
|
case ScanResult::matchFound:
|
|
|
|
notifyClients( String("Match Found: ") + match.matchId + " - " + match.matchName + " with confidence of " + match.matchConfidence );
|
|
|
|
|
|
|
|
if (match.scanResult != lastMatch.scanResult) {
|
|
|
|
if (match.scanResult != lastMatch.scanResult) {
|
|
|
|
if (checkPairingValid()) {
|
|
|
|
if (checkPairingValid()) {
|
|
|
|
openDoor(match);
|
|
|
|
openDoor(match);
|
|
|
@@ -727,14 +795,15 @@ void doScan()
|
|
|
|
notifyClients("Security issue! Match was not sent by MQTT because of invalid sensor pairing! This could potentially be an attack! If the sensor is new or has been replaced by you do a (re)pairing in settings page.");
|
|
|
|
notifyClients("Security issue! Match was not sent by MQTT because of invalid sensor pairing! This could potentially be an attack! If the sensor is new or has been replaced by you do a (re)pairing in settings page.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
notifyClients( String("Match Found: ") + match.matchId + " - " + match.matchName + " with confidence of " + match.matchConfidence );
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ScanResult::noMatchFound:
|
|
|
|
case ScanResult::noMatchFound:
|
|
|
|
notifyClients(String("No Match Found (Code ") + match.returnCode + ")");
|
|
|
|
|
|
|
|
if (match.scanResult != lastMatch.scanResult) {
|
|
|
|
if (match.scanResult != lastMatch.scanResult) {
|
|
|
|
ringBell();
|
|
|
|
ringBell();
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
setCooldown(5000); // wait some time before next scan to let the LED blink
|
|
|
|
setCooldown(5000); // wait some time before next scan to let the LED blink
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
notifyClients(String("No Match Found (Code ") + match.returnCode + ")");
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ScanResult::error:
|
|
|
|
case ScanResult::error:
|
|
|
|
notifyClients(String("ScanResult Error (Code ") + match.returnCode + ")");
|
|
|
|
notifyClients(String("ScanResult Error (Code ") + match.returnCode + ")");
|
|
|
@@ -783,7 +852,9 @@ void keyboardPoller(void){
|
|
|
|
static uint8_t pin[NUM_PIN_MAX_DIGITS] = {0};
|
|
|
|
static uint8_t pin[NUM_PIN_MAX_DIGITS] = {0};
|
|
|
|
uint8_t key = keypad.getKey();
|
|
|
|
uint8_t key = keypad.getKey();
|
|
|
|
if(key){
|
|
|
|
if(key){
|
|
|
|
Serial.printf("KeyVal: %c\n", key);
|
|
|
|
//String keyStr(key);
|
|
|
|
|
|
|
|
//notifyClients("Key: "+keyStr);
|
|
|
|
|
|
|
|
//Serial.printf("KeyVal: %c\n", key);
|
|
|
|
pin[pinpos++] = key;
|
|
|
|
pin[pinpos++] = key;
|
|
|
|
resetTimer = 0;
|
|
|
|
resetTimer = 0;
|
|
|
|
io.digitalWrite(buzzerOutputPin, HIGH);
|
|
|
|
io.digitalWrite(buzzerOutputPin, HIGH);
|
|
|
@@ -792,7 +863,7 @@ void keyboardPoller(void){
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(pinpos){
|
|
|
|
if(pinpos){
|
|
|
|
resetTimer++;
|
|
|
|
resetTimer++;
|
|
|
|
if(resetTimer > 4000/KEY_POLLING_MS){
|
|
|
|
if(resetTimer > 2000/KEY_POLLING_MS){
|
|
|
|
resetTimer = 0;
|
|
|
|
resetTimer = 0;
|
|
|
|
pinpos = 0;
|
|
|
|
pinpos = 0;
|
|
|
|
Serial.println("RESET");
|
|
|
|
Serial.println("RESET");
|
|
|
@@ -807,15 +878,25 @@ void keyboardPoller(void){
|
|
|
|
pinOK= false;
|
|
|
|
pinOK= false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pinpos = 0;
|
|
|
|
|
|
|
|
if(pinOK){
|
|
|
|
if(pinOK){
|
|
|
|
Serial.println("OPEN!!");
|
|
|
|
Serial.println("OPEN!!");
|
|
|
|
Match match;
|
|
|
|
Match match;
|
|
|
|
match.matchName = "KEYPAD";
|
|
|
|
match.matchName = "KEYPAD";
|
|
|
|
openDoor(match);
|
|
|
|
openDoor(match);
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
|
Serial.println("WRONG");
|
|
|
|
pinOK = true;
|
|
|
|
|
|
|
|
PinStr = "************";
|
|
|
|
|
|
|
|
for(uint8_t i=0;i<pinpos;i++){
|
|
|
|
|
|
|
|
uint8_t coosenPinDigit = PinStr.charAt(i);
|
|
|
|
|
|
|
|
if(pin[i] != coosenPinDigit){
|
|
|
|
|
|
|
|
pinOK= false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pinOK){
|
|
|
|
|
|
|
|
ESP.restart();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pinpos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|