aboutsummaryrefslogtreecommitdiff
path: root/vote/vote.ino
diff options
context:
space:
mode:
Diffstat (limited to 'vote/vote.ino')
-rw-r--r--vote/vote.ino173
1 files changed, 173 insertions, 0 deletions
diff --git a/vote/vote.ino b/vote/vote.ino
new file mode 100644
index 0000000..44fd179
--- /dev/null
+++ b/vote/vote.ino
@@ -0,0 +1,173 @@
+// SPDX-FileCopyrightText: 2025 Amal Mazrah <mazrah@ruc.dk>
+// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+// SPDX-FileCopyrightText: 2025 Mennatullah Hatim Kassim <stud-mennatulla@ruc.dk>
+// SPDX-FileCopyrightText: 2025 Noor Ahmad <noora@ruc.dk>
+// SPDX-FileCopyrightText: 2025 Tanishka Suwalka <tanishkas@ruc.dk>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+/// Mussel vote - an Arduino sketch to monitor mussel biosensors
+///
+/// @version 0.0.3
+/// @see <https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z2tFBF4gN7ziG9oXtUytVQNYe3VhQ>
+/// @see <https://moodle.ruc.dk/course/view.php?id=23504>
+
+// arduino-esp32 Logging system
+// activate in Arduino IDE: Tools -> Core Debug Level
+// special: set Core Debug Level to Error for plot-friendly output
+#define CONFIG_ARDUHAL_ESP_LOG 1
+#define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
+#include <esp32-hal-log.h>
+#undef ARDUHAL_LOG_FORMAT
+#define ARDUHAL_LOG_FORMAT(letter, format) \
+ ARDUHAL_LOG_COLOR_##letter "[" #letter "] %s(): " format \
+ ARDUHAL_LOG_RESET_COLOR "\r\n", __FUNCTION__
+
+// arduino-esp32 Bluetooth Low Energy (BLE) networking stack
+#include <BLEDevice.h>
+#include <BLEScan.h>
+#include <BLEAdvertisedDevice.h>
+#include <BLEEddystoneTLM.h>
+#include <BLEBeacon.h>
+
+#define MUSSEL_VOTE_TIME_AHEAD 60000U // 1 minute
+#define MUSSEL_VOTE_TIME_BEHIND 120000U // 2 minutes
+
+// Limited size NOW!! can be transformed into infinite array
+#define STACK_SIZE 1000
+
+struct Vote {
+ String id;
+ unsigned long timestamp;
+ int measure;
+};
+
+void begin();
+String desc();
+int read();
+String debug();
+bool push(String id, unsigned long timestamp, int measure);
+void printStack();
+bool qualifyVote(Vote vote, unsigned long currentTime);
+
+int _attitude;
+int _pin;
+bool _boolState;
+byte _count;
+unsigned long _time;
+
+// Array to store ID strings
+String idStack[STACK_SIZE];
+unsigned long timeStack[STACK_SIZE];
+int measureStack[STACK_SIZE];
+
+// Index of the top element in the stack, -1 means stack is empty
+int top = -1;
+
+int scanTime = 1; //In seconds
+
+// pointer to control Bluetooth networking
+BLEScan *pBLEScan;
+
+// Bluetooth beacon discovery callbacks
+class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
+
+ // decode name and temperature from Eddystone TLM advertisement
+ void onResult(BLEAdvertisedDevice advertisedDevice) {
+ if (advertisedDevice.haveName()
+ && advertisedDevice.getFrameType() == BLE_EDDYSTONE_TLM_FRAME
+ ) {
+ BLEEddystoneTLM EddystoneTLM(&advertisedDevice);
+ push(
+ advertisedDevice.getName(),
+ millis(),
+ EddystoneTLM.getTemp()
+ );
+ }
+ }
+};
+
+/// Function to push data onto the stack
+bool push(String id, unsigned long timestamp, int measure) {
+
+ // Check if stack is full
+ if (top >= STACK_SIZE - 1) {
+ Serial.println("Stack Full");
+
+ // Return false if stack is full
+ return false;
+ }
+ top++;
+ idStack[top] = id;
+ timeStack[top] = timestamp;
+ measureStack[top] = measure;
+
+ // Return true on successful push
+ return true;
+}
+
+/// Function to print stack contents
+void printStack() {
+ for (int i = top; i >= 0; i--) {
+ Serial.print("ID: "); Serial.print(idStack[i]);
+ Serial.print(", Time: "); Serial.print(timeStack[i]);
+ Serial.print(", measure: "); Serial.println(measureStack[i]);
+ }
+}
+
+bool qualifyVote(Vote vote, unsigned long currentTime) {
+
+ // If the measure is 42 (YES), check timestamp validity
+ if (vote.measure == 42) {
+ // If the vote's timestamp is within 1 minute, count it as YES
+ if (currentTime - vote.timestamp <= MUSSEL_VOTE_TIME_AHEAD) {
+ return true;
+ }
+ // If the vote's timestamp is older than 2 minutes, count it as NO
+ else if (currentTime - vote.timestamp > MUSSEL_VOTE_TIME_BEHIND) {
+ return false;
+ }
+ }
+
+ // If the measure is 2, always count the vote as NO
+ if (vote.measure == 2) {
+ return false;
+ }
+
+ // Default case: vote is invalid if no conditions are met
+ return false;
+}
+
+/// Dump internal variables, formatted for use with Serial Plotter
+///
+/// @return internal variables as String
+String debug() {
+ return static_cast<String>(
+ "pin:") + _pin
+ + "\tboolState:" + _boolState
+ + "\ttime:" + _time
+ + "\tcount:" + _count;
+}
+
+void setup() {
+ // enable logging to serial
+ Serial.begin(115200);
+ esp_log_level_set("*", ESP_LOG_DEBUG);
+
+ // setup Bluetooth
+ BLEDevice::init("");
+ pBLEScan = BLEDevice::getScan();
+ pBLEScan->setAdvertisedDeviceCallbacks(
+ new MyAdvertisedDeviceCallbacks());
+ pBLEScan->setActiveScan(true);
+ pBLEScan->setInterval(100);
+ pBLEScan->setWindow(99);
+}
+
+void loop() {
+ BLEScanResults *foundDevices = pBLEScan->start(scanTime, false);
+ pBLEScan->clearResults();
+
+ printStack();
+
+ delay(500);
+}