update
This commit is contained in:
@@ -16,7 +16,9 @@ CFingerLogic::CFingerLogic(CMain *pMain)
|
|||||||
memset(&m_FingerParams, 0, sizeof(m_FingerParams));
|
memset(&m_FingerParams, 0, sizeof(m_FingerParams));
|
||||||
memset(m_aFingerSlots, 0, sizeof(m_aFingerSlots));
|
memset(m_aFingerSlots, 0, sizeof(m_aFingerSlots));
|
||||||
m_FingerSlotsAdded = 0;
|
m_FingerSlotsAdded = 0;
|
||||||
|
m_ErrorCounter = 0;
|
||||||
|
|
||||||
|
m_InitTimer.initializeMs(100, TimerDelegate(&CFingerLogic::InitFinger, this));
|
||||||
m_PowerOffTimer.initializeMs(1000, TimerDelegate(&CFingerLogic::PowerOff, this));
|
m_PowerOffTimer.initializeMs(1000, TimerDelegate(&CFingerLogic::PowerOff, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +33,13 @@ void CFingerLogic::SetState(FingerLogicState state)
|
|||||||
{
|
{
|
||||||
m_State = state;
|
m_State = state;
|
||||||
|
|
||||||
|
if(m_State == STATE_ERROR)
|
||||||
|
m_ErrorCounter++;
|
||||||
|
|
||||||
if(m_State == STATE_READY || m_State == STATE_ERROR)
|
if(m_State == STATE_READY || m_State == STATE_ERROR)
|
||||||
m_PowerOffTimer.start(false);
|
{
|
||||||
|
m_PowerOffTimer.startOnce();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_PowerOffTimer.stop();
|
m_PowerOffTimer.stop();
|
||||||
@@ -47,9 +54,8 @@ void CFingerLogic::PowerOff()
|
|||||||
|
|
||||||
debugf("PowerOff()");
|
debugf("PowerOff()");
|
||||||
m_Power = false;
|
m_Power = false;
|
||||||
Main().FingerEnable(false);
|
m_ErrorCounter = 0;
|
||||||
wifi_set_sleep_type(LIGHT_SLEEP_T);
|
Main().FingerPower(false);
|
||||||
system_soft_wdt_feed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::PowerOn()
|
void CFingerLogic::PowerOn()
|
||||||
@@ -59,14 +65,15 @@ void CFingerLogic::PowerOn()
|
|||||||
|
|
||||||
debugf("PowerOn()");
|
debugf("PowerOn()");
|
||||||
m_Power = true;
|
m_Power = true;
|
||||||
Main().FingerEnable(true);
|
Main().FingerPower(true);
|
||||||
wifi_set_sleep_type(MODEM_SLEEP_T);
|
system_soft_wdt_feed();
|
||||||
delayMilliseconds(100);
|
delayMilliseconds(100);
|
||||||
|
system_soft_wdt_feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::OnFingerInterrupt(bool finger)
|
void CFingerLogic::OnFinger(bool finger)
|
||||||
{
|
{
|
||||||
debugf("OnFingerInterrupt: %s", finger ? "DOWN" : "UP");
|
debugf("OnFinger: %s", finger ? "DOWN" : "UP");
|
||||||
m_Finger = finger;
|
m_Finger = finger;
|
||||||
|
|
||||||
if(finger)
|
if(finger)
|
||||||
@@ -122,15 +129,20 @@ void CFingerLogic::InitFinger()
|
|||||||
if(m_State > STATE_INIT_VERIFYPASSWORD)
|
if(m_State > STATE_INIT_VERIFYPASSWORD)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(m_ErrorCounter > 100)
|
||||||
|
return;
|
||||||
|
|
||||||
SetState(STATE_INIT_VERIFYPASSWORD);
|
SetState(STATE_INIT_VERIFYPASSWORD);
|
||||||
FingerPrint().AsyncVerifyPassword((VerifyPasswordCallback)InitFinger_OnVerifyPassword, this);
|
FingerPrint().AsyncVerifyPassword((VerifyPasswordCallback)InitFinger_OnVerifyPassword, this);
|
||||||
|
|
||||||
m_Timer.initializeMs(100, TimerDelegate(&CFingerLogic::InitFinger, this)).start();
|
m_InitTimer.start();
|
||||||
|
m_ErrorCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::InitFinger_OnVerifyPassword(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
|
void CFingerLogic::InitFinger_OnVerifyPassword(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
|
||||||
{
|
{
|
||||||
pThis->m_Timer.stop();
|
pThis->m_ErrorCounter--;
|
||||||
|
pThis->m_InitTimer.stop();
|
||||||
debugf("InitFinger_OnVerifyPassword: (%d) %s", error, errorStr);
|
debugf("InitFinger_OnVerifyPassword: (%d) %s", error, errorStr);
|
||||||
|
|
||||||
if(error == ERROR_OK)
|
if(error == ERROR_OK)
|
||||||
@@ -157,11 +169,38 @@ void CFingerLogic::InitFinger_OnReadSystemParameters(CFingerLogic *pThis, Finger
|
|||||||
debugf("packetLength: %d", param->packetLength);
|
debugf("packetLength: %d", param->packetLength);
|
||||||
debugf("baudRate: %d", param->baudRate);
|
debugf("baudRate: %d", param->baudRate);
|
||||||
|
|
||||||
|
if(param->securityLevel != pThis->Main().Settings().m_SecurityLevel)
|
||||||
|
{
|
||||||
|
pThis->SetState(STATE_INIT_SETSYSTEM_SECURITYLEVEL);
|
||||||
|
pThis->FingerPrint().AsyncSetSystemParameter((SetSystemParameterCallback)InitFinger_OnSetSystemSecurityLevel, pThis, FINGERPRINT_SECURITY_REG_ADDR, pThis->Main().Settings().m_SecurityLevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pThis->SetState(STATE_INIT_READTEMPLATEMAP);
|
||||||
|
pThis->FingerPrint().AsyncReadTemplateMap((ReadTemplateMapCallback)InitFinger_OnReadTemplateMap, pThis, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pThis->SetState(STATE_ERROR);
|
||||||
|
pThis->m_InitTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFingerLogic::InitFinger_OnSetSystemSecurityLevel(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
|
||||||
|
{
|
||||||
|
debugf("InitFinger_OnSetSystemSecurityLevel: (%d) %s", error, errorStr);
|
||||||
|
|
||||||
|
if(error == ERROR_OK)
|
||||||
|
{
|
||||||
pThis->SetState(STATE_INIT_READTEMPLATEMAP);
|
pThis->SetState(STATE_INIT_READTEMPLATEMAP);
|
||||||
pThis->FingerPrint().AsyncReadTemplateMap((ReadTemplateMapCallback)InitFinger_OnReadTemplateMap, pThis, 0);
|
pThis->FingerPrint().AsyncReadTemplateMap((ReadTemplateMapCallback)InitFinger_OnReadTemplateMap, pThis, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
pThis->SetState(STATE_ERROR);
|
pThis->SetState(STATE_ERROR);
|
||||||
|
pThis->m_InitTimer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::InitFinger_OnReadTemplateMap(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen)
|
void CFingerLogic::InitFinger_OnReadTemplateMap(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen)
|
||||||
@@ -241,7 +280,10 @@ void CFingerLogic::InitFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintErr
|
|||||||
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)InitFinger_OnDownloadCharacteristics, pThis, 0x01);
|
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)InitFinger_OnDownloadCharacteristics, pThis, 0x01);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
pThis->SetState(STATE_ERROR);
|
pThis->SetState(STATE_ERROR);
|
||||||
|
pThis->m_InitTimer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::InitFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
|
void CFingerLogic::InitFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
|
||||||
@@ -282,7 +324,10 @@ void CFingerLogic::InitFinger_OnDownloadCharacteristics(CFingerLogic *pThis, Fin
|
|||||||
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)InitFinger_OnLoadTemplate, pThis, position, 0x01);
|
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)InitFinger_OnLoadTemplate, pThis, position, 0x01);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
pThis->SetState(STATE_ERROR);
|
pThis->SetState(STATE_ERROR);
|
||||||
|
pThis->m_InitTimer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -537,9 +582,7 @@ void CFingerLogic::EnrollFinger_OnCreateTemplate(CFingerLogic *pThis, FingerPrin
|
|||||||
pThis->FingerPrint().AsyncStoreTemplate((StoreTemplateCallback)EnrollFinger_OnStoreTemplate, pThis, pThis->m_iBuffer, 0x01);
|
pThis->FingerPrint().AsyncStoreTemplate((StoreTemplateCallback)EnrollFinger_OnStoreTemplate, pThis, pThis->m_iBuffer, 0x01);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
pThis->SetState(STATE_READY);
|
pThis->SetState(STATE_READY);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::EnrollFinger_OnStoreTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint16_t positionNumber)
|
void CFingerLogic::EnrollFinger_OnStoreTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint16_t positionNumber)
|
||||||
@@ -554,9 +597,7 @@ void CFingerLogic::EnrollFinger_OnStoreTemplate(CFingerLogic *pThis, FingerPrint
|
|||||||
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)EnrollFinger_OnLoadTemplate, pThis, positionNumber, 0x01);
|
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)EnrollFinger_OnLoadTemplate, pThis, positionNumber, 0x01);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
pThis->SetState(STATE_READY);
|
pThis->SetState(STATE_READY);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
|
void CFingerLogic::EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
|
||||||
@@ -570,9 +611,7 @@ void CFingerLogic::EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintE
|
|||||||
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)EnrollFinger_OnDownloadCharacteristics, pThis, 0x01);
|
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)EnrollFinger_OnDownloadCharacteristics, pThis, 0x01);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
pThis->SetState(STATE_READY);
|
pThis->SetState(STATE_READY);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFingerLogic::EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
|
void CFingerLogic::EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
|
||||||
@@ -586,13 +625,20 @@ void CFingerLogic::EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, F
|
|||||||
ctx.update(pChar, charLen);
|
ctx.update(pChar, charLen);
|
||||||
uint8_t *digest = ctx.getHash().data();
|
uint8_t *digest = ctx.getHash().data();
|
||||||
|
|
||||||
Serial1.printf("NEW Finger %d hexdigest: ", pThis->m_iBuffer);
|
|
||||||
for(uint8_t i = 0; i < sizeof(digest); i++)
|
|
||||||
Serial1.printf("%x", digest[i]);
|
|
||||||
Serial1.printf("\n");
|
|
||||||
|
|
||||||
pThis->Main().OnFingerEnrolled(pThis->m_iBuffer, digest);
|
pThis->Main().OnFingerEnrolled(pThis->m_iBuffer, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
pThis->SetState(STATE_READY);
|
pThis->SetState(STATE_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CFingerLogic::SetSecurityLevel(int securityLevel)
|
||||||
|
{
|
||||||
|
SetState(STATE_SETSYSTEM_SECURITYLEVEL);
|
||||||
|
FingerPrint().AsyncSetSystemParameter((SetSystemParameterCallback)SetSecurityLevel_OnSetSystemSecurityLevel, this, FINGERPRINT_SECURITY_REG_ADDR, securityLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFingerLogic::SetSecurityLevel_OnSetSystemSecurityLevel(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
|
||||||
|
{
|
||||||
|
debugf("SetSecurityLevel_OnSetSystemSecurityLevel: (%d) %s", error, errorStr);
|
||||||
|
pThis->SetState(STATE_READY);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ enum FingerLogicState
|
|||||||
|
|
||||||
STATE_INIT_VERIFYPASSWORD,
|
STATE_INIT_VERIFYPASSWORD,
|
||||||
STATE_INIT_READSYSTEMPARAMETERS,
|
STATE_INIT_READSYSTEMPARAMETERS,
|
||||||
|
STATE_INIT_SETSYSTEM_SECURITYLEVEL,
|
||||||
STATE_INIT_READTEMPLATEMAP,
|
STATE_INIT_READTEMPLATEMAP,
|
||||||
STATE_INIT_VERIFYTEMPLATES,
|
STATE_INIT_VERIFYTEMPLATES,
|
||||||
|
|
||||||
@@ -33,7 +34,9 @@ enum FingerLogicState
|
|||||||
STATE_ENROLL_CREATETEMPLATE,
|
STATE_ENROLL_CREATETEMPLATE,
|
||||||
STATE_ENROLL_STORETEMPLATE,
|
STATE_ENROLL_STORETEMPLATE,
|
||||||
STATE_ENROLL_LOADTEMPLATE,
|
STATE_ENROLL_LOADTEMPLATE,
|
||||||
STATE_ENROLL_DOWNLOADCHARACTERISTICS
|
STATE_ENROLL_DOWNLOADCHARACTERISTICS,
|
||||||
|
|
||||||
|
STATE_SETSYSTEM_SECURITYLEVEL
|
||||||
};
|
};
|
||||||
|
|
||||||
class CFingerLogic
|
class CFingerLogic
|
||||||
@@ -41,7 +44,7 @@ class CFingerLogic
|
|||||||
public:
|
public:
|
||||||
CFingerLogic(class CMain *pMain);
|
CFingerLogic(class CMain *pMain);
|
||||||
void Init(CFingerPrint *pFingerPrint);
|
void Init(CFingerPrint *pFingerPrint);
|
||||||
void OnFingerInterrupt(bool finger);
|
void OnFinger(bool finger);
|
||||||
|
|
||||||
bool FingerSlot(uint16_t index);
|
bool FingerSlot(uint16_t index);
|
||||||
bool FingerSlot(uint16_t index, bool value);
|
bool FingerSlot(uint16_t index, bool value);
|
||||||
@@ -50,6 +53,7 @@ public:
|
|||||||
void InitFinger();
|
void InitFinger();
|
||||||
static void InitFinger_OnVerifyPassword(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
static void InitFinger_OnVerifyPassword(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
||||||
static void InitFinger_OnReadSystemParameters(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param);
|
static void InitFinger_OnReadSystemParameters(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param);
|
||||||
|
static void InitFinger_OnSetSystemSecurityLevel(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
||||||
static void InitFinger_OnGetTemplates(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
static void InitFinger_OnGetTemplates(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
||||||
static void InitFinger_OnReadTemplateMap(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen);
|
static void InitFinger_OnReadTemplateMap(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen);
|
||||||
void InitFinger_VerifyTemplates();
|
void InitFinger_VerifyTemplates();
|
||||||
@@ -76,6 +80,9 @@ public:
|
|||||||
static void EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
static void EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
||||||
static void EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen);
|
static void EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen);
|
||||||
|
|
||||||
|
void SetSecurityLevel(int securityLevel);
|
||||||
|
static void SetSecurityLevel_OnSetSystemSecurityLevel(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
|
||||||
|
|
||||||
CMain &Main() { return *m_pMain; }
|
CMain &Main() { return *m_pMain; }
|
||||||
CFingerPrint &FingerPrint() { return *m_pFingerPrint; }
|
CFingerPrint &FingerPrint() { return *m_pFingerPrint; }
|
||||||
|
|
||||||
@@ -84,11 +91,13 @@ private:
|
|||||||
void PowerOff();
|
void PowerOff();
|
||||||
void PowerOn();
|
void PowerOn();
|
||||||
void SetState(FingerLogicState state);
|
void SetState(FingerLogicState state);
|
||||||
|
Timer m_InitTimer;
|
||||||
Timer m_PowerOffTimer;
|
Timer m_PowerOffTimer;
|
||||||
|
|
||||||
CMain *m_pMain;
|
CMain *m_pMain;
|
||||||
CFingerPrint *m_pFingerPrint;
|
CFingerPrint *m_pFingerPrint;
|
||||||
FingerLogicState m_State;
|
FingerLogicState m_State;
|
||||||
|
int m_ErrorCounter;
|
||||||
bool m_Finger;
|
bool m_Finger;
|
||||||
|
|
||||||
CFingerSystemParameters m_FingerParams;
|
CFingerSystemParameters m_FingerParams;
|
||||||
@@ -97,7 +106,6 @@ private:
|
|||||||
|
|
||||||
int32_t m_iBuffer;
|
int32_t m_iBuffer;
|
||||||
|
|
||||||
Timer m_Timer;
|
|
||||||
void *m_fnUserCallback;
|
void *m_fnUserCallback;
|
||||||
void *m_pUserData;
|
void *m_pUserData;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,6 +69,36 @@ enum FingerPrintError
|
|||||||
ERROR_COMMUNICATIONPORT = 0x1D, // fail to operate the communication port
|
ERROR_COMMUNICATIONPORT = 0x1D, // fail to operate the communication port
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FINGERPRINT_BAUD_REG_ADDR 0x4 //!< BAUDRATE register address
|
||||||
|
#define FINGERPRINT_BAUDRATE_9600 0x1 //!< UART baud 9600
|
||||||
|
#define FINGERPRINT_BAUDRATE_19200 0x2 //!< UART baud 19200
|
||||||
|
#define FINGERPRINT_BAUDRATE_28800 0x3 //!< UART baud 28800
|
||||||
|
#define FINGERPRINT_BAUDRATE_38400 0x4 //!< UART baud 38400
|
||||||
|
#define FINGERPRINT_BAUDRATE_48000 0x5 //!< UART baud 48000
|
||||||
|
#define FINGERPRINT_BAUDRATE_57600 0x6 //!< UART baud 57600
|
||||||
|
#define FINGERPRINT_BAUDRATE_67200 0x7 //!< UART baud 67200
|
||||||
|
#define FINGERPRINT_BAUDRATE_76800 0x8 //!< UART baud 76800
|
||||||
|
#define FINGERPRINT_BAUDRATE_86400 0x9 //!< UART baud 86400
|
||||||
|
#define FINGERPRINT_BAUDRATE_96000 0xA //!< UART baud 96000
|
||||||
|
#define FINGERPRINT_BAUDRATE_105600 0xB //!< UART baud 105600
|
||||||
|
#define FINGERPRINT_BAUDRATE_115200 0xC //!< UART baud 115200
|
||||||
|
|
||||||
|
#define FINGERPRINT_SECURITY_REG_ADDR 0x5 //!< Security level register address
|
||||||
|
// The safety level is 1 The highest rate of false recognition , The rejection
|
||||||
|
// rate is the lowest . The safety level is 5 The lowest tate of false
|
||||||
|
// recognition, The rejection rate is the highest .
|
||||||
|
#define FINGERPRINT_SECURITY_LEVEL_1 0X1 //!< Security level 1
|
||||||
|
#define FINGERPRINT_SECURITY_LEVEL_2 0X2 //!< Security level 2
|
||||||
|
#define FINGERPRINT_SECURITY_LEVEL_3 0X3 //!< Security level 3
|
||||||
|
#define FINGERPRINT_SECURITY_LEVEL_4 0X4 //!< Security level 4
|
||||||
|
#define FINGERPRINT_SECURITY_LEVEL_5 0X5 //!< Security level 5
|
||||||
|
|
||||||
|
#define FINGERPRINT_PACKET_REG_ADDR 0x6 //!< Packet size register address
|
||||||
|
#define FINGERPRINT_PACKET_SIZE_32 0X0 //!< Packet size is 32 Byte
|
||||||
|
#define FINGERPRINT_PACKET_SIZE_64 0X1 //!< Packet size is 64 Byte
|
||||||
|
#define FINGERPRINT_PACKET_SIZE_128 0X2 //!< Packet size is 128 Byte
|
||||||
|
#define FINGERPRINT_PACKET_SIZE_256 0X3 //!< Packet size is 256 Byte
|
||||||
|
|
||||||
enum RecvStates
|
enum RecvStates
|
||||||
{
|
{
|
||||||
RECV_DONE = 0,
|
RECV_DONE = 0,
|
||||||
@@ -92,6 +122,7 @@ typedef void (CFingerPrint::*RecvCallback)(FingerPrintIdent ident, uint8_t *pDat
|
|||||||
|
|
||||||
typedef void (*VerifyPasswordCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
typedef void (*VerifyPasswordCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
||||||
typedef void (*ReadSystemParametersCallback)(void *pUser, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param);
|
typedef void (*ReadSystemParametersCallback)(void *pUser, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param);
|
||||||
|
typedef void (*SetSystemParameterCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
||||||
typedef void (*ReadImageCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
typedef void (*ReadImageCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
||||||
typedef void (*ConvertImageCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
typedef void (*ConvertImageCallback)(void *pUser, FingerPrintError error, const char *errorStr);
|
||||||
typedef void (*SearchTemplateCallback)(void *pUser, FingerPrintError error, const char *errorStr, int16_t position, int16_t score);
|
typedef void (*SearchTemplateCallback)(void *pUser, FingerPrintError error, const char *errorStr, int16_t position, int16_t score);
|
||||||
@@ -112,11 +143,13 @@ public:
|
|||||||
|
|
||||||
int VerifyPassword();
|
int VerifyPassword();
|
||||||
int ReadSystemParameters(uint8_t aResponse[17]);
|
int ReadSystemParameters(uint8_t aResponse[17]);
|
||||||
|
int SetSystemParameter(uint8_t regAddr, uint8_t value);
|
||||||
int DeleteTemplate(uint16_t positionStart, uint16_t count);
|
int DeleteTemplate(uint16_t positionStart, uint16_t count);
|
||||||
int EmptyDatabase();
|
int EmptyDatabase();
|
||||||
|
|
||||||
int AsyncVerifyPassword(VerifyPasswordCallback fnCallback, void *pUser);
|
int AsyncVerifyPassword(VerifyPasswordCallback fnCallback, void *pUser);
|
||||||
int AsyncReadSystemParameters(ReadSystemParametersCallback fnCallback, void *pUser);
|
int AsyncReadSystemParameters(ReadSystemParametersCallback fnCallback, void *pUser);
|
||||||
|
int AsyncSetSystemParameter(SetSystemParameterCallback fnCallback, void *pUser, uint8_t regAddr, uint8_t value);
|
||||||
int AsyncReadImage(ReadImageCallback fnCallback, void *pUser);
|
int AsyncReadImage(ReadImageCallback fnCallback, void *pUser);
|
||||||
int AsyncConvertImage(ConvertImageCallback fnCallback, void *pUser, uint8_t numCharBuffer);
|
int AsyncConvertImage(ConvertImageCallback fnCallback, void *pUser, uint8_t numCharBuffer);
|
||||||
int AsyncSearchTemplate(SearchTemplateCallback fnCallback, void *pUser, uint8_t numCharBuffer, uint16_t positionStart, uint16_t numTemplates);
|
int AsyncSearchTemplate(SearchTemplateCallback fnCallback, void *pUser, uint8_t numCharBuffer, uint16_t positionStart, uint16_t numTemplates);
|
||||||
@@ -130,6 +163,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void OnAsyncVerifyPassword(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
void OnAsyncVerifyPassword(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
||||||
void OnAsyncReadSystemParameters(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
void OnAsyncReadSystemParameters(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
||||||
|
void OnAsyncSetSystemParameter(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
||||||
void OnAsyncReadImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
void OnAsyncReadImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
||||||
void OnAsyncConvertImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
void OnAsyncConvertImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
||||||
void OnAsyncSearchTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
void OnAsyncSearchTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
|
||||||
|
|||||||
@@ -50,6 +50,31 @@ int CFingerPrint::ReadSystemParameters(uint8_t aResponse[17])
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CFingerPrint::SetSystemParameter(uint8_t regAddr, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t aPayload[] = {
|
||||||
|
COMMAND_SETSYSPARA,
|
||||||
|
regAddr,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
|
||||||
|
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
|
||||||
|
|
||||||
|
FingerPrintIdent ident;
|
||||||
|
uint8_t aResponse[1];
|
||||||
|
int ret = Recv(&ident, aResponse, sizeof(aResponse));
|
||||||
|
m_RecvState = RECV_DROP;
|
||||||
|
|
||||||
|
if(ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if(ident != IDENT_ACK)
|
||||||
|
return ERROR_COMMUNICATION;
|
||||||
|
|
||||||
|
uint8_t error = aResponse[0];
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int CFingerPrint::DeleteTemplate(uint16_t positionStart, uint16_t count)
|
int CFingerPrint::DeleteTemplate(uint16_t positionStart, uint16_t count)
|
||||||
{
|
{
|
||||||
uint8_t aPayload[] = {
|
uint8_t aPayload[] = {
|
||||||
|
|||||||
@@ -90,6 +90,40 @@ void CFingerPrint::OnAsyncReadSystemParameters(FingerPrintIdent ident, uint8_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CFingerPrint::AsyncSetSystemParameter(SetSystemParameterCallback fnCallback, void *pUser, uint8_t regAddr, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t aPayload[] = {
|
||||||
|
COMMAND_SETSYSPARA,
|
||||||
|
regAddr,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
|
||||||
|
m_fnRecvCallback = &CFingerPrint::OnAsyncSetSystemParameter;
|
||||||
|
m_fnUserCallback = (void *)fnCallback;
|
||||||
|
m_pUserData = pUser;
|
||||||
|
|
||||||
|
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFingerPrint::OnAsyncSetSystemParameter(FingerPrintIdent ident, uint8_t *pData, uint16_t length)
|
||||||
|
{
|
||||||
|
m_RecvState = RECV_DROP;
|
||||||
|
|
||||||
|
if(ident != IDENT_ACK)
|
||||||
|
{
|
||||||
|
((SetSystemParameterCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "The received packet is no ack packet!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t error = pData[0];
|
||||||
|
const char *errorStr = ExplainFingerError(error);
|
||||||
|
|
||||||
|
((SetSystemParameterCallback)m_fnUserCallback)(m_pUserData, (FingerPrintError)error, errorStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int CFingerPrint::AsyncReadImage(ReadImageCallback fnCallback, void *pUser)
|
int CFingerPrint::AsyncReadImage(ReadImageCallback fnCallback, void *pUser)
|
||||||
{
|
{
|
||||||
uint8_t aPayload[] = {
|
uint8_t aPayload[] = {
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ CSettings::CSettings()
|
|||||||
strcpy(m_aPSK, "");
|
strcpy(m_aPSK, "");
|
||||||
m_DHCP = true;
|
m_DHCP = true;
|
||||||
strcpy(m_aHostname, "safeweb");
|
strcpy(m_aHostname, "safeweb");
|
||||||
m_Address = IPAddress(0, 0, 0, 0);
|
m_Address = IpAddress(0, 0, 0, 0);
|
||||||
m_Netmask = IPAddress(0, 0, 0, 0);
|
m_Netmask = IpAddress(0, 0, 0, 0);
|
||||||
m_Gateway = IPAddress(0, 0, 0, 0);
|
m_Gateway = IpAddress(0, 0, 0, 0);
|
||||||
memset(m_aLockCode, 0, sizeof(m_aLockCode));
|
memset(m_aLockCode, 0, sizeof(m_aLockCode));
|
||||||
|
m_SecurityLevel = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSettings::Exists()
|
bool CSettings::Exists()
|
||||||
@@ -53,6 +54,11 @@ bool CSettings::Load()
|
|||||||
m_Netmask = network["netmask"].as<const char *>();
|
m_Netmask = network["netmask"].as<const char *>();
|
||||||
m_Gateway = network["gateway"].as<const char *>();
|
m_Gateway = network["gateway"].as<const char *>();
|
||||||
|
|
||||||
|
JsonObject mqtt = doc["mqtt"];
|
||||||
|
strncpy(m_aMqttName, mqtt["client_name"], sizeof(m_aMqttName));
|
||||||
|
m_MqttURL = Url("mqtt", mqtt["username"], mqtt["password"], mqtt["host"], mqtt["port"]);
|
||||||
|
m_MqttUnlock = bool(mqtt["unlock"]);
|
||||||
|
|
||||||
JsonArray lockCode = doc["lock_code"];
|
JsonArray lockCode = doc["lock_code"];
|
||||||
uint8_t tmp = min(lockCode.size(), sizeof(m_aLockCode));
|
uint8_t tmp = min(lockCode.size(), sizeof(m_aLockCode));
|
||||||
for(uint8_t i = 0; i < tmp; i++)
|
for(uint8_t i = 0; i < tmp; i++)
|
||||||
@@ -73,6 +79,8 @@ bool CSettings::Load()
|
|||||||
m_FingerPrints[finger.m_FingerNum] = finger;
|
m_FingerPrints[finger.m_FingerNum] = finger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_SecurityLevel = min(max(int(doc["security_level"]), 1), 5);
|
||||||
|
|
||||||
delete[] pData;
|
delete[] pData;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -93,6 +101,14 @@ void CSettings::Save()
|
|||||||
network["netmask"] = m_Netmask.toString();
|
network["netmask"] = m_Netmask.toString();
|
||||||
network["gateway"] = m_Gateway.toString();
|
network["gateway"] = m_Gateway.toString();
|
||||||
|
|
||||||
|
JsonObject mqtt = doc.createNestedObject("mqtt");
|
||||||
|
mqtt["client_name"] = m_aMqttName;
|
||||||
|
mqtt["host"] = m_MqttURL.Host;
|
||||||
|
mqtt["port"] = m_MqttURL.getPort();
|
||||||
|
mqtt["username"] = m_MqttURL.User;
|
||||||
|
mqtt["password"] = m_MqttURL.Password;
|
||||||
|
mqtt["unlock"] = m_MqttUnlock;
|
||||||
|
|
||||||
JsonArray lockCode = doc.createNestedArray("lock_code");
|
JsonArray lockCode = doc.createNestedArray("lock_code");
|
||||||
for(uint8_t i = 0; i < sizeof(m_aLockCode); i++)
|
for(uint8_t i = 0; i < sizeof(m_aLockCode); i++)
|
||||||
lockCode.add(m_aLockCode[i]);
|
lockCode.add(m_aLockCode[i]);
|
||||||
@@ -112,6 +128,8 @@ void CSettings::Save()
|
|||||||
obj["digest"] = String(aHexDigest);
|
obj["digest"] = String(aHexDigest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc["security_level"] = m_SecurityLevel;
|
||||||
|
|
||||||
String docString;
|
String docString;
|
||||||
serializeJsonPretty(doc, docString);
|
serializeJsonPretty(doc, docString);
|
||||||
fileSetContent(APP_SETTINGS_FILE, docString);
|
fileSetContent(APP_SETTINGS_FILE, docString);
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ public:
|
|||||||
IpAddress m_Netmask;
|
IpAddress m_Netmask;
|
||||||
IpAddress m_Gateway;
|
IpAddress m_Gateway;
|
||||||
|
|
||||||
|
Url m_MqttURL;
|
||||||
|
char m_aMqttName[64];
|
||||||
|
bool m_MqttUnlock;
|
||||||
|
|
||||||
uint8_t m_aLockCode[8];
|
uint8_t m_aLockCode[8];
|
||||||
|
|
||||||
struct CFingerPrint
|
struct CFingerPrint
|
||||||
@@ -33,6 +37,8 @@ public:
|
|||||||
uint8_t m_aDigest[SHA256_SIZE];
|
uint8_t m_aDigest[SHA256_SIZE];
|
||||||
};
|
};
|
||||||
HashMap<uint16_t, CFingerPrint> m_FingerPrints;
|
HashMap<uint16_t, CFingerPrint> m_FingerPrints;
|
||||||
|
|
||||||
|
int m_SecurityLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,27 +1,60 @@
|
|||||||
#include <SmingCore.h>
|
#include <SmingCore.h>
|
||||||
#include "FingerPrint.h"
|
#include "FingerPrint.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
HardwareSerial Serial1(UART_ID_1);
|
HardwareSerial Serial1(UART_ID_1);
|
||||||
NtpClient ntpClient("at.pool.ntp.org", 3600);
|
NtpClient ntpClient("at.pool.ntp.org", 3600);
|
||||||
|
|
||||||
void IRAM_ATTR OnFingerInterrupt()
|
static SimpleTimer procTimer;
|
||||||
|
volatile uint8_t procTimerLoops = 0;
|
||||||
|
void OnProcTimer()
|
||||||
{
|
{
|
||||||
// LOW = FINGER, HIGH = NO FINGER
|
const bool finger = !digitalRead(FINGER_DETECT_PIN);
|
||||||
bool status = digitalRead(FINGER_DETECT_PIN);
|
const bool unlocked = !digitalRead(SAFELOCK_DETECT_PIN);
|
||||||
|
const bool opened = digitalRead(DOOR_DETECT_PIN);
|
||||||
|
static Debounce Finger(finger);
|
||||||
|
static Debounce Unlocked(unlocked);
|
||||||
|
static Debounce Opened(opened);
|
||||||
|
|
||||||
g_Main.OnFingerInterrupt(!status);
|
int8_t fingerEdge = Finger.debounce(finger);
|
||||||
|
if(fingerEdge)
|
||||||
|
g_Main.OnFinger(fingerEdge & 1);
|
||||||
|
|
||||||
|
int8_t unlockedEdge = Unlocked.debounce(unlocked);
|
||||||
|
if(unlockedEdge)
|
||||||
|
g_Main.OnLock(unlockedEdge & 1);
|
||||||
|
|
||||||
|
int8_t openedEdge = Finger.debounce(opened);
|
||||||
|
if(openedEdge)
|
||||||
|
g_Main.OnDoor(openedEdge & 1);
|
||||||
|
|
||||||
|
procTimerLoops++;
|
||||||
|
if(procTimerLoops > 25) // 250ms
|
||||||
|
procTimer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR OnLevelChangeISR()
|
||||||
|
{
|
||||||
|
procTimerLoops = 0;
|
||||||
|
procTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ready()
|
void ready()
|
||||||
{
|
{
|
||||||
debugf("READY!");
|
debugf("READY!");
|
||||||
|
|
||||||
gpio_pin_wakeup_enable(GPIO_ID_PIN(FINGER_DETECT_PIN), GPIO_PIN_INTR_LOLEVEL);
|
|
||||||
|
|
||||||
g_Main.Init(Serial);
|
g_Main.Init(Serial);
|
||||||
|
|
||||||
attachInterrupt(FINGER_DETECT_PIN, OnFingerInterrupt, CHANGE);
|
gpio_pin_wakeup_enable(GPIO_ID_PIN(FINGER_DETECT_PIN), GPIO_PIN_INTR_LOLEVEL);
|
||||||
|
gpio_pin_wakeup_enable(GPIO_ID_PIN(SAFELOCK_DETECT_PIN), GPIO_PIN_INTR_LOLEVEL);
|
||||||
|
gpio_pin_wakeup_enable(GPIO_ID_PIN(DOOR_DETECT_PIN), GPIO_PIN_INTR_HILEVEL);
|
||||||
|
|
||||||
|
attachInterrupt(FINGER_DETECT_PIN, OnLevelChangeISR, CHANGE);
|
||||||
|
attachInterrupt(SAFELOCK_DETECT_PIN, OnLevelChangeISR, CHANGE);
|
||||||
|
attachInterrupt(DOOR_DETECT_PIN, OnLevelChangeISR, CHANGE);
|
||||||
|
|
||||||
|
procTimer.initializeMs<10>(OnProcTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
@@ -45,7 +78,7 @@ void init()
|
|||||||
|
|
||||||
pinMode(FINGER_DETECT_PIN, INPUT);
|
pinMode(FINGER_DETECT_PIN, INPUT);
|
||||||
pinMode(SAFELOCK_DETECT_PIN, INPUT);
|
pinMode(SAFELOCK_DETECT_PIN, INPUT);
|
||||||
pinMode(DOOR_DETECT_PIN, INPUT);
|
pinMode(DOOR_DETECT_PIN, INPUT_PULLUP);
|
||||||
|
|
||||||
// mount spiffs
|
// mount spiffs
|
||||||
spiffs_mount();
|
spiffs_mount();
|
||||||
|
|||||||
357
app/main.cpp
357
app/main.cpp
@@ -1,6 +1,10 @@
|
|||||||
#include <SmingCore.h>
|
#include <SmingCore.h>
|
||||||
|
#include <Network/Mqtt/MqttBuffer.h>
|
||||||
#include <Data/WebHelpers/base64.h>
|
#include <Data/WebHelpers/base64.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <MultipartParser.h>
|
||||||
|
#include <HttpMultipartResource.h>
|
||||||
|
#include <OtaUpgradeStream.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
@@ -10,17 +14,98 @@ CMain::CMain() : m_FingerLogic(this)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void STAGotIP(IpAddress ip, IpAddress mask, IpAddress gateway)
|
static void fileUploadMapper(HttpFiles& files)
|
||||||
{
|
{
|
||||||
debugf("GOTIP - IP: %s, MASK: %s, GW: %s\n", ip.toString().c_str(), mask.toString().c_str(),
|
files["firmware"] = new OtaUpgradeStream;
|
||||||
gateway.toString().c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void STADisconnect(const String& ssid, MacAddress bssid, WifiDisconnectReason reason)
|
static int onMessageDelivered(MqttClient& client, mqtt_message_t* message)
|
||||||
{
|
{
|
||||||
|
Serial1 << _F("Message with id ") << message->puback.message_id << _F(" and QoS ") << message->puback.qos
|
||||||
|
<< _F(" was delivered successfully.") << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for messages, arrived from MQTT server
|
||||||
|
static int onMessageReceived(MqttClient& client, mqtt_message_t* message)
|
||||||
|
{
|
||||||
|
Serial1 << _F("Received: ") << MqttBuffer(message->publish.topic_name) << ':' << endl;
|
||||||
|
Serial1 << '\t' << MqttBuffer(message->publish.content) << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::OnStationGotIP(IpAddress ip, IpAddress mask, IpAddress gateway)
|
||||||
|
{
|
||||||
|
m_StationConnected = true;
|
||||||
|
debugf("GOTIP - IP: %s, MASK: %s, GW: %s\n", ip.toString().c_str(), mask.toString().c_str(), gateway.toString().c_str());
|
||||||
|
StartMqttClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::OnStationDisconnect(const String& ssid, MacAddress bssid, WifiDisconnectReason reason)
|
||||||
|
{
|
||||||
|
m_StationConnected = false;
|
||||||
debugf("DISCONNECT - SSID: %s, REASON: %d", ssid.c_str(), WifiEvents.getDisconnectReasonDesc(reason).c_str());
|
debugf("DISCONNECT - SSID: %s, REASON: %d", ssid.c_str(), WifiEvents.getDisconnectReasonDesc(reason).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CMain::MqttOnConnect(MqttClient& client, mqtt_message_t* message)
|
||||||
|
{
|
||||||
|
debugf("MQTT Connected!");
|
||||||
|
|
||||||
|
MqttSendMessage("safeweb/status", "online");
|
||||||
|
|
||||||
|
MqttSendDescription();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::MqttOnDisconnect(TcpClient& client, bool flag)
|
||||||
|
{
|
||||||
|
if(flag == true)
|
||||||
|
debugf("MQTT Broker Disconnected!!");
|
||||||
|
else
|
||||||
|
debugf("MQTT Broker Unreachable!!");
|
||||||
|
|
||||||
|
// Restart connection attempt after few seconds
|
||||||
|
if(!m_StationConnected)
|
||||||
|
m_MqttTimer.initializeMs(2 * 1000, TimerDelegate(&CMain::StartMqttClient, this)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::MqttSendDescription()
|
||||||
|
{
|
||||||
|
if(m_Mqtt.getConnectionState() != eTCS_Connected) {
|
||||||
|
StartMqttClient(); // Auto reconnect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::MqttSendMessage(const char *topic, const char *msg)
|
||||||
|
{
|
||||||
|
if(m_Mqtt.getConnectionState() != eTCS_Connected) {
|
||||||
|
StartMqttClient(); // Auto reconnect
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Mqtt.publish(topic, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::StartMqttClient()
|
||||||
|
{
|
||||||
|
m_MqttTimer.stop();
|
||||||
|
if(!m_StationConnected || !Settings().m_MqttURL.Port || !Settings().m_MqttURL.Host)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!m_Mqtt.setWill("safeweb/status", "offline", MqttClient::getFlags(MQTT_QOS_AT_LEAST_ONCE, MQTT_RETAIN_TRUE))) {
|
||||||
|
debugf("Unable to mqtt.setWill");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Mqtt.setEventHandler(MQTT_TYPE_PUBACK, onMessageDelivered);
|
||||||
|
|
||||||
|
m_Mqtt.setConnectedHandler(MqttDelegate(&CMain::MqttOnConnect, this));
|
||||||
|
|
||||||
|
m_Mqtt.setCompleteDelegate(TcpClientCompleteDelegate(&CMain::MqttOnDisconnect, this));
|
||||||
|
m_Mqtt.setMessageHandler(onMessageReceived);
|
||||||
|
|
||||||
|
m_Mqtt.connect(Settings().m_MqttURL, Settings().m_aMqttName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CMain::Init(HardwareSerial &serial)
|
void CMain::Init(HardwareSerial &serial)
|
||||||
{
|
{
|
||||||
m_Settings.Load();
|
m_Settings.Load();
|
||||||
@@ -45,27 +130,61 @@ void CMain::Init(HardwareSerial &serial)
|
|||||||
WifiAccessPoint.enable(true);
|
WifiAccessPoint.enable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
WifiEvents.onStationGotIP(STAGotIP);
|
WifiEvents.onStationGotIP(StationGotIPDelegate(&CMain::OnStationGotIP, this));
|
||||||
WifiEvents.onStationDisconnect(STADisconnect);
|
WifiEvents.onStationDisconnect(StationDisconnectDelegate(&CMain::OnStationDisconnect, this));
|
||||||
|
|
||||||
m_FTP.listen(21);
|
m_FTP.listen(21);
|
||||||
m_FTP.addUser(m_Settings.m_aUsername, m_Settings.m_aPassword);
|
m_FTP.addUser(m_Settings.m_aUsername, m_Settings.m_aPassword);
|
||||||
|
|
||||||
|
HttpServerSettings settings;
|
||||||
|
settings.closeOnContentError = false;
|
||||||
|
settings.keepAliveSeconds = 5;
|
||||||
|
|
||||||
|
m_HttpServer.configure(settings);
|
||||||
|
m_HttpServer.setBodyParser(MIME_JSON, bodyToStringParser);
|
||||||
|
m_HttpServer.setBodyParser(MIME_FORM_MULTIPART, formMultipartParser);
|
||||||
m_HttpServer.listen(80);
|
m_HttpServer.listen(80);
|
||||||
m_HttpServer.setBodyParser("application/json", bodyToStringParser);
|
|
||||||
|
|
||||||
m_HttpServer.paths.set("/api", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
|
m_HttpServer.paths.set("/api/state", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
m_HttpServer.paths.set("/api/dashboard", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api/dashboard", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
m_HttpServer.paths.set("/api/fingerprint", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api/fingerprint", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
m_HttpServer.paths.set("/api/fingerprint/label", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api/fingerprint/label", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
m_HttpServer.paths.set("/api/fingerprint/delete", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api/fingerprint/delete", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
m_HttpServer.paths.set("/api/fingerprint/enroll", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api/fingerprint/enroll", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
|
m_HttpServer.paths.set("/api/fingerprint/security", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
m_HttpServer.paths.set("/api/unlock", HttpPathDelegate(&CMain::HttpOnApi, this));
|
m_HttpServer.paths.set("/api/unlock", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
|
m_HttpServer.paths.set("/api/reset", HttpPathDelegate(&CMain::HttpOnApi, this));
|
||||||
|
m_HttpServer.paths.set("/upgrade", new HttpMultipartResource(fileUploadMapper, HttpResourceDelegate(&CMain::HttpOnUpload, this)));
|
||||||
|
|
||||||
m_HttpServer.paths.setDefault(HttpPathDelegate(&CMain::HttpOnFile, this));
|
m_HttpServer.paths.setDefault(HttpPathDelegate(&CMain::HttpOnFile, this));
|
||||||
|
|
||||||
m_FingerPrint.Init(serial, 0xFFFFFFFF, 0x00000000);
|
m_FingerPrint.Init(serial, 0xFFFFFFFF, 0x00000000);
|
||||||
m_FingerLogic.Init(&m_FingerPrint);
|
m_FingerLogic.Init(&m_FingerPrint);
|
||||||
|
|
||||||
|
m_LightSleepTimer.initializeMs(60 * 1000, TimerDelegate(&CMain::EnterLightSleep, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wakeupCallback() {
|
||||||
|
debugf("Wakeing up @ %lu", millis());
|
||||||
|
debugf("Wakeing up @ %s", SystemClock.getSystemTimeString().c_str());
|
||||||
|
wifi_fpm_close();
|
||||||
|
wifi_set_opmode(STATION_MODE);
|
||||||
|
wifi_station_connect();
|
||||||
|
system_soft_wdt_feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::EnterLightSleep()
|
||||||
|
{
|
||||||
|
debugf("Going to sleep @ %lu", millis());
|
||||||
|
debugf("Going to sleep @ %s", SystemClock.getSystemTimeString().c_str());
|
||||||
|
wifi_station_disconnect();
|
||||||
|
wifi_set_opmode(NULL_MODE);
|
||||||
|
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
|
||||||
|
wifi_fpm_open();
|
||||||
|
wifi_fpm_set_wakeup_cb(wakeupCallback);
|
||||||
|
wifi_fpm_do_sleep(0xFFFFFFF);
|
||||||
|
system_soft_wdt_feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMain::HttpAuthorized(HttpRequest &request, HttpResponse &response)
|
bool CMain::HttpAuthorized(HttpRequest &request, HttpResponse &response)
|
||||||
@@ -124,7 +243,6 @@ void CMain::HttpOnApi(HttpRequest &request, HttpResponse &response)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HttpStatus status = HandleApi(request.method, endpoint, jsonReq, jsonResp);
|
HttpStatus status = HandleApi(request.method, endpoint, jsonReq, jsonResp);
|
||||||
if(status != HTTP_STATUS_OK)
|
if(status != HTTP_STATUS_OK)
|
||||||
{
|
{
|
||||||
@@ -140,73 +258,96 @@ void CMain::HttpOnApi(HttpRequest &request, HttpResponse &response)
|
|||||||
|
|
||||||
HttpStatus CMain::HandleApi(HttpMethod method, String endpoint, JsonDocument &req, JsonDocument &resp)
|
HttpStatus CMain::HandleApi(HttpMethod method, String endpoint, JsonDocument &req, JsonDocument &resp)
|
||||||
{
|
{
|
||||||
String test;
|
if(endpoint == "state" || endpoint == "dashboard")
|
||||||
serializeJsonPretty(req, test);
|
|
||||||
|
|
||||||
debugf("request: %s\n", test.c_str());
|
|
||||||
|
|
||||||
if(endpoint == "dashboard")
|
|
||||||
{
|
{
|
||||||
if(method != HTTP_GET) return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
if(method != HTTP_GET) return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
|
|
||||||
JsonObject lock = resp.createNestedObject("lock");
|
JsonObject state = resp.createNestedObject("state");
|
||||||
lock["locked"] = true;
|
state["unlocked"] = (bool)!digitalRead(SAFELOCK_DETECT_PIN);
|
||||||
|
state["opened"] = (bool)digitalRead(DOOR_DETECT_PIN);
|
||||||
|
state["battery"] = (system_adc_read() / 1024.f) / 0.237;
|
||||||
|
|
||||||
JsonObject door = resp.createNestedObject("door");
|
if(endpoint == "dashboard")
|
||||||
door["closed"] = true;
|
|
||||||
|
|
||||||
JsonObject battery = resp.createNestedObject("battery");
|
|
||||||
debugf("adc: %d\n", system_adc_read());
|
|
||||||
battery["voltage"] = (system_adc_read() / 1024.f) / 0.23;
|
|
||||||
battery["color"] = "success";
|
|
||||||
if(battery["voltage"] < 3.6f)
|
|
||||||
battery["color"] = "warning";
|
|
||||||
|
|
||||||
JsonObject network = resp.createNestedObject("network");
|
|
||||||
if(WifiStation.isEnabled())
|
|
||||||
{
|
{
|
||||||
network["type"] = "Station";
|
JsonObject network = resp.createNestedObject("network");
|
||||||
network["ssid"] = WifiStation.getSSID();
|
if(WifiStation.isEnabled())
|
||||||
network["channel"] = WifiStation.getChannel();
|
{
|
||||||
network["dhcp"] = WifiStation.isEnabledDHCP();
|
network["type"] = "Station";
|
||||||
network["rssi"] = WifiStation.getRssi();
|
network["ssid"] = WifiStation.getSSID();
|
||||||
network["signal"] = Rssi2Quality(WifiStation.getRssi());
|
network["channel"] = WifiStation.getChannel();
|
||||||
network["address"] = WifiStation.getIP().toString();
|
network["dhcp"] = WifiStation.isEnabledDHCP();
|
||||||
}
|
network["rssi"] = WifiStation.getRssi();
|
||||||
else
|
network["signal"] = Rssi2Quality(network["rssi"]);
|
||||||
{
|
network["address"] = WifiStation.getIP().toString();
|
||||||
network["type"] = "Access Point";
|
}
|
||||||
network["ssid"] = WifiAccessPoint.getSSID();
|
else
|
||||||
network["channel"] = WifiStation.getChannel();
|
{
|
||||||
network["dhcp"] = true;
|
network["type"] = "Access Point";
|
||||||
network["address"] = WifiAccessPoint.getIP().toString();
|
network["ssid"] = WifiAccessPoint.getSSID();
|
||||||
|
network["channel"] = WifiStation.getChannel();
|
||||||
|
network["dhcp"] = true;
|
||||||
|
network["address"] = WifiAccessPoint.getIP().toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(endpoint == "unlock")
|
else if(endpoint == "unlock")
|
||||||
{
|
{
|
||||||
if(method != HTTP_POST) return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
if(method != HTTP_POST) return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
|
|
||||||
LockUnlock();
|
if(!req.containsKey("unlock"))
|
||||||
resp["success"] = "true";
|
return HTTP_STATUS_BAD_REQUEST;
|
||||||
|
|
||||||
|
if(req["unlock"])
|
||||||
|
LockUnlock();
|
||||||
|
}
|
||||||
|
else if(endpoint == "reset")
|
||||||
|
{
|
||||||
|
if(method != HTTP_POST) return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
|
|
||||||
|
if(!req.containsKey("reset"))
|
||||||
|
return HTTP_STATUS_BAD_REQUEST;
|
||||||
|
|
||||||
|
if(req["reset"])
|
||||||
|
System.restart(500);
|
||||||
}
|
}
|
||||||
else if(endpoint == "fingerprint")
|
else if(endpoint == "fingerprint")
|
||||||
{
|
{
|
||||||
if(method != HTTP_GET) return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
if(method == HTTP_GET)
|
||||||
|
|
||||||
JsonArray fingerprints = resp.createNestedArray("fingerprints");
|
|
||||||
uint16_t tmp = Settings().m_FingerPrints.count();
|
|
||||||
for(uint16_t i = 0; i < tmp; i++)
|
|
||||||
{
|
{
|
||||||
JsonObject obj = fingerprints.createNestedObject();
|
JsonArray fingerprints = resp.createNestedArray("fingerprints");
|
||||||
const CSettings::CFingerPrint &finger = Settings().m_FingerPrints.valueAt(i);
|
uint16_t tmp = Settings().m_FingerPrints.count();
|
||||||
|
for(uint16_t i = 0; i < tmp; i++)
|
||||||
|
{
|
||||||
|
JsonObject obj = fingerprints.createNestedObject();
|
||||||
|
const CSettings::CFingerPrint &finger = Settings().m_FingerPrints.valueAt(i);
|
||||||
|
|
||||||
obj["num"] = finger.m_FingerNum;
|
obj["num"] = finger.m_FingerNum;
|
||||||
obj["label"] = String(finger.m_aLabel);
|
obj["label"] = String(finger.m_aLabel);
|
||||||
|
|
||||||
char aHexDigest[SHA256_SIZE*2+1];
|
char aHexDigest[SHA256_SIZE*2+1];
|
||||||
bytes2hex(finger.m_aDigest, sizeof(finger.m_aDigest), aHexDigest, sizeof(aHexDigest));
|
bytes2hex(finger.m_aDigest, sizeof(finger.m_aDigest), aHexDigest, sizeof(aHexDigest));
|
||||||
obj["digest"] = String(aHexDigest);
|
obj["digest"] = String(aHexDigest);
|
||||||
|
}
|
||||||
|
resp["securityLevel"] = Settings().m_SecurityLevel;
|
||||||
}
|
}
|
||||||
|
else if(method == HTTP_POST)
|
||||||
|
{
|
||||||
|
if(!req.containsKey("securityLevel"))
|
||||||
|
return HTTP_STATUS_BAD_REQUEST;
|
||||||
|
|
||||||
|
int newLevel = req["securityLevel"].as<int>();
|
||||||
|
if(newLevel > FINGERPRINT_SECURITY_LEVEL_5 || newLevel < FINGERPRINT_SECURITY_LEVEL_1)
|
||||||
|
return HTTP_STATUS_BAD_REQUEST;
|
||||||
|
|
||||||
|
if(newLevel != Settings().m_SecurityLevel)
|
||||||
|
{
|
||||||
|
Settings().m_SecurityLevel = newLevel;
|
||||||
|
Settings().Save();
|
||||||
|
FingerLogic().SetSecurityLevel(newLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
else if(endpoint == "fingerprint/label")
|
else if(endpoint == "fingerprint/label")
|
||||||
{
|
{
|
||||||
@@ -224,8 +365,6 @@ HttpStatus CMain::HandleApi(HttpMethod method, String endpoint, JsonDocument &re
|
|||||||
CSettings::CFingerPrint &finger = Settings().m_FingerPrints.valueAt(index);
|
CSettings::CFingerPrint &finger = Settings().m_FingerPrints.valueAt(index);
|
||||||
strncpy(finger.m_aLabel, label.c_str(), sizeof(finger.m_aLabel));
|
strncpy(finger.m_aLabel, label.c_str(), sizeof(finger.m_aLabel));
|
||||||
Settings().Save();
|
Settings().Save();
|
||||||
|
|
||||||
resp["success"] = true;
|
|
||||||
}
|
}
|
||||||
else if(endpoint == "fingerprint/delete")
|
else if(endpoint == "fingerprint/delete")
|
||||||
{
|
{
|
||||||
@@ -243,8 +382,6 @@ HttpStatus CMain::HandleApi(HttpMethod method, String endpoint, JsonDocument &re
|
|||||||
FingerPrint().DeleteTemplate(finger.m_FingerNum, 1);
|
FingerPrint().DeleteTemplate(finger.m_FingerNum, 1);
|
||||||
Settings().m_FingerPrints.removeAt(index);
|
Settings().m_FingerPrints.removeAt(index);
|
||||||
Settings().Save();
|
Settings().Save();
|
||||||
|
|
||||||
resp["success"] = true;
|
|
||||||
}
|
}
|
||||||
else if(endpoint == "fingerprint/enroll")
|
else if(endpoint == "fingerprint/enroll")
|
||||||
{
|
{
|
||||||
@@ -254,7 +391,7 @@ HttpStatus CMain::HandleApi(HttpMethod method, String endpoint, JsonDocument &re
|
|||||||
{
|
{
|
||||||
if(req["cancel"].as<bool>() && m_Enrolling)
|
if(req["cancel"].as<bool>() && m_Enrolling)
|
||||||
{
|
{
|
||||||
resp["success"] = FingerLogic().EnrollFinger(false);
|
FingerLogic().EnrollFinger(false);
|
||||||
m_Enrolling = false;
|
m_Enrolling = false;
|
||||||
m_Enrolled = false;
|
m_Enrolled = false;
|
||||||
}
|
}
|
||||||
@@ -336,15 +473,100 @@ void CMain::HttpOnFile(HttpRequest &request, HttpResponse &response)
|
|||||||
response.sendFile(file);
|
response.sendFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMain::OnFingerInterrupt(bool finger)
|
int CMain::HttpOnUpload(HttpServerConnection& connection, HttpRequest& request, HttpResponse& response)
|
||||||
{
|
{
|
||||||
m_FingerLogic.OnFingerInterrupt(finger);
|
if(!HttpAuthorized(request, response))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ReadWriteStream* file = request.files["firmware"];
|
||||||
|
auto otaStream = static_cast<OtaUpgradeStream*>(file);
|
||||||
|
if(otaStream == nullptr) {
|
||||||
|
debug_e("Something went wrong with the file upload");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(response.isSuccess() && !otaStream->hasError()) {
|
||||||
|
// defer the reboot by 1000 milliseconds to give time to the web server to return the response
|
||||||
|
System.restart(1000);
|
||||||
|
|
||||||
|
response.sendFile("otadone.html");
|
||||||
|
response.headers[HTTP_HEADER_CONNECTION] = "close";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.code = HTTP_STATUS_BAD_REQUEST;
|
||||||
|
response.setContentType(MIME_HTML);
|
||||||
|
String html = toString(otaStream->errorCode);
|
||||||
|
response.headers[HTTP_HEADER_CONTENT_LENGTH] = html.length();
|
||||||
|
response.sendString(html);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMain::FingerEnable(bool enable)
|
void CMain::CheckSleep()
|
||||||
|
{
|
||||||
|
if(!m_FingerPlaced &&
|
||||||
|
!m_LockUnlocked &&
|
||||||
|
!m_DoorOpened)
|
||||||
|
{
|
||||||
|
m_LightSleepTimer.startOnce();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_LightSleepTimer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::OnFinger(bool finger)
|
||||||
|
{
|
||||||
|
m_FingerPlaced = finger;
|
||||||
|
m_FingerLogic.OnFinger(finger);
|
||||||
|
|
||||||
|
if(finger)
|
||||||
|
MqttSendMessage("safeweb/finger/placed", "true");
|
||||||
|
else
|
||||||
|
MqttSendMessage("safeweb/finger/placed", "false");
|
||||||
|
CheckSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::OnLock(bool unlocked)
|
||||||
|
{
|
||||||
|
m_LockUnlocked = unlocked;
|
||||||
|
|
||||||
|
if(unlocked)
|
||||||
|
MqttSendMessage("safeweb/lock/unlocked", "true");
|
||||||
|
else
|
||||||
|
MqttSendMessage("safeweb/lock/unlocked", "false");
|
||||||
|
CheckSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::OnDoor(bool opened)
|
||||||
|
{
|
||||||
|
m_DoorOpened = opened;
|
||||||
|
|
||||||
|
if(opened)
|
||||||
|
MqttSendMessage("safeweb/door/opened", "true");
|
||||||
|
else
|
||||||
|
MqttSendMessage("safeweb/door/opened", "false");
|
||||||
|
CheckSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMain::FingerPower(bool enable)
|
||||||
{
|
{
|
||||||
const int pin = FINGER_ENABLE_PIN;
|
const int pin = FINGER_ENABLE_PIN;
|
||||||
digitalWrite(pin, !enable);
|
digitalWrite(pin, !enable);
|
||||||
|
|
||||||
|
if(enable)
|
||||||
|
{
|
||||||
|
wifi_set_sleep_level(MAX_SLEEP_T);
|
||||||
|
wifi_set_listen_interval(3);
|
||||||
|
wifi_set_sleep_type(MODEM_SLEEP_T);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wifi_set_sleep_type(LIGHT_SLEEP_T);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMain::LockSendBytes(uint8_t *pBytes, uint8_t len)
|
void CMain::LockSendBytes(uint8_t *pBytes, uint8_t len)
|
||||||
@@ -443,11 +665,6 @@ void CMain::OnFingerEnrolled(uint16_t fingerNum, uint8_t digest[SHA256_SIZE])
|
|||||||
bytes2hex(finger.m_aDigest, sizeof(finger.m_aDigest), aHexDigest, sizeof(aHexDigest));
|
bytes2hex(finger.m_aDigest, sizeof(finger.m_aDigest), aHexDigest, sizeof(aHexDigest));
|
||||||
debugf("OnFingerEnrolled: \"%s\"", aHexDigest);
|
debugf("OnFingerEnrolled: \"%s\"", aHexDigest);
|
||||||
|
|
||||||
Serial1.printf("(sz: %d) Finger hexdigest: ", sizeof(finger.m_aDigest));
|
|
||||||
for(uint8_t i = 0; i < sizeof(finger.m_aDigest); i++)
|
|
||||||
Serial1.printf("%x", finger.m_aDigest[i]);
|
|
||||||
Serial1.printf("\n");
|
|
||||||
|
|
||||||
Settings().m_FingerPrints[fingerNum] = finger;
|
Settings().m_FingerPrints[fingerNum] = finger;
|
||||||
Settings().Save();
|
Settings().Save();
|
||||||
m_Enrolled = true;
|
m_Enrolled = true;
|
||||||
|
|||||||
27
app/main.h
27
app/main.h
@@ -19,10 +19,19 @@ class CMain
|
|||||||
public:
|
public:
|
||||||
CMain();
|
CMain();
|
||||||
void Init(HardwareSerial &serial);
|
void Init(HardwareSerial &serial);
|
||||||
|
void CheckSleep();
|
||||||
|
void EnterLightSleep();
|
||||||
|
|
||||||
void OnFingerInterrupt(bool finger);
|
void OnStationGotIP(IpAddress ip, IpAddress mask, IpAddress gateway);
|
||||||
|
void OnStationDisconnect(const String& ssid, MacAddress bssid, WifiDisconnectReason reason);
|
||||||
|
int MqttOnConnect(MqttClient& client, mqtt_message_t* message);
|
||||||
|
void MqttOnDisconnect(TcpClient& client, bool flag);
|
||||||
|
|
||||||
void FingerEnable(bool enable);
|
void OnFinger(bool finger);
|
||||||
|
void OnLock(bool unlocked);
|
||||||
|
void OnDoor(bool opened);
|
||||||
|
|
||||||
|
void FingerPower(bool enable);
|
||||||
|
|
||||||
void LockUnlock();
|
void LockUnlock();
|
||||||
void EnrollMessage(const char *msg, bool error=false);
|
void EnrollMessage(const char *msg, bool error=false);
|
||||||
@@ -38,9 +47,14 @@ private:
|
|||||||
bool HttpAuthorized(HttpRequest &request, HttpResponse &response);
|
bool HttpAuthorized(HttpRequest &request, HttpResponse &response);
|
||||||
void HttpOnApi(HttpRequest &request, HttpResponse &response);
|
void HttpOnApi(HttpRequest &request, HttpResponse &response);
|
||||||
void HttpOnFile(HttpRequest &request, HttpResponse &response);
|
void HttpOnFile(HttpRequest &request, HttpResponse &response);
|
||||||
|
int HttpOnUpload(HttpServerConnection& connection, HttpRequest& request, HttpResponse& response);
|
||||||
|
|
||||||
HttpStatus HandleApi(HttpMethod method, String endpoint, JsonDocument &req, JsonDocument &resp);
|
HttpStatus HandleApi(HttpMethod method, String endpoint, JsonDocument &req, JsonDocument &resp);
|
||||||
|
|
||||||
|
void StartMqttClient();
|
||||||
|
void MqttSendDescription();
|
||||||
|
void MqttSendMessage(const char *topic, const char *msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LockSendBytes(uint8_t *pBytes, uint8_t len);
|
void LockSendBytes(uint8_t *pBytes, uint8_t len);
|
||||||
void LockSendCode(uint8_t code[8]);
|
void LockSendCode(uint8_t code[8]);
|
||||||
@@ -51,12 +65,21 @@ private:
|
|||||||
|
|
||||||
FtpServer m_FTP;
|
FtpServer m_FTP;
|
||||||
HttpServer m_HttpServer;
|
HttpServer m_HttpServer;
|
||||||
|
MqttClient m_Mqtt;
|
||||||
|
Timer m_MqttTimer;
|
||||||
|
Timer m_LightSleepTimer;
|
||||||
|
|
||||||
String m_EnrollMessage;
|
String m_EnrollMessage;
|
||||||
String m_EnrollLabel;
|
String m_EnrollLabel;
|
||||||
CSettings::CFingerPrint m_EnrolledFinger;
|
CSettings::CFingerPrint m_EnrolledFinger;
|
||||||
bool m_Enrolling;
|
bool m_Enrolling;
|
||||||
bool m_Enrolled;
|
bool m_Enrolled;
|
||||||
|
|
||||||
|
bool m_StationConnected;
|
||||||
|
|
||||||
|
bool m_FingerPlaced;
|
||||||
|
bool m_LockUnlocked;
|
||||||
|
bool m_DoorOpened;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CMain g_Main;
|
extern CMain g_Main;
|
||||||
|
|||||||
@@ -73,3 +73,32 @@ int Rssi2Quality(sint8 rssi)
|
|||||||
else
|
else
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debounce::Debounce() : state(0xFF) {}
|
||||||
|
Debounce::Debounce(bool signal) { init(signal); }
|
||||||
|
void Debounce::init(bool signal)
|
||||||
|
{
|
||||||
|
if(signal)
|
||||||
|
state = 0xFF;
|
||||||
|
else
|
||||||
|
state = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t Debounce::debounce(bool signal)
|
||||||
|
{
|
||||||
|
const uint8_t current = state & UPPER;
|
||||||
|
const uint8_t history = (state << 1) & LOWER;
|
||||||
|
|
||||||
|
state = current | history | signal;
|
||||||
|
|
||||||
|
// Events are triggered when the history is saturated
|
||||||
|
// with the opposite of the active switch state.
|
||||||
|
// As a result, the events are guaranteed to alternate.
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case UPPER: state = 0x00; return -1; // LOW/False (falling edge)
|
||||||
|
case LOWER: state = 0xFF; return 1; // HIGH/True (rising edge)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;//state & UPPER;
|
||||||
|
}
|
||||||
|
|||||||
18
app/utils.h
18
app/utils.h
@@ -5,4 +5,22 @@ int hex2bytes(const char *str, uint8_t *bytes, int32_t length);
|
|||||||
void bytes2hex(const uint8_t *bytes, int32_t length, char *str, int32_t strLength);
|
void bytes2hex(const uint8_t *bytes, int32_t length, char *str, int32_t strLength);
|
||||||
int Rssi2Quality(sint8 rssi);
|
int Rssi2Quality(sint8 rssi);
|
||||||
|
|
||||||
|
class Debounce
|
||||||
|
{
|
||||||
|
static constexpr uint8_t UPPER = 0b10000000;
|
||||||
|
static constexpr uint8_t LOWER = 0b01111111;
|
||||||
|
public:
|
||||||
|
Debounce();
|
||||||
|
Debounce(bool signal);
|
||||||
|
void init(bool signal);
|
||||||
|
/* Return value:
|
||||||
|
* 0: no change
|
||||||
|
* -1: LOW/False (falling edge)
|
||||||
|
* 1: HIGH/True (rising edge)
|
||||||
|
*/
|
||||||
|
int8_t debounce(bool signal);
|
||||||
|
private:
|
||||||
|
uint8_t state;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
11
component.mk
11
component.mk
@@ -1,4 +1,11 @@
|
|||||||
ARDUINO_LIBRARIES := ArduinoJson6
|
ARDUINO_LIBRARIES := ArduinoJson6 MultipartParser OtaUpgrade
|
||||||
|
|
||||||
HWCONFIG = spiffs
|
HWCONFIG = spiffs-two-roms
|
||||||
SPIFF_FILES = files
|
SPIFF_FILES = files
|
||||||
|
|
||||||
|
ifndef MAKE_DOCS
|
||||||
|
|
||||||
|
web-upload: spiffs-image-update
|
||||||
|
$(call WriteFlash,$(SPIFF_START_ADDR)=$(SPIFF_BIN_OUT))
|
||||||
|
|
||||||
|
endif
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
files/favicon.ico.gz
Normal file
BIN
files/favicon.ico.gz
Normal file
Binary file not shown.
@@ -1,25 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="Safe control panel">
|
|
||||||
<title>Safe control panel</title>
|
|
||||||
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha256-LA89z+k9fjgMKQ/kq4OO2Mrf8VltYml/VES+Rg0fh20=" crossorigin="anonymous" />
|
|
||||||
<link rel="stylesheet" href="main.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="spinner"><div class="rect1"></div> <div class="rect2"></div> <div class="rect3"></div> <div class="rect4"></div> <div class="rect5"></div></div>
|
|
||||||
<noscript><center><h1>Your browser does not support JavaScript!</h1></center></noscript>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/nunjucks/3.0.1/nunjucks.min.js" integrity="sha256-sh9FYQZVVLprCQB3/IcNyCRrZwu9hZ+xLHhUszDfsK4=" crossorigin="anonymous"></script>
|
|
||||||
<script src="templates.js"></script>
|
|
||||||
<script src="main.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha256-pS96pU17yq+gVu4KBQJi38VpSuKN7otMrDQprzf/DWY=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha256-5+02zu5UULQkO7w1GIr6vftCgMfFdZcAHeDtFnKZsBs=" crossorigin="anonymous"></script>
|
|
||||||
</html>
|
|
||||||
BIN
files/index.html.gz
Normal file
BIN
files/index.html.gz
Normal file
Binary file not shown.
Binary file not shown.
BIN
files/main.js.gz
BIN
files/main.js.gz
Binary file not shown.
BIN
files/otadone.html.gz
Normal file
BIN
files/otadone.html.gz
Normal file
Binary file not shown.
@@ -10,6 +10,13 @@
|
|||||||
"netmask": "0.0.0.0",
|
"netmask": "0.0.0.0",
|
||||||
"gateway": "0.0.0.0"
|
"gateway": "0.0.0.0"
|
||||||
},
|
},
|
||||||
|
"mqtt": {
|
||||||
|
"client_name": "safeweb",
|
||||||
|
"host": "",
|
||||||
|
"port": 0,
|
||||||
|
"username": "safeweb",
|
||||||
|
"password": "password"
|
||||||
|
},
|
||||||
"lock_code": [
|
"lock_code": [
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@@ -21,5 +28,6 @@
|
|||||||
7
|
7
|
||||||
],
|
],
|
||||||
"fingerprints": [
|
"fingerprints": [
|
||||||
]
|
],
|
||||||
|
"security_level": 4
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Reference in New Issue
Block a user