From 324d97c0cef3c8ae0845ea371a17b21a9552a379 Mon Sep 17 00:00:00 2001
From: Svante Kaiser <svantekaiser@example.com>
Date: Fri, 15 Dec 2023 18:50:37 +0300
Subject: [PATCH] switch between intercoms

---
 src/app/routes.cpp                            |   2 +
 .../stateMachine.cpp.disabled}                |   2 +-
 .../stateMachine.h.disabled}                  |   0
 .../{ => old}/stateMachineCyfral.cpp.disabled |   0
 .../{ => old}/stateMachineCyfral.h.disabled   |   0
 src/domain/stateMachineController.cpp         |  27 +++
 src/domain/stateMachineController.h           |  14 ++
 src/domain/stateMachineStrategy.h             |   8 +
 src/domain/strategies/cyfralStrategy.cpp      | 141 +++++++++++++++
 src/domain/strategies/cyfralStrategy.h        |  42 +++++
 src/domain/strategies/vizitStrategy.cpp       | 171 ++++++++++++++++++
 src/domain/strategies/vizitStrategy.h         |  46 +++++
 src/main.cpp                                  |  17 +-
 13 files changed, 467 insertions(+), 3 deletions(-)
 rename src/domain/{stateMachine.cpp => old/stateMachine.cpp.disabled} (99%)
 rename src/domain/{stateMachine.h => old/stateMachine.h.disabled} (100%)
 rename src/domain/{ => old}/stateMachineCyfral.cpp.disabled (100%)
 rename src/domain/{ => old}/stateMachineCyfral.h.disabled (100%)
 create mode 100644 src/domain/stateMachineController.cpp
 create mode 100644 src/domain/stateMachineController.h
 create mode 100644 src/domain/stateMachineStrategy.h
 create mode 100644 src/domain/strategies/cyfralStrategy.cpp
 create mode 100644 src/domain/strategies/cyfralStrategy.h
 create mode 100644 src/domain/strategies/vizitStrategy.cpp
 create mode 100644 src/domain/strategies/vizitStrategy.h

