aboutsummaryrefslogtreecommitdiff
path: root/vote/vote.ino
blob: e695806f4a007b281f4b567113a972537a605325 (plain)
  1. // SPDX-FileCopyrightText: 2025 Amal Mazrah <mazrah@ruc.dk>
  2. // SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
  3. // SPDX-FileCopyrightText: 2025 Mennatullah Hatim Kassim <stud-mennatulla@ruc.dk>
  4. // SPDX-FileCopyrightText: 2025 Noor Ahmad <noora@ruc.dk>
  5. // SPDX-FileCopyrightText: 2025 Tanishka Suwalka <tanishkas@ruc.dk>
  6. // SPDX-License-Identifier: GPL-3.0-or-later
  7. /// Mussel vote - an Arduino sketch to monitor mussel biosensors
  8. ///
  9. /// @version 0.0.3
  10. /// @see <https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z2tFBF4gN7ziG9oXtUytVQNYe3VhQ>
  11. /// @see <https://moodle.ruc.dk/course/view.php?id=23504>
  12. // arduino-esp32 Logging system
  13. // activate in Arduino IDE: Tools -> Core Debug Level
  14. // special: set Core Debug Level to Error for plot-friendly output
  15. #define CONFIG_ARDUHAL_ESP_LOG 1
  16. #define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
  17. #include <esp32-hal-log.h>
  18. #undef ARDUHAL_LOG_FORMAT
  19. #define ARDUHAL_LOG_FORMAT(letter, format) \
  20. ARDUHAL_LOG_COLOR_##letter "[" #letter "] %s(): " format \
  21. ARDUHAL_LOG_RESET_COLOR "\r\n", __FUNCTION__
  22. // arduino-esp32 Bluetooth Low Energy (BLE) networking stack
  23. #include <BLEDevice.h>
  24. #include <BLEScan.h>
  25. #include <BLEAdvertisedDevice.h>
  26. #include <BLEEddystoneTLM.h>
  27. #include <BLEBeacon.h>
  28. // Validity timing thresholds
  29. const unsigned long VOTE_TIME_AHEAD = 1 * 60 * 1000; // 1 minute
  30. const unsigned long VOTE_TIME_BEHIND = 2 * 60 * 1000; // 2 minutes
  31. // Limited size NOW!! can be transformed into infinite array
  32. #define STACK_SIZE 1000
  33. struct Vote {
  34. String id;
  35. unsigned long timestamp;
  36. int measure;
  37. };
  38. bool push(String id, unsigned long timestamp, int measure);
  39. void printStack();
  40. bool qualifyVote(Vote vote, unsigned long currentTime);
  41. int _attitude;
  42. int _pin;
  43. bool _boolState;
  44. byte _count;
  45. unsigned long _time;
  46. // Array to store ID strings
  47. String idStack[STACK_SIZE];
  48. unsigned long timeStack[STACK_SIZE];
  49. int measureStack[STACK_SIZE];
  50. // Index of the top element in the stack, -1 means stack is empty
  51. int top = -1;
  52. int scanTime = 1; //In seconds
  53. // pointer to control Bluetooth networking
  54. BLEScan *pBLEScan;
  55. // Bluetooth beacon discovery callbacks
  56. class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  57. // decode name and temperature from Eddystone TLM advertisement
  58. void onResult(BLEAdvertisedDevice advertisedDevice) {
  59. if (advertisedDevice.haveName()
  60. && advertisedDevice.getFrameType() == BLE_EDDYSTONE_TLM_FRAME
  61. ) {
  62. BLEEddystoneTLM EddystoneTLM(&advertisedDevice);
  63. push(
  64. advertisedDevice.getName(),
  65. millis(),
  66. EddystoneTLM.getTemp()
  67. );
  68. }
  69. }
  70. };
  71. /// Function to push data onto the stack
  72. bool push(String id, unsigned long timestamp, int measure) {
  73. // Check if stack is full
  74. if (top >= STACK_SIZE - 1) {
  75. Serial.println("Stack Full");
  76. // Return false if stack is full
  77. return false;
  78. }
  79. top++;
  80. idStack[top] = id;
  81. timeStack[top] = timestamp;
  82. measureStack[top] = measure;
  83. // Return true on successful push
  84. return true;
  85. }
  86. /// Function to print stack contents
  87. void printStack() {
  88. for (int i = top; i >= 0; i--) {
  89. Serial.print("ID: "); Serial.print(idStack[i]);
  90. Serial.print(", Time: "); Serial.print(timeStack[i]);
  91. Serial.print(", measure: "); Serial.println(measureStack[i]);
  92. }
  93. }
  94. bool qualifyVote(Vote vote, unsigned long currentTime) {
  95. // If the measure is 42 (YES), check timestamp validity
  96. if (vote.measure == 42) {
  97. // If the vote's timestamp is within 1 minute, count it as YES
  98. if (currentTime - vote.timestamp <= VOTE_TIME_AHEAD) {
  99. return true;
  100. }
  101. // If the vote's timestamp is older than 2 minutes, count it as NO
  102. else if (currentTime - vote.timestamp > VOTE_TIME_BEHIND) {
  103. return false;
  104. }
  105. }
  106. // If the measure is 2, always count the vote as NO
  107. if (vote.measure == 2) {
  108. return false;
  109. }
  110. // Default case: vote is invalid if no conditions are met
  111. return false;
  112. }
  113. void setup() {
  114. // enable logging to serial
  115. Serial.begin(115200);
  116. esp_log_level_set("*", ESP_LOG_DEBUG);
  117. // setup Bluetooth
  118. BLEDevice::init("");
  119. pBLEScan = BLEDevice::getScan();
  120. pBLEScan->setAdvertisedDeviceCallbacks(
  121. new MyAdvertisedDeviceCallbacks());
  122. pBLEScan->setActiveScan(true);
  123. pBLEScan->setInterval(100);
  124. pBLEScan->setWindow(99);
  125. }
  126. void loop() {
  127. BLEScanResults *foundDevices = pBLEScan->start(scanTime, false);
  128. pBLEScan->clearResults();
  129. // misuse error-only log level for plot-friendly output
  130. #if ARDUHAL_LOG_LEVEL == ARDUHAL_LOG_LEVEL_ERROR
  131. Serial.printf("pin:%d boolState:%d time:%d count:%d\n",
  132. _pin, _boolState, _time, _count);
  133. #endif
  134. delay(500);
  135. }