Remote Health Care Monitoring System Based on Arduino Nano33 IOt and Raspberry Pi

by sananh2004 in Circuits > Arduino

1043 Views, 2 Favorites, 0 Comments

Remote Health Care Monitoring System Based on Arduino Nano33 IOt and Raspberry Pi

hand.jpg
WhatsApp Image 2023-10-22 at 15.18.53_0afa6a3c.jpg

In today's rapidly evolving world, healthcare has reached a pivotal turning point. The critical need for precise and constant health monitoring is driving innovation like never before. Smart IoT devices are becoming indispensable tools, bridging the gap between patients and healthcare professionals. These devices empower us to keep a vigilant eye on our health, allowing for timely interventions and better care.

Now, let's delve into our project – the IoT-based Remote Health Care Monitoring System.

Welcome to our project! We've created something amazing to help improve healthcare, especially for elderly people. We've harnessed the power of technology to create a remote health monitoring system that's changing the way we take care of our health. Our project makes it easy to keep track of important health information without leaving your home. We built this system to simplify healthcare, reduce hospital visits, and improve the quality of care. With our step-by-step guide, you'll discover how it works and how it can empower you to take control of your health. It allows for the convenient and secure collection of vital health data, like heart rate, SpO2 and temperature, using sensors and a user-friendly interface(GUI). This project is more than wires, sensors, and data – it's about transforming healthcare.

Supplies

Block Diagram

block.png
block2.jpg

This is a simple block diagram demonstrating the IoT Based Remote Health Care Monitoring System with Arduino nano 33 IOT and Raspberry pi. We have used 3 sensors MAX30100 Sensor for measuring the Heart rate and SpO2 levels of a person, MLX90614 Sensor for measuring the temperature of a person, and ECG sensor for measuring the ECG (electrocardiogram) of a person. All the data from the sensors is collected from the arduino nano and then the data from the cloud is collected from the Raspberry pi and displayed on the GUI. And now the data can be seen by anyone in the world.

Sensors Description

ecg.jpeg
mlx.jpeg
max.jpeg

MAX30100 Pulse Oximeter Sensor:

Pulse Oximetry is a test used to measure the oxygen level i.e. oxygen saturation of the blood. It is an easy, painless measure of how well oxygen is being sent to parts of your body furthest from your heart, such as the arms and legs. What to study more about the health care visit “https://www.hopkinsmedicine.org/”.

No doubt the Max30100 Pulse Oximeter is an amazing sensor, still it has some disadvantages it may generate incorrect readings if the finger is not properly placed. The ambient light falling on the sensor can affect the final reading. While using the Max30100 Oximeter, make sure your finger is not moving because it can result in an incorrect reading.

Max30100 Pulse Oximeter Sensor Technical Specification:

The MAX30100 operates from 1.8V and 3.3V power supplies.

Applications

  • Wearable Devices
  • Fitness Assistant Devices
  • Medical Monitoring Devices

Pinouts:

As you can see clearly the Max30100 Pulse Oximeter has a total of 5 male headers which are clearly labeled as VIN, GND, SCL, SDA, and INT. This is an i2c supported sensor and communicates with the Arduino board through i2c communication bus.

MLX90614 Temperature Sensor:

The MLX90614 is a Contactless Infrared (IR) Digital Temperature Sensor that can be used to measure the temperature of a particular object ranging from -70° C to 382.2°C. The sensor uses IR rays to measure the temperature of the object without any physical contact and communicates to the microcontroller using the I2C protocol.

MLX90614 Temperature Sensor Specifications

  • Operating Voltage: 3.6V to 5V (available in 3V and 5V version)
  • Supply Current: 1.5mA
  • Object Temperature Range: -70° C to 382.2°C
  • Ambient Temperature Range: -40° C to 125°C
  • Accuracy: 0.02°C
  • Field of View: 80°
  • Distance between object and sensor: 2cm-5cm (approx.).

Pinouts:

As you can see clearly the MLX90614 temperature Sensor has a total of 4 male headers which are clearly labeled as VIN, GND, SCL and SDA.

ECG Sensor:

