- // 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);
- }
|