aboutsummaryrefslogtreecommitdiff
path: root/vote/vote.ino
blob: 44fd179b0b8286f68d20b138213f4ffbc083dbc9 (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. #define MUSSEL_VOTE_TIME_AHEAD 60000U // 1 minute
  29. #define MUSSEL_VOTE_TIME_BEHIND 120000U // 2 minutes
  30. // Limited size NOW!! can be transformed into infinite array
  31. #define STACK_SIZE 1000
  32. struct Vote {
  33. String id;
  34. unsigned long timestamp;
  35. int measure;
  36. };
  37. void begin();
  38. String desc();
  39. int read();
  40. String debug();
  41. bool push(String id, unsigned long timestamp, int measure);
  42. void printStack();
  43. bool qualifyVote(Vote vote, unsigned long currentTime);
  44. int _attitude;
  45. int _pin;
  46. bool _boolState;
  47. byte _count;
  48. unsigned long _time;
  49. // Array to store ID strings
  50. String idStack[STACK_SIZE];
  51. unsigned long timeStack[STACK_SIZE];
  52. int measureStack[STACK_SIZE];
  53. // Index of the top element in the stack, -1 means stack is empty
  54. int top = -1;
  55. int scanTime = 1; //In seconds
  56. // pointer to control Bluetooth networking
  57. BLEScan *pBLEScan;
  58. // Bluetooth beacon discovery callbacks
  59. class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  60. // decode name and temperature from Eddystone TLM advertisement
  61. void onResult(BLEAdvertisedDevice advertisedDevice) {
  62. if (advertisedDevice.haveName()
  63. && advertisedDevice.getFrameType() == BLE_EDDYSTONE_TLM_FRAME
  64. ) {
  65. BLEEddystoneTLM EddystoneTLM(&advertisedDevice);
  66. push(
  67. advertisedDevice.getName(),
  68. millis(),
  69. EddystoneTLM.getTemp()
  70. );
  71. }
  72. }
  73. };
  74. /// Function to push data onto the stack
  75. bool push(String id, unsigned long timestamp, int measure) {
  76. // Check if stack is full
  77. if (top >= STACK_SIZE - 1) {
  78. Serial.println("Stack Full");
  79. // Return false if stack is full
  80. return false;
  81. }
  82. top++;
  83. idStack[top] = id;
  84. timeStack[top] = timestamp;
  85. measureStack[top] = measure;
  86. // Return true on successful push
  87. return true;
  88. }
  89. /// Function to print stack contents
  90. void printStack() {
  91. for (int i = top; i >= 0; i--) {
  92. Serial.print("ID: "); Serial.print(idStack[i]);
  93. Serial.print(", Time: "); Serial.print(timeStack[i]);
  94. Serial.print(", measure: "); Serial.println(measureStack[i]);
  95. }
  96. }
  97. bool qualifyVote(Vote vote, unsigned long currentTime) {
  98. // If the measure is 42 (YES), check timestamp validity
  99. if (vote.measure == 42) {
  100. // If the vote's timestamp is within 1 minute, count it as YES
  101. if (currentTime - vote.timestamp <= MUSSEL_VOTE_TIME_AHEAD) {
  102. return true;
  103. }
  104. // If the vote's timestamp is older than 2 minutes, count it as NO
  105. else if (currentTime - vote.timestamp > MUSSEL_VOTE_TIME_BEHIND) {
  106. return false;
  107. }
  108. }
  109. // If the measure is 2, always count the vote as NO
  110. if (vote.measure == 2) {
  111. return false;
  112. }
  113. // Default case: vote is invalid if no conditions are met
  114. return false;
  115. }
  116. /// Dump internal variables, formatted for use with Serial Plotter
  117. ///
  118. /// @return internal variables as String
  119. String debug() {
  120. return static_cast<String>(
  121. "pin:") + _pin
  122. + "\tboolState:" + _boolState
  123. + "\ttime:" + _time
  124. + "\tcount:" + _count;
  125. }
  126. void setup() {
  127. // enable logging to serial
  128. Serial.begin(115200);
  129. esp_log_level_set("*", ESP_LOG_DEBUG);
  130. // setup Bluetooth
  131. BLEDevice::init("");
  132. pBLEScan = BLEDevice::getScan();
  133. pBLEScan->setAdvertisedDeviceCallbacks(
  134. new MyAdvertisedDeviceCallbacks());
  135. pBLEScan->setActiveScan(true);
  136. pBLEScan->setInterval(100);
  137. pBLEScan->setWindow(99);
  138. }
  139. void loop() {
  140. BLEScanResults *foundDevices = pBLEScan->start(scanTime, false);
  141. pBLEScan->clearResults();
  142. printStack();
  143. delay(500);
  144. }