The AD8232 ECG sensor is a commercial board used to calculate the electrical movement of the human heart. This action can be chart like an Electrocardiogram and the output of this is an analog reading.

Pinouts:

The heart rate monitoring sensor like AD8232 includes the pins like SDN pin, LO+ pin, LO- pin, OUTPUT pin, 3.3V pin, and GND pin. So that we can connect this IC to development boards like Arduino by soldering pins.

ECG Sensor Specifications

The features of this sensor mainly include the following.

  • Operation of single supply ranges from 2V to 3.5V
  • The front end is integrated fully with only lead ECG
  • The virtual ground can be generated through integrated reference
  • RFI filter is used internally
  • The current supply is low like 170 µA
  • The output is rail to rail
  • Shutdown pin
  • CMRR is 80 dB
  • Incorporated RLD amplifier (right leg drive
  • Electrode configurations are 2 or 3
  • The operational amplifier is uncommitted
  • It accepts half cell potential up to ±300 mV
  • Three-pole adaptable LPF with adaptable gain
  • The signal gain is high using DC blocking capacity
  • Filter settling can be improved by quick restore
  • Two-pole adaptable HPF
  • 4 mm × 4 mm and 20-lead LFCSP package


Circuit Diagram

blockdiagram.jpg

The circuit diagram of IOT based IoT Based Remote Health Care Monitoring System is shown in the figure below. If you are doing the same project then assemble the circuit as shown in the figure below:

Circuit Diagram Of Patient Health Monitoring Based On IOT:

  1. Connect MLX90614 Scl pin to A5 of Arduino, Sda pin to A4 of Arduino and the other 2 pins to Gnd and Vcc.
  2. Connect MAX30100 Scl pin to A5 of Arduino, Sda pin to A4 of Arduino and the other 2 pins to Gnd and Vcc.
  3. Connect ECG Output pin to A0, Lo- pin to D11 of Arduino, Lo+ pin to D10 of Arduino and the other 2 pins to Gnd and Vcc.

Below is the individual connections of the Sensors with Arduino nano:


Setting Up Firebase

fr.jpg
fr1.jpg
fr3.jpg
fr5.jpg
fr4.jpg

Firebase has served as a backbone of my project that ensures secure, efficient, and accessible management of health data. It acts as the central repository where all patient health metrics, including heart rate, temperature, and ECG data, are securely stored in real-time and firestore. This cloud-based platform not only provides a seamless connection between our IoT devices and the user interface but also empowers patients and healthcare providers with instantaneous access to critical information. Furthermore, Firebase guarantees data security and privacy, ensuring that sensitive patient data is protected from unauthorized access.

Steps to follow for setting up Firebase:

  1. Open firebase, then Go to Console.
  2. After going to console add a new project and name it.
  3. After that setup both the Realtime and firestore databases.
  4. And now you are good to go.

Now when you click on Real-time you can see real time data of the sensors and when you click on firestore you can view the historical data of the sensors.

Source Code of Sensors With Arduino

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include <Adafruit_MLX90614.h>

#define REPORTING_PERIOD_MS 1000

PulseOximeter pox;
uint32_t tsLastReport = 0;

Adafruit_MLX90614 mlx;

void onBeatDetected() {
 Serial.println("Beat!");
}

void setup() {
 Serial.begin(9600);
 Serial.print("Initializing pulse oximeter..");

 // Initialize the PulseOximeter instance
 // Failures are generally due to an improper I2C wiring, missing power supply
 // or wrong target chip
 if (!pox.begin()) {
  Serial.println("FAILED");
  for(;;);
 } else {
  Serial.println("SUCCESS");
 }
 pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

 mlx.begin();
 pinMode(10, INPUT); // Setup for leads off detection LO +
 pinMode(11, INPUT); // Setup for leads off detection LO -
}

void loop() {
 // Make sure to call update as fast as possible
 pox.update();

 if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
  Serial.print("Heart rate:");
  Serial.print(pox.getHeartRate());
  Serial.print(" bpm / SpO2:");
  Serial.print(pox.getSpO2());
  Serial.println("%");

  float ambientTemp = mlx.readAmbientTempC();
  float objectTemp = mlx.readObjectTempC();

  Serial.print("Ambient Temperature: ");
  Serial.print(ambientTemp);
  Serial.println(" °C");

  Serial.print("Object Temperature: ");
  Serial.print(objectTemp);
  Serial.println(" °C");

  if ((digitalRead(10) == 1) || (digitalRead(11) == 1)) {
   Serial.println('!');
  } else {
   // send the value of analog input 0:
   Serial.print("ECG Value: ");
   Serial.println(analogRead(A0));
  }

  tsLastReport = millis();
 }
 
 // Wait for a bit to keep serial data from saturating
 // Adjust the delay as needed
}

