diff --git a/firmware/core/core.ino b/firmware/core/core.ino index f1c17f7..d9e1362 100644 --- a/firmware/core/core.ino +++ b/firmware/core/core.ino @@ -1,13 +1,18 @@ #include #include +#include "protocol.h" +#include "peripheral.h" const int led = 13; //LED pin config -byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; -#define SERVER_HOST "192.168.1.106" -#define SERVER_PORT 2828 +byte mac[] = {0xDE, 0xAD, 0x00, 0x09, 0x00, 0x09}; +#define SERVER_HOST "192.168.1.103" +#define SERVER_PORT 39999 #define MAX_CONNECT_RETRIES 5 +#define MAX_PACKET_SIZE 16 EthernetClient client; +Door door; +Alarm alarm; void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers { @@ -36,6 +41,8 @@ void setup() { pinMode(led, OUTPUT); + door.Init(); + alarm.Init(); // Open serial communications and wait for port to open: Serial.begin(9600); @@ -64,8 +71,51 @@ } -void parseCmd(char charRecved) +void parsePacket(packet* p) { + Serial.print(F("Packet type: ")); + Serial.println(p->type); + switch(p->type){ + case PacketTypeCommand: + switch (p->payload.command.commandType) { + case DoDoorOpen: + door.Open(); + break; + case DoAlarmOn: + alarm.On(); + break; + case DoAlarmOff: + alarm.Off(); + break; + } + break; + case PacketTypeRequest: + case PacketTypeResponse: + case PacketTypeEvent: + break; + } +} + +void receivePacket(byte charRecved) +{ + static uint8_t packetBuffer[MAX_PACKET_SIZE]; + static uint8_t ptr; + struct packet* pPacket = (struct packet*)packetBuffer; + if(!ptr){ + if(charRecved == PacketIdentifier) + packetBuffer[ptr++] = charRecved; + }else if(ptr < MAX_PACKET_SIZE-1){ + packetBuffer[ptr++] = charRecved; + if(ptr >= 4){ //payloadSize field already received + if(pPacket->payloadSize == ptr - 4){ //packet receiving competed + parsePacket(pPacket); + ptr = 0; //receiving next packet + }else if(pPacket->payloadSize > MAX_PACKET_SIZE - 4){ + Serial.println("Packet is too long"); + ptr = 0; //restart packet receiving + } + } + } } void renewDhcp() @@ -80,6 +130,12 @@ void loop() { static uint8_t connect_retries = 0; + + if(door.UpdateState()){ + Serial.println("Door opened illegally"); + alarm.On(); + } + if (!client.connected()) { digitalWrite(led, LOW); client.stop(); @@ -99,7 +155,7 @@ } } while (client.available() > 0){ - parseCmd(client.read()); + receivePacket(client.read()); } renewDhcp(); } diff --git a/firmware/core/peripheral.cpp b/firmware/core/peripheral.cpp new file mode 100644 index 0000000..644ba9a --- /dev/null +++ b/firmware/core/peripheral.cpp @@ -0,0 +1,72 @@ +#include "peripheral.h" + +void Door::Init() +{ + pinMode(lockMagnetPin, OUTPUT); + pinMode(lockDetectPin, INPUT); + digitalWrite(lockMagnetPin, HIGH);//lock door + digitalWrite(lockDetectPin, HIGH);//enable pull-up + + lastDectVal = digitalRead(lockDetectPin); + lastDectTime = millis(); +} + +void Door::Open() +{ + if (state == DoorLocked) { + digitalWrite(lockMagnetPin, LOW); + state = DoorPreparedOpen; + Serial.println("DoorPreparedOpen"); + } +} + +bool Door::detect() +{ + unsigned char ret = digitalRead(lockDetectPin); + if(millis()-lastDectTime > DetectorSwitchDelay && + (ret ^ lastDectVal)){ + + lastDectTime = millis(); + lastDectVal = ret; + } + return lastDectVal == HIGH; +} + +bool Door::UpdateState() +{ + switch (state) { + case DoorLocked: + if (detect()) { + state = DoorOpened; + return true; + } + break; + case DoorPreparedOpen: + if (detect()) { + digitalWrite(lockMagnetPin, HIGH); + state = DoorOpened; + Serial.println("DoorOpened"); + } + break; + case DoorOpened: + if (!detect()) { + digitalWrite(lockMagnetPin, HIGH); + state = DoorLocked; + Serial.println("DoorLocked"); + } + break; + } + return false; +} + +void Alarm::Init() +{ + pinMode(alarmPin, OUTPUT); + digitalWrite(alarmPin, LOW); +} + +void Alarm::setAlarm(bool _on) +{ + on = _on; + digitalWrite(alarmPin, _on ? HIGH : LOW); +} diff --git a/firmware/core/peripheral.h b/firmware/core/peripheral.h new file mode 100644 index 0000000..e589777 --- /dev/null +++ b/firmware/core/peripheral.h @@ -0,0 +1,47 @@ +#ifndef PERIPHERAL_H__ +#define PERIPHERAL_H__ +#include "Arduino.h" + +#define lockMagnetPin 12 +#define lockDetectPin 4 +#define buttonPin 5 +#define alarmPin 6 + +#define DetectorSwitchDelay 80 + +class Door +{ + enum DoorStateDef + { + DoorLocked, DoorPreparedOpen, DoorOpened + }; + DoorStateDef state; + unsigned long lastDectTime; + unsigned char lastDectVal; + bool detect(); //return true if lock detected door opened +public: + Door():state(DoorOpened){} + void Init(); + void Open(); + bool UpdateState(); //return true if door is opened while locked +}; + +class Alarm +{ + bool on; + void setAlarm(bool); +public: + Alarm():on(false){} + void Init(); + void On(){ + setAlarm(true); + } + void Off(){ + setAlarm(false); + } + bool IsAlarmOn(){ + return on; + } +}; + +#endif diff --git a/firmware/core/protocol.h b/firmware/core/protocol.h new file mode 100644 index 0000000..2bcfe16 --- /dev/null +++ b/firmware/core/protocol.h @@ -0,0 +1,54 @@ +#ifndef PROTOCOL_H__ +#define PROTOCOL_H__ + +#define PacketIdentifier 0xA1 +enum eventTypeDef +{ + CardDidScan,DoorDidOpen,DoorDidClose,DoorReleaseDidTriggered,AlarmDidOn,AlarmDidOff +}; +enum commandTypeDef +{ + DoDoorOpen,DoAlarmOn,DoAlarmOff +}; +enum requestTypeDef +{ + RequestAuth +}; +enum responseTypeDef +{ + ResponseNegative,ResponsePositive,ResponseNatural +}; +enum packetTypeDef +{ + PacketTypeEvent,PacketTypeCommand,PacketTypeRequest,PacketTypeResponse +}; +struct eventPayload{ + uint8_t eventType; //0->cardDidScan 1->doorDidOpen 2->doorDidClose 3->doorReleaseDidTriggered 4->alarmDidOn 5->alarmDidOff +}; +struct commandPayload{ + uint8_t commandType; //0->doDoorOpen 1->doAlarmOn 2->doAlarmOff +}; +struct requestPayload{ + uint8_t requestType; //0->auth + unsigned char param[]; +}; +struct authParam{ + uint32_t cardId; //little_endian +}; +struct responsePayload{ + uint8_t responseType; //0->negative 1->positive 2->natural + unsigned char param[]; +}; +struct packet{ + uint8_t characteristicAndVersion; // must be 0xA1 + uint8_t type; //0->event 1->command 2->request 3->response + uint16_t payloadSize; //little_endian + union{ + struct eventPayload event; + struct commandPayload command; + struct requestPayload request; + struct responsePayload response; + }payload; +}; +#endif + diff --git a/software/config.js b/software/config.js index f60211a..688d0f3 100644 --- a/software/config.js +++ b/software/config.js @@ -1,6 +1,6 @@ module.exports = { bindAddress: "0.0.0.0", - bindPort : 57005, + bindPort : 39999, logFile : "./access.log", sockFile : "/tmp/card9.sock", accounts9 : "https://accounts.net9.org",