diff --git a/src/app/routes.cpp b/src/app/routes.cpp
index 73a2c5c..a3ea6b5 100644
--- a/src/app/routes.cpp
+++ b/src/app/routes.cpp
@@ -244,6 +244,8 @@ void initRoutes() {
   server.on("/api/v1/networkSettings", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, networkSettingsUpdate);
 
   server.on("/api/v1/intercomStatus", intercomStatus);
+  //server.on("/api/v1/intercomSettings", HTTP_GET, intercomSettingsRead);
+  //server.on("/api/v1/intercomSettings", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, intercomSettingsUpdate);
 
   server.on("/api/v1/mqttStatus", mqttStatus);
   server.on("/api/v1/mqttSettings", HTTP_GET, mqttSettingsRead);
diff --git a/src/domain/stateMachine.cpp b/src/domain/old/stateMachine.cpp.disabled
similarity index 99%
rename from src/domain/stateMachine.cpp
rename to src/domain/old/stateMachine.cpp.disabled
index 6f5e1e1..d194c84 100644
--- a/src/domain/stateMachine.cpp
+++ b/src/domain/old/stateMachine.cpp.disabled
@@ -24,7 +24,7 @@ void resetCounters() {
 }
 
 void writeState(char* message) {
-  //println(message);
+  println(message);
   publishToMQTT(STATE_MQTT_TOPIC, message);
 }
 
diff --git a/src/domain/stateMachine.h b/src/domain/old/stateMachine.h.disabled
similarity index 100%
rename from src/domain/stateMachine.h
rename to src/domain/old/stateMachine.h.disabled
diff --git a/src/domain/stateMachineCyfral.cpp.disabled b/src/domain/old/stateMachineCyfral.cpp.disabled
similarity index 100%
rename from src/domain/stateMachineCyfral.cpp.disabled
rename to src/domain/old/stateMachineCyfral.cpp.disabled
diff --git a/src/domain/stateMachineCyfral.h.disabled b/src/domain/old/stateMachineCyfral.h.disabled
similarity index 100%
rename from src/domain/stateMachineCyfral.h.disabled
rename to src/domain/old/stateMachineCyfral.h.disabled
diff --git a/src/domain/stateMachineController.cpp b/src/domain/stateMachineController.cpp
new file mode 100644
index 0000000..cab0ff8
--- /dev/null
+++ b/src/domain/stateMachineController.cpp
@@ -0,0 +1,27 @@
+#include "domain/stateMachineController.h"
+
+StateMachineController::StateMachineController() : _strategy(nullptr) {}
+
+void StateMachineController::setStrategy(StateMachineStrategy* newStrategy) {
+  if (_strategy) {
+    delete _strategy;
+  }
+
+  _strategy = newStrategy;
+  if (_strategy) {
+    _strategy->setup();
+  }
+}
+
+void StateMachineController::updateStateMachine(int data) {
+  if (_strategy) {
+    _strategy->updateStateMachine(data);
+  }
+}
+
+StateMachineController::~StateMachineController() {
+  // Cleanup the strategy in the destructor
+  if (_strategy) {
+    delete _strategy;
+  }
+}
\ No newline at end of file
diff --git a/src/domain/stateMachineController.h b/src/domain/stateMachineController.h
new file mode 100644
index 0000000..0d6d2bf
--- /dev/null
+++ b/src/domain/stateMachineController.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "domain/stateMachineStrategy.h"
+
+class StateMachineController {
+private:
+  StateMachineStrategy* _strategy;
+
+public:
+  StateMachineController();
+  void setStrategy(StateMachineStrategy* newStrategy);
+  void updateStateMachine(int data);
+  ~StateMachineController();
+};
\ No newline at end of file
diff --git a/src/domain/stateMachineStrategy.h b/src/domain/stateMachineStrategy.h
new file mode 100644
index 0000000..c7ff367
--- /dev/null
+++ b/src/domain/stateMachineStrategy.h
@@ -0,0 +1,8 @@
+#pragma once
+
+class StateMachineStrategy {
+public:
+  virtual void setup() = 0;
+  virtual void updateStateMachine(int data) = 0;
+  virtual ~StateMachineStrategy() {}
+};
\ No newline at end of file
diff --git a/src/domain/strategies/cyfralStrategy.cpp b/src/domain/strategies/cyfralStrategy.cpp
new file mode 100644
index 0000000..28b723c
--- /dev/null
+++ b/src/domain/strategies/cyfralStrategy.cpp
@@ -0,0 +1,141 @@
+#include "domain/strategies/cyfralStrategy.h"
+
+CyfralStrategy::CyfralStrategy() {}
+
+void CyfralStrategy::setup() {
+  _initStateMachine();
+}
+
+void CyfralStrategy::updateStateMachine(int data) {
+  switch (_currentState) {
+    case NOT_CONNECTED:
+      if (data == LOW) {} 
+      else if (data == HIGH) {
+        _changeState(CONNECTED);
+      }
+      break;
+
+    case CONNECTED:
+      if (data == LOW) {
+        _countZeros++;
+        if (_countZeros >= NOT_CONNECTED_THRESHOLD) {
+          _changeState(NOT_CONNECTED);
+        }
+      } else if (data == HIGH) {
+        if (_countZeros >= INITIALIZING_CALL_THRESHOLD) {
+          _changeState(RECEIVING_DATA);
+        }
+      }
+      break;
+
+    case RECEIVING_DATA:
+      _receiveData(data);
+
+      if (data == LOW) {
+        _countOnes = 0;
+        _countZeros++;
+        if (_countZeros >= DATA_RECEIVED_THESHOLD) {
+          _flatReceived();
+          _changeState(DATA_RECEIVED);
+        }
+      } else if (data == HIGH) {
+        _countZeros = 0;
+        _countOnes++;
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      }
+      break;
+
+    case DATA_RECEIVED:
+      if (data == LOW) {
+        _countZeros++;
+        if (_countZeros >= CALL_ENDED_THRESHOLD) {
+          _changeState(CALL_ENDED);
+        }
+      } else if (data == HIGH) {
+        _countOnes++;
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      break;
+      }
+
+    case CALL_ENDED:
+      if (data == LOW) {
+        _countZeros++;
+        if (_countZeros >= NOT_CONNECTED_THRESHOLD) {
+          _changeState(NOT_CONNECTED);
+        }
+      } else if (data == HIGH) {
+        _countOnes++;
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      break;
+      }
+  }
+}
+
+void CyfralStrategy::_resetCounters() {
+  _countZeros = 0;
+  _countOnes = 0;
+
+  _previousData = 0;
+  _dataLength = 0;
+  _signalDuration = 0;
+}
+
+void CyfralStrategy::_writeState(char* message) {
+  println(message);
+  publishToMQTT(STATE_MQTT_TOPIC, message);
+}
+
+void CyfralStrategy::_receiveData(int data) {
+  if (data != _previousData) {
+    if (_previousData == HIGH) {
+      //println("AAAA ", dataLength, " ", signalDuration);
+      _dataLength++;
+    }
+    _signalDuration = 0;
+  } else {
+    _signalDuration++;
+  }
+  _previousData = data;
+}
+
+void CyfralStrategy::_changeState(State state, bool resetCountersFlag) {
+  _currentState = state;
+
+  switch (state) {
+    case NOT_CONNECTED:
+      ledTurnOff();
+      _writeState("not connected");
+      break;
+    case CONNECTED:
+      ledTurnOn();
+      _writeState("connected");
+      break;
+    case RECEIVING_DATA:
+      _writeState("receiving data");
+      break;
+  }
+
+  if (resetCountersFlag)
+    _resetCounters();
+}
+
+void CyfralStrategy::_flatReceived() {
+  int flat = _dataLength/2;
+
+  if (flat < 1)
+    return;
+
+  println("| data length: ", _dataLength);
+  println("| flat: ", flat);
+  publishToMQTT(FLAT_NUMBER_MQTT_TOPIC, flat);
+}
+
+void CyfralStrategy::_initStateMachine() {
+  _changeState(CONNECTED);
+}
diff --git a/src/domain/strategies/cyfralStrategy.h b/src/domain/strategies/cyfralStrategy.h
new file mode 100644
index 0000000..d5941d7
--- /dev/null
+++ b/src/domain/strategies/cyfralStrategy.h
@@ -0,0 +1,42 @@
+#include "utils/print.h"
+#include "config/config.h"
+#include "infra/mqtt.h"
+#include "infra/led.h"
+#include "domain/stateMachineStrategy.h"
+
+class CyfralStrategy : public StateMachineStrategy {
+private:
+  enum State {
+    NOT_CONNECTED,
+    CONNECTED,
+    RECEIVING_DATA,
+    DATA_RECEIVED,
+    CALL_ENDED
+  };
+
+  const int CONNECTED_THRESHOLD = 50000;
+  const int NOT_CONNECTED_THRESHOLD = 50000;
+  const int INITIALIZING_CALL_THRESHOLD = 15000;
+  const int DATA_RECEIVED_THESHOLD = 30000;
+  const int CALL_ENDED_THRESHOLD = 10000;
+
+  State _currentState = NOT_CONNECTED;
+  int _countZeros = 0;
+  int _countOnes = 0;
+
+  int _previousData = 0;
+  int _dataLength = 0;
+  int _signalDuration = 0;
+
+  void _resetCounters();
+  void _writeState(char* message);
+  void _receiveData(int data);
+  void _changeState(State state, bool resetCountersFlag = true);
+  void _flatReceived();
+  void _initStateMachine();
+
+public:
+  CyfralStrategy();
+  void setup() override;
+  void updateStateMachine(int data) override;
+};
diff --git a/src/domain/strategies/vizitStrategy.cpp b/src/domain/strategies/vizitStrategy.cpp
new file mode 100644
index 0000000..2c53cb9
--- /dev/null
+++ b/src/domain/strategies/vizitStrategy.cpp
@@ -0,0 +1,171 @@
+#include "domain/strategies/vizitStrategy.h"
+
+VizitStrategy::VizitStrategy() {}
+
+void VizitStrategy::setup() {
+  _initStateMachine();
+}
+
+void VizitStrategy::updateStateMachine(int data) {
+  switch (_currentState) {
+    case NOT_CONNECTED:
+      if (data == LOW) {} 
+      else if (data == HIGH) {
+        _changeState(CONNECTED);
+      }
+      break;
+
+    case CONNECTED:
+      if (data == LOW) {
+        _countZeros++;
+        if (_countZeros >= NOT_CONNECTED_THRESHOLD) {
+          _changeState(NOT_CONNECTED);
+        }
+      } else if (data == HIGH) {
+        if (_countZeros >= INITIALIZING_CALL_THRESHOLD) {
+          _changeState(RECEIVING_FIRST_DIGIT);
+        }
+      }
+      break;
+
+    case RECEIVING_FIRST_DIGIT:
+      _receiveDigit(data);
+
+      if (data == LOW) {
+        _countOnes = 0;
+        _countZeros++;
+      } else if (data == HIGH) {
+        _countZeros = 0;
+        _countOnes++;
+        if (_countOnes >= DATA_RECEIVED_THESHOLD) {
+          _firstDigitReceived();
+          _changeState(RECEIVING_SECOND_DIGIT);
+        }
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      }
+      break;
+
+    case RECEIVING_SECOND_DIGIT:
+      _receiveDigit(data);
+
+      if (data == LOW) {
+        _countOnes = 0;
+        _countZeros++;
+      } else if (data == HIGH) {
+        _countZeros = 0;
+        _countOnes++;
+        if (_countOnes >= DATA_RECEIVED_THESHOLD) {
+          _secondDigitReceived();
+          _changeState(DATA_RECEIVED);
+        }
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      }
+      break;
+
+    case DATA_RECEIVED:
+      if (data == LOW) {
+        _countZeros++;
+        if (_countZeros >= CALL_ENDED_THRESHOLD) {
+          _changeState(CALL_ENDED);
+        }
+      } else if (data == HIGH) {
+        _countOnes++;
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      break;
+      }
+
+    case CALL_ENDED:
+      if (data == LOW) {
+        _countZeros++;
+        if (_countZeros >= NOT_CONNECTED_THRESHOLD) {
+          _changeState(NOT_CONNECTED);
+        }
+      } else if (data == HIGH) {
+        _countOnes++;
+        if (_countOnes >= CONNECTED_THRESHOLD) {
+          _changeState(CONNECTED);
+        }
+      break;
+      }
+  }
+}
+
+void VizitStrategy::_resetCounters() {
+  _countZeros = 0;
+  _countOnes = 0;
+
+  _previousData = 0;
+  _dataLength = 1;
+  _signalDuration = 0;
+}
+
+void VizitStrategy::_writeState(char* message) {
+  println(message);
+  publishToMQTT(STATE_MQTT_TOPIC, message);
+}
+
+void VizitStrategy::_receiveDigit(int data) {
+  if (data != _previousData) {
+    if (_previousData == HIGH) {
+      //println("AAAA ", dataLength, " ", signalDuration);
+      _dataLength++;
+    }
+    _signalDuration = 0;
+  } else {
+    _signalDuration++;
+  }
+  _previousData = data;
+}
+
+void VizitStrategy::_changeState(State state, bool resetCountersFlag) {
+  _currentState = state;
+
+  switch (state) {
+    case NOT_CONNECTED:
+      ledTurnOff();
+      _writeState("not connected");
+      break;
+    case CONNECTED:
+      ledTurnOn();
+      _writeState("connected");
+      break;
+    case RECEIVING_FIRST_DIGIT:
+      _writeState("receiving data");
+      break;
+  }
+
+  if (resetCountersFlag)
+    _resetCounters();
+}
+
+void VizitStrategy::_firstDigitReceived() {
+  println("| 1 data length: ", _dataLength);
+  _flat = _dataLength*10;
+}
+
+void VizitStrategy::_secondDigitReceived() {
+  if (_dataLength == 11) {
+    _dataLength = 1;
+  }
+
+  _flat += _dataLength;
+  _flat -= 1;
+
+  if (_flat > 100 && _flat < 110) {
+    _flat -= 100;
+  }
+
+  println("| 2 data length: ", _dataLength);
+  println("| flat: ", _flat);
+  publishToMQTT(FLAT_NUMBER_MQTT_TOPIC, _flat);
+}
+
+void VizitStrategy::_initStateMachine() {
+  _changeState(CONNECTED);
+}
diff --git a/src/domain/strategies/vizitStrategy.h b/src/domain/strategies/vizitStrategy.h
new file mode 100644
index 0000000..f7c72a7
--- /dev/null
+++ b/src/domain/strategies/vizitStrategy.h
@@ -0,0 +1,46 @@
+#include "utils/print.h"
+#include "config/config.h"
+#include "infra/mqtt.h"
+#include "infra/led.h"
+#include "domain/stateMachineStrategy.h"
+
+class VizitStrategy : public StateMachineStrategy {
+private:
+  enum State {
+    NOT_CONNECTED,
+    CONNECTED,
+    RECEIVING_FIRST_DIGIT,
+    RECEIVING_SECOND_DIGIT,
+    DATA_RECEIVED,
+    CALL_ENDED
+  };
+
+  const int CONNECTED_THRESHOLD = 50000;
+  const int NOT_CONNECTED_THRESHOLD = 50000;
+  const int INITIALIZING_CALL_THRESHOLD = 45;
+  const int DATA_RECEIVED_THESHOLD = 5000;
+  const int CALL_ENDED_THRESHOLD = 10000;
+
+  State _currentState = NOT_CONNECTED;
+  int _countZeros = 0;
+  int _countOnes = 0;
+
+  int _previousData = 0;
+  int _dataLength = 0;
+  int _signalDuration = 0;
+
+  int _flat = 0;
+
+  void _resetCounters();
+  void _writeState(char* message);
+  void _receiveDigit(int data);
+  void _changeState(State state, bool resetCountersFlag=true);
+  void _firstDigitReceived();
+  void _secondDigitReceived();
+  void _initStateMachine();
+
+public:
+  VizitStrategy();
+  void setup() override;
+  void updateStateMachine(int data) override;
+};
diff --git a/src/main.cpp b/src/main.cpp
index 76ce856..8631129 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,22 +16,33 @@
 #include "infra/fs.h"
 #include "infra/httpServer.h"
 
-#include "domain/stateMachine.h"
 #include "app/routes.h"
 
+#include "domain/stateMachineController.h"
+#include "domain/strategies/cyfralStrategy.h"
+
 uint32_t lastMillis;
 uint64_t lastMicros;
 
 int data = 0;
 
 bool flag = false;
+int zeros = 0;
+int ones = 0;
+
+StateMachineController controller;
+CyfralStrategy strategy;
 
 void IRAM_ATTR one() {
   flag = true;
+  //zeros = 0;
+  ones += 1;
 }
 
 void IRAM_ATTR zero() {
   flag = false;
+  //ones = 0;
+  zeros += 1;
 }
 
 void setup() {
@@ -60,12 +71,14 @@ void setup() {
   initMQTT();
   initRoutes();
   initHttpServer();
+
+  controller.setStrategy(&strategy);
 }
 
 void loop() {
   if (lastMicros < micros()) {
     data = digitalRead(DATA_PIN);
-    updateStateMachine(data);
+    controller.updateStateMachine(data);
 
     if (PRINT_RAW_SIGNAL_FLAG)
       printf("{}", data);