Setting Up GUI

gui.jpg
login.jpg
table.jpg

Now we would develop the GUI (Graphical user interface)

The GUI serves as a crucial bridge between the users (patients, healthcare providers, and families) and the complex data collected by the remote health monitoring system. The GUI presents real-time and historical data, of heart rate, temperature, and ECG sensor. Patients can view their health metrics, trends, and history, which can empower them to actively manage their health. They can also initiate actions like sharing data with doctors.

Steps to setup the GUI on raspberry pi:

  1. First open the raspberry pi desktop.
  2. Then open the terminal to install some of libraries:
  • pip install firebase-admin
  • python3 -m pip3 install
  • sudo apt install python3-pip3
  1. Now open the Thony editor for writting the code.

Below is the code for the GUI:

Login.py code:

from tkinter import *
from tkinter import Tk, ttk
from tkinter import messagebox
import os # You need to import this module to launch another script

# Colors
co1 = "#525561"
co2 = "#FFFFFF"
co3 = "#1D90F5"

root = Tk()
root.title("Login")
root.geometry('400x450')
root.resizable(width=False, height=False)
root.configure(bg=co1)

frame_up = Frame(root, width=310, height=50, bg=co1)
frame_up.grid(row=0, column=0)

frame_down = Frame(root, width=310, height=400, bg=co1)
frame_down.grid(row=1, column=0)
heading = Label(frame_up, text="LOGIN", bg=co1, font=('yu gothic ui Bold', 23), fg=co2)
heading.place(x=80, y=5)


line = Label(frame_up, width=40, text="", height=1, bg=co3, anchor=NW)
line.place(x=10, y=45)
label_style = {"font": ('yu gothic ui Regular', 15), "fg": co2, "bg": co1, "anchor": NW}
username = Label(frame_down, text="username *", height=1, **label_style)

username.place(x=10, y=10)

e_name = Entry(frame_down, width=25, justify='left', font=("", 15), highlightthickness=1)
e_name.place(x=14, y=48)
password = Label(frame_down, text="password *", height=1, **label_style)
password.place(x=10, y=95)
e_password = Entry(frame_down, width=25, justify='left', show='*', font=("", 15), highlightthickness=1)

e_password.place(x=14, y=130)
email = Label(frame_down, text="email *", height=1, **label_style)
email.place(x=10, y=175)
e_email = Entry(frame_down, width=25, justify='left', font=("", 15), highlightthickness=1)

e_email.place(x=14, y=210)
email_password = Label(frame_down, text="email password *", height=1, **label_style)

email_password.place(x=10, y=255)

e_email_password = Entry(frame_down, width=25, justify='left', show='*', font=("", 15), highlightthickness=1)
e_email_password.place(x=14, y=290)

# Button

button_confirm = Button(frame_down, text="Login", bg=co3, fg=co1, width=39, height=2, font=("Ivy 9 bold"))
button_confirm.place(x=35, y=400)

# Credentials
credentials = [
  ['harshita', 'harshita', 'harshita.sanan@gmail.com', 'harshita20'],
  ['jhanvi', 'jhanvi', 'jhanvi@gmail.com', 'jhanvi']
]

def check_password():
  name = e_name.get()
  password = str(e_password.get())
  email = e_email.get()
  email_password = e_email_password.get()
   
  for user in credentials:
    if name == user[0] and password == user[1] and email == user[2] and email_password == user[3]:
      messagebox.showinfo('Login', f'Welcome, {name}!')
      # Launch the my_firebase.py script
      os.system('python my_firebase.py')
      return # Exit the loop if a matching user is found

  messagebox.showwarning('Error', 'Invalid username, password, email, or email password')

