Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
maheshyadav216
Published © CC BY-NC-SA

CompanionCare: Empowering Independence

Assistive Technology Gadget for peoples with disabilities - Things Locator, Safety and Support for Special Needs

AdvancedFull instructions providedOver 5 days528
CompanionCare: Empowering Independence

Things used in this project

Story

Read more

Schematics

Project-CompanionCare-Empowering-Independence

CompanionCare-Device

CareTakerAlert Device

Room-Anchors-BLE-Beacon

BLE-Sensor-Beacon-Config-setup

Tag-M5StickC Plus

Tag-M5StickC Plus2

UNIHIKER-PAM8403-Speaker-Interfacing

Code

UNIHIKER-CompanionCare

Python
#=============================================================================//
# Project                - CompanionCare: Empowering Independence
# Author                 - https://www.hackster.io/maheshyadav216
# Hardware               - UNIHIKER, M5StickC Plus, XIAO ESP32S3       
# Sensors                - Fermion BLE Sensor Beacon
# Software               - Arduino IDE, PlatformIO
# GitHub Repo of Project - https://github.com/maheshyadav216/Project-CompanionCare-Empowering-Independence 
# Code last Modified on  - 24/08/2024
# Code/Content license   - (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
#============================================================================//

# Project code for UNIHIKER
# This is Main Controller Device, attached to Lanyard and to be worn around 
# neck by person with special needs
# Assistive technologies for people with disabilities

# With this device person can locate, track their important items like -
# medicine bag, Walking stick, Keychain etc. if misplaced in house
# But before that **Special Tag Devices should be permanantly attached to 
# these daily use important items/things

# This device can be used by person with limmited movement (physically)
# Using Touchscreen panel
# Peoples with Partial/full Visual impairments can also use this device 
# by use of Voice commands - Like, "Hello Robot" "Find my medicine bag"
# CompanionCare system will find that device location and display on screen,
# as well as Announce its location on speaker. Send Buzzer signal to Tag device

import time
from pinpong.board import Board, Pin
from pinpong.extension.unihiker import *
from unihiker import GUI
import paho.mqtt.client as mqtt
import threading
from DFRobot_DF2301Q import *
from unihiker import Audio  # Import the Audio module from the unihiker package

# MQTT settings
broker = "192.168.0.107"
port = 1883
topic_subscribe_medicine_bag = "home/medicine_bag"
topic_subscribe_keychain = "home/keychain"
topic_publish_medbag_buzzer = "home/UNIHIKER/medbag_buzzer"
topic_publish_keychain_buzzer = "home/UNIHIKER/keychain_buzzer"
topic_publish_careTaker_buzzer = "home/UNIHIKER/caretaker_buzzer"
topic_publish_careTaker_fallAlert = "home/UNIHIKER/caretaker_fallAlert"

username = "siot"
password = "dfrobot"

# Initialize the UNIHIKER
Board().begin()

# Instantiate the GUI class
gui = GUI()

# Instantiate the Audio class
audio = Audio()  

# Initialize location variables
medicine_bag_location = "Unknown"
keychain_location = "Unknown"

# MQTT client setup
client = mqtt.Client()
client.username_pw_set(username, password)

# The callback for when the client receives a CONNACK response from the server
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected to MQTT Broker!")
        client.subscribe(topic_subscribe_medicine_bag)
        client.subscribe(topic_subscribe_keychain)
    else:
        print(f"Failed to connect, return code {rc}")

# The callback for when a PUBLISH message is received from the server
def on_message(client, userdata, msg):
    global medicine_bag_location, keychain_location
    message = msg.payload.decode()
    if msg.topic == topic_subscribe_medicine_bag:
        medicine_bag_location = message
    elif msg.topic == topic_subscribe_keychain:
        keychain_location = message
    print(f"Message received from {msg.topic}: {message}")

client.on_connect = on_connect
client.on_message = on_message

print("Connecting to MQTT Broker...")
client.connect(broker, port, 60)

# Publish a message to a specific topic
def publish_message(topic, message):
    print(f"Publishing message to {topic}: {message}")
    client.publish(topic, message)

# Start the MQTT loop in a separate thread
def mqtt_loop():
    client.loop_forever()

mqtt_thread = threading.Thread(target=mqtt_loop)
mqtt_thread.start()