button_confirm = Button(frame_down, text="Login", bg=co3, fg=co1, width=39, height=2, font=("Ivy 9 bold"), command=check_password)
button_confirm.place(x=15, y=335)

root.mainloop()


Data extraction code:

import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkcalendar import Calendar
import firebase_admin
from firebase_admin import credentials, firestore
from datetime import datetime
import pyrebase
import os
import requests

# Initialize Firebase Admin SDK with your JSON key file
cred = credentials.Certificate("/home/harshita_sanan/Desktop/firestore/sensordata-5b22b-firebase-adminsdk-4978y-469cc2463e.json")
firebase_admin.initialize_app(cred)

# Create a Firestore client
db = firestore.client()

def retrieve_historical_data():
  selected_date_str = date_picker.get_date()
  selected_time = time_entry.get()
  # Parse the selected date string to a datetime object
  selected_datetime_str = f"{selected_date_str} {selected_time}"

  # Parse the combined date and time string to a datetime object
  selected_datetime = datetime.strptime(selected_datetime_str, "%m/%d/%Y %I:%M%p")

  # Format the selected date to match the Firestore timestamp format
  formatted_date = selected_datetime.strftime("%B %d, %Y at %I:%M%p")

  # Access a Firestore collection and retrieve data from documents with a specific timestamp
  collection_ref = db.collection("patientData")

  # Define a query to filter documents by the timestamp field
  query = collection_ref.where("timestamp", "==", formatted_date)

  # Retrieve matching documents
  docs = query.stream()

  data_str = ""
  for doc in docs:
    data = doc.to_dict()
    data_str += f"Data: {data}\n"

  if data_str:
    result_label.config(text=data_str)
  else:
    result_label.config(text=f"No documents found for {formatted_date}")

def SubmitData():
  config = {
    "apiKey": "AIz*************",
    "authDomain": "senso***********",
    "databaseURL": "https*****************",
    "storageBucket": "se*******************"
  }

  firebase = pyrebase.initialize_app(config)
  db_realtime = firebase.database()
  data = db_realtime.child("Patient Data").get().val()

  if data:
    HeartRate = data.get("Heart")
    SPO2 = data.get("Spo2")
    Temperature = data.get("Temp")

    webhook_url = "https://maker.ifttt.com/trigge*******************"
    data_to_send = {
      "value1": HeartRate,
      "value2": SPO2,
      "value3": Temperature
    }
    response = requests.post(webhook_url, json=data_to_send)
    if response.status_code == 200:
      print("Request Sent")
    else:
      print("Request Not Sent")
  else:
    print("Real-time data not found in the Realtime Database.")
 
   
def retrieve_realtime_data():
  def update_realtime_data():
    config = {
       
      "apiKey": "AIzaSyBeA6*************",
      "authDomain": "sensorda****************",
      "databaseURL": "https://sensordata-******************",
      "storageBucket": "sensorda****************"
    }
     

    firebase = pyrebase.initialize_app(config)
    db_realtime = firebase.database()

    data = db_realtime.child("Patient Data").get().val()

    if data is not None:
      ECG = data.get("ECG")
      HeartRate = data.get("Heart")
      SPO2 = data.get("Spo2")
      Temperature = data.get("Temp")

      # Update your Tkinter UI with the new data
      data_str = f"Real-time Data:\nHeart Rate: {HeartRate}\nSPO2: {SPO2}\nTemperature: {Temperature}\nECG: {ECG}"
       
       
      realtime_label.config(text=data_str, font=("Helvetica", 30), bg="black", fg="white")

    # Schedule the next update in milliseconds (e.g., every 1000ms for 1 second)
    root.after(1000, update_realtime_data)

  realtime_window = tk.Toplevel()
  realtime_window.title("Real-Time Data")
   
  window_width = 800
  window_height = 400
  screen_width = realtime_window.winfo_screenwidth()
  screen_height = realtime_window.winfo_screenheight()
   
  x = (screen_width - window_width) // 2
  y = (screen_height - window_height) // 2
   
  realtime_window.geometry(f"{window_width}x{window_height}+{x}+{y}")
   

  realtime_label = tk.Label(realtime_window, text="", font=("Helvetica", 30), bg="black", fg="white")
  #realtime_label.pack()
  realtime_label.grid(row=0, column=0, sticky="nsew")
  # Use grid layout and sticky to fill the window
  submit_button = tk.Button(realtime_window, text="Submit Data", command=SubmitData, font=("Helvetica", 16))
  submit_button.grid(row=1, column=0, padx=20, pady=10)
  # Configure the grid to expand and fill the available space
  realtime_window.grid_rowconfigure(0, weight=1)
  realtime_window.grid_columnconfigure(0, weight=1)
  update_realtime_data()

root = tk.Tk()
root.title("Firestore Data Retrieval")

#root.attributes('-fullscreen', True)
# Create a date picker widget

style = ttk.Style()
style.configure("TButton", background="black", foreground="white")
style.configure("TLabel", background="black", foreground="white")
style.layout("TButton", [("Button.focus", {"children": [("Button.padding", {"children": [("Button.label", {"side": "left", "expand": 1})]})]})])

# Configure the Calendar widget
date_picker = Calendar(root, date_pattern="mm/dd/yyyy", background="black", foreground="white", headersbackground="black", headersforeground="white", bordercolor="black", normalbackground="black", normalforeground="white", othermonthbackground="black", othermonthforeground="grey")
date_picker.pack(fill='both', expand=True)
date_picker.config(font=('Helvetica', 20))
# Create a time entry field
time_label = tk.Label(root, text="Select a Time (e.g., 12:00AM):", font=('Helvetica', 16))
time_label.pack()
time_entry = tk.Entry(root, font=('Helvetica', 16))
time_entry.pack()
 
# Create buttons for switching between historical and real-time data
historical_button = tk.Button(root, text="Historical Data", command=retrieve_historical_data, font=('Helvetica', 16))
historical_button.pack()

realtime_button = tk.Button(root, text="Real-Time Data", command=retrieve_realtime_data , font=('Helvetica', 16))
realtime_button.pack()
# Create buttons to show login and signup windows


result_label = tk.Label(root, text="", font=('Helvetica', 16))
result_label.pack()

root.mainloop()

Sending Data to Firebase

excel.jpg
fr4.jpg
fr5.jpg

Code for Sending the data to the Firebase Real Time and Excel sheet:

#include <WiFiNINA.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include <Adafruit_MLX90614.h>
#include "Firebase_Arduino_WiFiNINA.h"

#define DATABASE_URL "sensordata-****************" //<databaseName>.firebaseio.com or <databaseName>.<region>.firebasedatabase.app
#define DATABASE_SECRET "ytCfLvAQ******************"
#define WIFI_SSID ""
#define WIFI_PASSWORD ""

// Define Firebase data object
FirebaseData fbdo;

#define REPORTING_PERIOD_MS 1000
Adafruit_MLX90614 mlx = Adafruit_MLX90614();

PulseOximeter pox;
uint32_t tsLastReport = 0;

const char* ssid = "vivo Y35";
const char* password = "jeetasha17022004";

void onBeatDetected() {
 Serial.println("Beat!");
}

// Ifttt settings
const char* server = "maker.ifttt.com";
String eventName = "Savedata";
String IFTTT_Key = "lS4Qfe5jLcxQwrl****************";

float value1 = 0.0;
float value2 = 0.0;
float value3 = 0.0;

String path = "/Patient Data";