# Function to process voice Assistant Response
def asstResponseMBE(str):
    # lets process 
    if (medicine_bag_location == "Unknown"):
        audio.play('MB-NoSignal-E.mp3')
    if (medicine_bag_location == "Bedroom"):
        audio.play('MB-bed-E.mp3')
    if (medicine_bag_location == "Kitchen"):
        audio.play('MB-Kit-E.mp3')
    if (medicine_bag_location == "Living Room"):
        audio.play('MB-LR-E.mp3')
    if (medicine_bag_location == "Office"):
        audio.play('MB-Off-E.mp3')

# Function to process voice Assistant Response
def asstResponseMBH(str):
    # lets process 
    if (medicine_bag_location == "Unknown"):
        audio.play('MB-NoSignal-H.mp3')
    if (medicine_bag_location == "Bedroom"):
        audio.play('MB-bed-H.mp3')
    if (medicine_bag_location == "Kitchen"):
        audio.play('MB-Kit-H.mp3')
    if (medicine_bag_location == "Living Room"):
        audio.play('MB-LR-H.mp3')
    if (medicine_bag_location == "Office"):
        audio.play('MB-Off-H.mp3')

# Function to process voice Assistant Response
def asstResponseKE(str):
    # lets process 
    if (medicine_bag_location == "Unknown"):
        audio.play('key-NoSignal-E.mp3')
    if (medicine_bag_location == "Bedroom"):
        audio.play('key-bed-E.mp3')
    if (medicine_bag_location == "Kitchen"):
        audio.play('key-kit-E.mp3')
    if (medicine_bag_location == "Living Room"):
        audio.play('key-LR-E.mp3')
    if (medicine_bag_location == "Office"):
        audio.play('key-Off-E.mp3')

# Function to process voice Assistant Response
def asstResponseKH(str):
    # lets process 
    if (medicine_bag_location == "Unknown"):
        audio.play('key-NoSignal-H.mp3')
    if (medicine_bag_location == "Bedroom"):
        audio.play('key-bed-H.mp3')
    if (medicine_bag_location == "Kitchen"):
        audio.play('key-kit-H.mp3')
    if (medicine_bag_location == "Living Room"):
        audio.play('key-LR-H.mp3')
    if (medicine_bag_location == "Office"):
        audio.play('key-Off-H.mp3')


# DF2301Q device handling
DF2301Q = DFRobot_DF2301Q_I2C()
DF2301Q.set_volume(12)
DF2301Q.set_mute_mode(0)
DF2301Q.set_wake_time(5)

def df2301q_thread():
    print("DF2301Q Thread Started")
    while True:
        DF2301Q_CMDID = DF2301Q.get_CMDID()
        time.sleep(0.05)
        if not DF2301Q_CMDID == 0:
            if (DF2301Q_CMDID==5):
                btclick(1)
                asstResponseMBE(medicine_bag_location)
            if (DF2301Q_CMDID==6):
                btclick(3)
                asstResponseMBE(medicine_bag_location)            
            if (DF2301Q_CMDID==7 or DF2301Q_CMDID==20):
                btclick(1)
                asstResponseMBH(medicine_bag_location)
            if (DF2301Q_CMDID==8):
                btclick(3)
                asstResponseMBH(medicine_bag_location)
            if (DF2301Q_CMDID==9):
                btclick(2)
                asstResponseKE(keychain_location)
            if (DF2301Q_CMDID==10):
                btclick(4)
                asstResponseKE(keychain_location)
            if (DF2301Q_CMDID==11 or DF2301Q_CMDID==21):
                btclick(2)
                asstResponseKH(keychain_location)
            if (DF2301Q_CMDID==12):
                btclick(4)
                asstResponseKH(keychain_location)
            if (DF2301Q_CMDID==13):
                btclick(2)
                asstResponseKH(keychain_location)
            if (DF2301Q_CMDID==14):
                btclick(4)
                asstResponseKH(keychain_location)            
            if (DF2301Q_CMDID==15 or DF2301Q_CMDID==16 or DF2301Q_CMDID==17 or DF2301Q_CMDID==18 or DF2301Q_CMDID==19):
                btclick(5)

df2301q_thread = threading.Thread(target=df2301q_thread)
df2301q_thread.start()