void setup() {
 Serial.begin(9600);

 Serial.print("Connecting to Wi-Fi");
 int status = WL_IDLE_STATUS;
 while (status != WL_CONNECTED) {
  status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print(".");
  delay(100);
 }
 Serial.println();
 Serial.print("Connected with IP: ");
 Serial.println(WiFi.localIP());
 Serial.println();

 // Provide the authentication data
 Firebase.begin(DATABASE_URL, DATABASE_SECRET, WIFI_SSID, WIFI_PASSWORD);
 Firebase.reconnectWiFi(true);

 Serial.println("Setting Sensor Data");

 // Initializing Pulse Oximeter sensor
 Serial.println();
 Serial.print("Initializing pulse oximeter..");

 // Initialize the PulseOximeter instance
 // Failures are generally due to an improper I2C wiring, missing power supply
 // or wrong target chip
 if (!pox.begin()) {
  Serial.println("FAILED");
  for (;;) {
  }
 } else {
  Serial.println("SUCCESS");
 }
 pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

 // Initializing the MLX90614 temperature sensor
 Wire.begin();
 mlx.begin();

 pinMode(10, INPUT); // Setup for leads off detection LO +
 pinMode(11, INPUT); // Setup for leads off detection LO -
  
}

void sendDataToIFTTT() {
 // Prepare the URL with event name and values
 String url = "/trigger/" + eventName + "/with/key/" + IFTTT_Key +
        "?value1=" + String(value1) + "&value2=" + String(value2) +
        "&value3=" + String(value3);

 Serial.println("Sending data to IFTTT: " + url);

 // Create a WiFiClient object
 WiFiClient client;

 // Connect to the server
 if (client.connect(server, 80)) {
  // Send an HTTP request
  client.print("GET " + url + " HTTP/1.1\r\n");
  client.print("Host: " + String(server) + "\r\n");
  client.print("Connection: close\r\n\r\n");

  // Read and print the response
  while (client.connected()) {
   if (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
   }
  }

  // Disconnect from the server
  client.stop();
 } else {
  Serial.println("Failed to connect to the server");
 }
}

void loop() {
 // Read sensor values
 // Make sure to call update as fast as possible
 pox.update();

 if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
  // Read heart rate and SpO2 values
  float heartRate = pox.getHeartRate();
  float SpO2Value = pox.getSpO2();
  float ecg=analogRead(A0);

  if (heartRate > 0 && SpO2Value > 0) {
   Serial.print("Heart rate: ");
   Serial.print(heartRate);
   Serial.print(" bpm / SpO2: ");
   Serial.print(SpO2Value);
   Serial.println("%");

   value2 = static_cast<float>(heartRate);
   value3 = static_cast<float>(SpO2Value);
   //Measuring Temp
   value1=static_cast<double>(mlx.readAmbientTempC());
    
   // Send data to IFTTT
   sendDataToIFTTT();

   // Sending data to Firebase
   if (Firebase.setFloat(fbdo, path + "/Heart", value2)) {
    Serial.println("Heart rate uploaded to Firebase");
   } else {
    Serial.println("Error uploading Heart rate to Firebase: " + fbdo.errorReason());
   }

   if (Firebase.setFloat(fbdo, path + "/Spo2", value3)) {
    Serial.println("SpO2 uploaded to Firebase");
   } else {
    Serial.println("Error uploading SpO2 to Firebase: " + fbdo.errorReason());
   }
   if (Firebase.setDouble(fbdo, path + "/Temp", value1)) {
    Serial.println("Temp uploaded to Firebase");
   } else {
    Serial.println("Error uploading SpO2 to Firebase: " + fbdo.errorReason());
   }
   if (Firebase.setDouble(fbdo, path + "/ECG", ecg)) {
    Serial.println("ECG uploaded to Firebase");
   } else {
    Serial.println("Error uploading ecg to Firebase: " + fbdo.errorReason());
   }
  } else {
   Serial.println("Invalid Heart rate or SpO2 values");
  }

  tsLastReport = millis();
 }
 
 // Continue with other code...
}


Code for sending the data of excel sheet to the Firebase Firestore database:

// function doGet(e) { 
//  Logger.log( JSON.stringify(e) ); // view parameters
//  var result = 'Ok'; // assume success
//  if (e.parameter == 'undefined') {
//   result = 'No Parameters';
//  }
//  else {
//   var sheet_id = '1JlVv88__0C_ttk5-dTRs6ZnaOfrdXzfGtWI-Dcw1AFk'; // Spreadsheet ID
//   var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet(); // get Active sheet
//   var newRow = sheet.getLastRow() + 1;
//   var rowData = [];
//   for (var param in e.parameter) {
//    Logger.log('In for loop, param=' + param);
//    var value = stripQuotes(e.parameter[param]);
//    Logger.log(param + ':' + e.parameter[param]);
//    switch (param) {
//     case 'Temperature': //Parameter
//      rowData[0] = value; //Value in column A
//      result = 'Written on column A';
//      break;
//     case 'Humidity': //Parameter
//      rowData[1] = value; //Value in column B
//      result += ' ,Written on column B';
//      break;  
//     default:
//      result = "unsupported parameter";
//    }
//   }
//   Logger.log(JSON.stringify(rowData));
//   // Write new row below
//   var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
//   newRange.setValues([rowData]);
//  }
//  // Return result of operation
//  firestore();
//  return ContentService.createTextOutput(result);
// }
// /**
// * Remove leading and trailing single or double quotes
// */
// function stripQuotes( value ) {
//  return value.replace(/^["']|['"]$/g, "");
// }

// function firestore(){
// //add firebase library to script before running the code
// //get firebase project credentials from GCP and add data from the created json key below
//  const email = "firebase-adminsd****************";
//  const key =  "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC+8XY18yTkKP6a\n1iSvF2R6FD7209nOj7iLAfQ3bSwxJEFbC0en45H7hR0L7UEt6xCxsRycms0K9xqx\nD/5iSuxioa/ItA20HF3xwymD8g93d2lurLj4xskJFkkBrqAWgRCxTwUebCpiV2zb\nfao/LnSG/mhEiLiJGI7vrn4D5e6ojJ7jkRFHV6WLJrBQVC0l7hY6D8gf8MkxdAqD\n/svlvxyP2spmojJmfPbaIxVVJwNJrX3GS9+A51Hx7bSaE3LMNWuGKcjCADEqTope\n9uAtn7mx8nAQhzr9neJ0b4rqWIX/3zk5yZAXiefN8PySthx8gEEobuzbdgFZp+e6\nl3TVr2y/AgMBAAECggEAXLDOl6XutKuJ3RQzPqP2bKTDZAK3auStyx0ptnZSy5A0\nAcRaBpAcX6Lg1NdZmrbPpdK6dvNWsgn+dRG0hXalhcPDl4SAWnyixifdUWYCSBY5\nojZKnMmy8axVyHFC2WnR9qDLdVdAw/h4qZw5Nu6QNq/tYceU/Uhkqslj9vR5hGvX\n6vJCVQhacpSM6XfxkTSMNtI4T/68oXXDbb45GIiNmtBSdw5iKwcuP9/xBAB*******************";
//  const projectId = "sensordata-5b22b";
//  var firestore = FirestoreApp.getFirestore (email, key, projectId);

// // get document data from ther spreadsheet
//  var ss = SpreadsheetApp.getActiveSpreadsheet();
//  //Give the sheetname of your spreadsheet
//  var sheetname = "IFTTT_Maker_Webhooks_Events"; 
//  var sheet = ss.getSheetByName(sheetname); 
//  // get the last row and column in order to define range
//  var sheetLR = sheet.getLastRow(); // get the last row
//  var sheetLC = sheet.getLastColumn(); // get the last column
//  var dataSR = 2; // the first row of data
//  // define the data range
//  var sourceRange = sheet.getRange(2,1,sheetLR-dataSR+1,sheetLC);

//  // get the data
//  var sourceData = sourceRange.getValues();
//  // get the number of length of the object in order to establish a loop value
//  var sourceLen = sourceData.length;
  
//  // Loop through the rows
//  for (var i= sourceLen-1;i<sourceLen;i++){
//   if (sourceData[i][1] !=='') {
//    var data = {};
    
//    data.timestamp = sourceData[i][0];
//    data.heartrate=sourceData[i][1];
//    firestore.createDocument("datalog",data);

//   } 
   
//  }
// }