# Fall detection in a separate thread
def fall_detection_thread():
    print("Fall Detection Thread Started")
    while True:
        Ax = accelerometer.get_x() / 16384.0
        Ay = accelerometer.get_y() / 16384.0
        Az = accelerometer.get_z() / 16384.0

        Gx = gyroscope.get_x() / 131.0
        Gy = gyroscope.get_y() / 131.0
        Gz = gyroscope.get_z() / 131.0

        x = Ax * Ax
        y = Ay * Ay
        z = Az * Az
        acc = x + y + z
        a = acc ** 0.5 * 10000

        if a < 1:
            fall = False
        elif a > 1:
            fall = True
            publish_message(topic_publish_careTaker_fallAlert, "Fall Alert")
            buzzer.play(buzzer.POWER_DOWN, buzzer.Once)

        time.sleep(0.5)

fall_detection_thread = threading.Thread(target=fall_detection_thread)
fall_detection_thread.start()


# Button Press Alert Detection thread
def button_monitor_thread():
    print("Button Monitor thread started")
    while True:
        # Check if button A is pressed
        if (button_a.is_pressed() == True) or (button_b.is_pressed() == True): 
            btclick(5)

button_monitor_thread = threading.Thread(target=button_monitor_thread)
button_monitor_thread.start()


# Define button click handlers
def btclick(data):
    if data == 1:
        gui.fill_rect(x=20, y=280, w=199, h=34, color="green")
        gui.draw_text(text=f"Medicine Bag is in: {medicine_bag_location}", x=120, y=300, font_size=10, origin="center", color="black")
    elif data == 2:
        gui.fill_rect(x=20, y=280, w=199, h=34, color="green")
        gui.draw_text(text=f"Keys are in: {keychain_location}", x=120, y=300, font_size=10, origin="center", color="black")
    elif data == 3:
        gui.fill_rect(x=20, y=280, w=199, h=34, color="green")
        gui.draw_text(text=f"Medicine Bag is in: {medicine_bag_location}", x=120, y=300, font_size=10, origin="center", color="black")
        publish_message(topic_publish_medbag_buzzer, "Buzzer: Medicine Bag")
    elif data == 4:
        publish_message(topic_publish_keychain_buzzer, "Buzzer: Keychain")
        gui.fill_rect(x=20, y=280, w=199, h=34, color="green")
        gui.draw_text(text=f"Keys are in: {keychain_location}", x=120, y=300, font_size=10, origin="center", color="black")
    elif data == 5:
        publish_message(topic_publish_careTaker_buzzer, "Buzzer: SOS Alert")
        gui.fill_rect(x=20, y=280, w=199, h=34, color="red"), 
        gui.draw_text(text="SOS Alert Sent !!", x=120, y=300, font_size=10, origin="center", color="white")
    print(data)

# GUI setup
gui.fill_rect(x=0, y=0, w=240, h=320, color="cyan", onclick=lambda: gui.fill_rect(x=20, y=280, w=199, h=34, color="cyan"))
gui.fill_circle(x=120, y=40, r=35, color="red", onclick=lambda: print("fill circle clicked"))
gui.draw_circle(x=120, y=40, r=35, width=5, color="yellow", onclick=lambda: print("Out circle clicked"))
gui.draw_rect(x=20, y=280, w=200, h=35, width=2, color=(255, 0, 0), onclick=lambda: print("rect clicked"))
gui.draw_text(text="SOS", x=120, y=40, font_size=16, origin="center", color="white", onclick=lambda: btclick(5))
txt2 = gui.draw_text(text="", x=120, y=300, font_size=10, origin="center", color="black")

# Add buttons
gui.add_button(x=120, y=100, w=200, h=30, text="Find Medicine Bag", origin='center', onclick=lambda: btclick(1))
gui.add_button(x=120, y=150, w=200, h=30, text="Find Keys", origin='center', onclick=lambda: btclick(2))
gui.add_button(x=120, y=200, w=200, h=30, text="Buzzer: Medicine Bag", origin='center', onclick=lambda: btclick(3))
gui.add_button(x=120, y=250, w=200, h=30, text="Buzzer: Keychain", origin='center', onclick=lambda: btclick(4))

while True:
    time.sleep(1)


#=================== hackster.io/maheshyadav216 ===============================#

CareTakerAlert Device