//Adding all rows
function doGet(e) { 
 Logger.log( JSON.stringify(e) ); // view parameters
 var result = 'Ok'; // assume success
 if (e.parameter == 'undefined') {
  result = 'No Parameters';
 }
 else {
  var sheet_id = '1JlVv88__0C_ttk5-dTRs6ZnaOfrdXzfGtWI-Dcw1AFk'; // Spreadsheet ID
  var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet(); // get Active sheet
  var newRow = sheet.getLastRow() + 1;
  var rowData = [];
  for (var param in e.parameter) {
   Logger.log('In for loop, param=' + param);
   var value = stripQuotes(e.parameter[param]);
   Logger.log(param + ':' + e.parameter[param]);
   switch (param) {
    case 'Temperature': //Parameter
     rowData[0] = value; //Value in column A
     result = 'Written on column A';
     break;
    case 'Humidity': //Parameter
     rowData[1] = value; //Value in column B
     result += ' ,Written on column B';
     break;  
    default:
     result = "unsupported parameter";
   }
  }
  Logger.log(JSON.stringify(rowData));
  // Write new row below
  var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
  newRange.setValues([rowData]);
 }
 // Return result of operation
 firestore();
 return ContentService.createTextOutput(result);
}
/**
* Remove leading and trailing single or double quotes
*/
function stripQuotes( value ) {
 return value.replace(/^["']|['"]$/g, "");
}

function firestore(){
//add firebase library to script before running the code
//get firebase project credentials from GCP and add data from the created json key below
  const email = "firebase-adm****************************";
  const key =  "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC+8XY18yTkKP6a\n1iSvF2R6FD7209nOj7iLAfQ3bSwxJEFbC0en45H7hR0L7UEt6xCxsRycms0K9xqx\nD/5iSuxioa/ItA20HF3xwymD8g93d2lurLj4xskJFkkBrqAWgRCxTwUebCpiV2zb\nfao/LnSG/mhEiLiJGI7vrn4D5e6ojJ7jkRFHV6WLJrBQVC0l7hY6D8gf8MkxdAqD\n/svlvxyP2spmojJmfPbaIxVVJwNJrX3GS9+A51Hx7bSaE3LMNWuGKcjCADEqTope\n9uAtn7mx8nAQhzr9neJ0b4rqWIX/3zk5yZAXiefN8PySthx8gEEobuzbdgFZp+e6\nl3TVr2y/AgMBAAECggEAXLDOl6XutKuJ3RQzPqP2bKTDZAK3auStyx0ptnZSy5A0\nAcRaBpAc***********************************";
  const projectId = "sensordata-5b22b";
  var firestore = FirestoreApp.getFirestore (email, key, projectId);

// get document data from ther spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  //Give the sheetname of your spreadsheet
  var sheetname = "IFTTT_Maker_Webhooks_Events"; 
  var sheet = ss.getSheetByName(sheetname); 
  // get the last row and column in order to define range
  var sheetLR = sheet.getLastRow(); // get the last row
  var sheetLC = sheet.getLastColumn(); // get the last column
  var dataSR = 2; // the first row of data
  // define the data range
  var sourceRange = sheet.getRange(2,1,sheetLR-dataSR+1,sheetLC);

  // get the data
  var sourceData = sourceRange.getValues();
  // get the number of length of the object in order to establish a loop value
  var sourceLen = sourceData.length;
  
 // Loop through the rows
  for (var i= sourceLen-1;i<sourceLen;i++){
   if (sourceData[i][1] !=='') {
    var data = {};
    
   data.timestamp = sourceData[i][0];
   data.temperature=sourceData[i][1];
   data.spo2 = sourceData[i][2];
   data.heartrate=sourceData[i][3];
    firestore.createDocument("patientData",data);

   } 
   
 }
}App script

For sending the sensor data to firebase Firestore using google app script you can take reference from this link:

https://ashnizaster.medium.com/how-to-send-sensor-data-to-firebase-firestore-using-google-app-script-part-1-aea75ab6cbd6


Working Video

WhatsApp Image 2023-10-22 at 15.18.53_0afa6a3c.jpg
ipad.jpg

Below is the working video of my project:

https://youtu.be/7XxpJqzegEk