C/C++
//=============================================================================//
// Project/Tutorial       - CompanionCare: Empowering Independence
// Author                 - https://www.hackster.io/maheshyadav216
// Hardware               - UNIHIKER, M5StickC Plus, XIAO ESP32S3       
// Sensors                - Fermion BLE Sensor Beacon
// Software               - Arduino IDE, PlatformIO
// GitHub Repo of Project - https://github.com/maheshyadav216/Project-CompanionCare-Empowering-Independence 
// Code last Modified on  - 22/08/2024
//============================================================================//

// Project code for Caretaker Alert Device - XIAO ESP32S3

#include <WiFi.h>
#include <PubSubClient.h>

// WiFi settings
const char* ssid = "xxxxxxxxxxxx";
const char* password = "xxxxxxxxxx";

// MQTT settings
const char* mqtt_server = "192.168.0.107";
const int mqtt_port = 1883;
const char* topic_subscribe = "home/UNIHIKER/caretaker_buzzer";
const char* mqtt_username = "siot";
const char* mqtt_password = "dfrobot";

const int buzzerPin = 9;
volatile bool buzzerState = false;

const int redLED = 8;
const int greenLED = 7;

const int reset_button = 6;

WiFiClient espClient;
PubSubClient client(espClient);

void callback(char* topic, byte* message, unsigned int length) {
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  Serial.println(messageTemp);

  if (String(topic) == topic_subscribe) {
    if (messageTemp == "Buzzer: SOS Alert") {
      digitalWrite(buzzerPin, LOW);
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH);
      buzzerState = true;
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("CareTaker", mqtt_username, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(topic_subscribe);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(reset_button, INPUT_PULLUP);
  pinMode(greenLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(buzzerPin, OUTPUT);  
  digitalWrite(greenLED, HIGH);
  digitalWrite(redLED, LOW);
  digitalWrite(buzzerPin, HIGH);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  reconnect();
}

void loop() {
  if (!digitalRead(reset_button)) {
    digitalWrite(greenLED, HIGH);
    digitalWrite(redLED, LOW);
    digitalWrite(buzzerPin, HIGH);
    buzzerState = false;
    Serial.println("Buzzer turned off");
  }

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  delay(1000);
}

Tag-M5StickC Plus

C/C++
//============================================================================//
// Project/Tutorial       - CompanionCare: Empowering Independence
// Author                 - https://www.hackster.io/maheshyadav216
// Hardware               - UNIHIKER, M5StickC Plus, XIAO ESP32S3       
// Sensors                - Fermion BLE Sensor Beacon
// Software               - Arduino IDE, PlatformIO
// GitHub Repo of Project - https://github.com/maheshyadav216/Project-CompanionCare-Empowering-Independence 
// Code last Modified on  - 22/08/2024
//============================================================================//

// Project code for Smart Tag. M5StickC Plus
// This Tag will be attached to medicine bag

#include <WiFi.h>
#include <PubSubClient.h>
#include <BLEDevice.h>
#include <BLEScan.h>

const int scanTime = 5; // Duration of BLE scan in seconds
BLEScan* pBLEScan;

// WiFi settings
const char* ssid = "xxxxxxxx";
const char* password = "xxxxxxxxx";

// MQTT settings
const char* mqtt_server = "192.168.0.107";
const int mqtt_port = 1883;
const char* topic_subscribe = "home/UNIHIKER/medbag_buzzer";
const char* topic_publish = "home/medicine_bag";
const char* mqtt_username = "siot";
const char* mqtt_password = "dfrobot";

const int buzzerPin = 2;
volatile bool buzzerState = false;

WiFiClient espClient;
PubSubClient client(espClient);

void playTone(int pin, int frequency, int duration) {
  tone(pin, frequency, duration);
  delay(duration); // Wait for the tone to finish
  noTone(pin);     // Stop the tone on the pin
}

void buzzerON(){
  playTone(buzzerPin, 1000, 250); // Play 1000 Hz for 500 milliseconds
  delay(250);                    // Wait for a second
  playTone(buzzerPin, 1500, 500); // Play 1500 Hz for 500 milliseconds
  delay(250);                    // Wait for a second
  playTone(buzzerPin, 2000, 250); // Play 2000 Hz for 500 milliseconds
  delay(250); 
}

void callback(char* topic, byte* message, unsigned int length) {
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  Serial.println(messageTemp);

  if (String(topic) == topic_subscribe) {
    if (messageTemp == "Buzzer: Medicine Bag") {
      buzzerState = true;
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("MedicineBag", mqtt_username, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(topic_subscribe);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);
  M5.Lcd.setRotation(1);
  M5.Lcd.setTextSize(2);
  M5.Lcd.fillScreen(BLACK);

  // Initialize BLE
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); // Create a BLE scan object
  pBLEScan->setActiveScan(true); // Active scan uses more power but gets results faster
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  reconnect();
}

void loop() {
  M5.update();

  if (M5.BtnA.wasPressed()) {
    M5.Beep.mute();
    buzzerState = false;
    Serial.println("Buzzer turned off");
  }

  M5.Lcd.setCursor(0, 10);
  M5.Lcd.setTextColor(CYAN, BLACK);
  M5.Lcd.print("Medicine Bag TAG");
  M5.Lcd.setCursor(0, 50);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.print("Scanning...");
  
  // Start BLE scan
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);

  int bestRSSI = -100; // Initialize with a very low RSSI
  String nearestRoom = "Unknown";

  // Iterate through found devices
  for (int i = 0; i < foundDevices.getCount(); i++) {
    BLEAdvertisedDevice device = foundDevices.getDevice(i);

    // Check if the device is one of our room beacons
    if (device.haveName()) {
      String deviceName = device.getName().c_str();
      if (deviceName == "Bedroom-Beacon" || 
          deviceName == "Kitchen-Beacon" || 
          deviceName == "LivingRoom-Beacon" || 
          deviceName == "Office-Beacon") {
        
        int rssi = device.getRSSI();
        if (rssi > bestRSSI) {
          bestRSSI = rssi;
          // Map beacon name to room name
          if (deviceName == "Bedroom-Beacon") nearestRoom = "Bedroom";
          else if (deviceName == "Kitchen-Beacon") nearestRoom = "Kitchen";
          else if (deviceName == "LivingRoom-Beacon") nearestRoom = "Living Room";
          else if (deviceName == "Office-Beacon") nearestRoom = "Office";
        }
      }
    }
  }

  if ((buzzerState == true) && (nearestRoom != "Unknown")){
    buzzerON();
  }

  // Display the room with the strongest signal
  M5.Lcd.fillScreen(BLACK);
  if (nearestRoom != "Unknown") {
    M5.Lcd.setCursor(0, 90);
    M5.Lcd.setTextColor(GREEN, BLACK);
    M5.Lcd.printf("Nearest Room:\n%s", nearestRoom.c_str());
  } else {
    M5.Lcd.setCursor(0, 90);
    M5.Lcd.setTextColor(RED, BLACK);
    M5.Lcd.print("No beacons found");
  }

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  static unsigned long lastPublish = 0;
   if (millis() - lastPublish > 5000) {
    lastPublish = millis();
  // Example: Publish a message
  client.publish(topic_publish, nearestRoom.c_str());
  }
}

Tag-M5StickC Plus2

C/C++
//============================================================================//
// Project/Tutorial       - CompanionCare: Empowering Independence
// Author                 - https://www.hackster.io/maheshyadav216
// Hardware               - UNIHIKER, M5StickC Plus, XIAO ESP32S3       
// Sensors                - Fermion BLE Sensor Beacon
// Software               - Arduino IDE, PlatformIO
// GitHub Repo of Project - https://github.com/maheshyadav216/Project-CompanionCare-Empowering-Independence 
// Code last Modified on  - 22/08/2024
//============================================================================//

// Project code for Smart Tag. M5StickC Plus2
// This Tag will be attached to Keychain

#include <M5StickCPlus2.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <BLEDevice.h>
#include <BLEScan.h>

const int scanTime = 5; // Duration of BLE scan in seconds
BLEScan* pBLEScan;

// WiFi settings
const char* ssid = "xxxxxxxxxx";
const char* password = "xxxxxxxxxxx";

// MQTT settings
const char* mqtt_server = "192.168.0.107";
const int mqtt_port = 1883;
const char* topic_subscribe = "home/UNIHIKER/keychain_buzzer";
const char* topic_publish = "home/keychain";
const char* mqtt_username = "siot";
const char* mqtt_password = "dfrobot";

const int buzzerPin = 2;
volatile bool buzzerState = false;

WiFiClient espClient;
PubSubClient client(espClient);

void playTone(int pin, int frequency, int duration) {
  tone(pin, frequency, duration);
  delay(duration); // Wait for the tone to finish
  noTone(pin);     // Stop the tone on the pin
}

void buzzerON(){
  playTone(buzzerPin, 1000, 150); // Play 1000 Hz for 500 milliseconds
  delay(50);                    // Wait for a second
  playTone(buzzerPin, 1000, 150); // Play 1000 Hz for 500 milliseconds
  delay(1000);                    // Wait for a second
  playTone(buzzerPin, 1000, 150); // Play 1000 Hz for 500 milliseconds
  delay(50);                    // Wait for a second
  playTone(buzzerPin, 1000, 150); // Play 1000 Hz for 500 milliseconds
  delay(1000); 
}

void callback(char* topic, byte* message, unsigned int length) {
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  Serial.println(messageTemp);

  if (String(topic) == topic_subscribe) {
    if (messageTemp == "Buzzer: Keychain") {
      buzzerState = true;
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("Keychain", mqtt_username, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(topic_subscribe);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  auto cfg = M5.config();
  StickCP2.begin(cfg);
  Serial.begin(115200);
  
  StickCP2.Display.setRotation(1);
  StickCP2.Display.setTextSize(2);
  StickCP2.Display.fillScreen(BLACK);

  // Initialize BLE
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); // Create a BLE scan object
  pBLEScan->setActiveScan(true); // Active scan uses more power but gets results faster
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  reconnect();
}

void loop() {
  StickCP2.update();

  if (StickCP2.BtnA.wasPressed()) {
    StickCP2.Speaker.end();
    buzzerState = false;
    Serial.println("Buzzer turned off");
  }

  StickCP2.Display.setCursor(0, 10);
  StickCP2.Display.setTextColor(ORANGE, BLACK);
  StickCP2.Display.print("Keychain TAG");
  StickCP2.Display.setCursor(0, 50);
  StickCP2.Display.setTextColor(WHITE, BLACK);
  StickCP2.Display.print("Scanning...");

  // Start BLE scan
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);

  int bestRSSI = -100; // Initialize with a very low RSSI
  String nearestRoom = "Unknown";

  // Iterate through found devices
  for (int i = 0; i < foundDevices.getCount(); i++) {
    BLEAdvertisedDevice device = foundDevices.getDevice(i);

    // Check if the device is one of our room beacons
    if (device.haveName()) {
      String deviceName = device.getName().c_str();
      if (deviceName == "Bedroom-Beacon" || 
          deviceName == "Kitchen-Beacon" || 
          deviceName == "LivingRoom-Beacon" || 
          deviceName == "Office-Beacon") {
        
        int rssi = device.getRSSI();
        if (rssi > bestRSSI) {
          bestRSSI = rssi;
          // Map beacon name to room name
          if (deviceName == "Bedroom-Beacon") nearestRoom = "Bedroom";
          else if (deviceName == "Kitchen-Beacon") nearestRoom = "Kitchen";
          else if (deviceName == "LivingRoom-Beacon") nearestRoom = "Living Room";
          else if (deviceName == "Office-Beacon") nearestRoom = "Office";
        }
      }
    }
  }

  if ((buzzerState == true) && (nearestRoom != "Unknown")){
    buzzerON();
  }

  // Display the room with the strongest signal
  StickCP2.Display.fillScreen(BLACK);
  if (nearestRoom != "Unknown") {
    StickCP2.Display.setCursor(0, 90);
    StickCP2.Display.setTextColor(GREEN, BLACK);
    StickCP2.Display.printf("Nearest Room:\n%s", nearestRoom.c_str());
  } else {
    StickCP2.Display.setCursor(0, 90);
    StickCP2.Display.setTextColor(RED, BLACK);
    StickCP2.Display.print("No beacons found");
  }

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  
  static unsigned long lastPublish = 0;
  if (millis() - lastPublish > 5000) {
    lastPublish = millis();
  // Example: Publish a message
  client.publish(topic_publish, nearestRoom.c_str());
  }
}

Project-CompanionCare-Empowering-Independence

Credits

maheshyadav216

maheshyadav216

15 projects • 31 followers
Electronics and Embedded Systems Engineer, Maker, Tech Content Creator and Web Designer

Comments