Skip to content

Commit 0492eb0

Browse files
committed
First Release
1 parent 691f7e4 commit 0492eb0

File tree

8 files changed

+815
-0
lines changed

8 files changed

+815
-0
lines changed

GscriptCode.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
var ss = SpreadsheetApp.openById('your spreadsheet ID here');
2+
var historyWeatherSheet = SpreadsheetApp.getActive().getSheetByName('Taipei City');
3+
var logSheet = ss.getSheetByName('Log');
4+
var taipeiToday = ss.getSheetByName('Sheet2');
5+
var nextRow = logSheet.getLastRow() + 1;
6+
7+
var currentTimeDate10 = logSheet.getRange(3, 9).getDisplayValue();
8+
var currentTimeDate20 = logSheet.getRange(3, 11).getDisplayValue();
9+
var currentTimeDate30 = logSheet.getRange(3, 13).getDisplayValue();
10+
var currentTimeDate40 = logSheet.getRange(3, 15).getDisplayValue();
11+
var todayTime = logSheet.getRange(2, 3).getDisplayValue();
12+
13+
function doGet(e){
14+
//----------------------------------------------------------------------------------
15+
//write_google_sheet() function in esp32 sketch, is send data to this code block
16+
//----------------------------------------------------------------------------------
17+
//get data from ESP32
18+
if (e.parameter == 'undefined') {
19+
return ContentService.createTextOutput("Received data is undefined");
20+
}
21+
//----------------------------------------------------------------------------------
22+
ssid = e.parameters.ssid;
23+
time = e.parameters.time;
24+
date = e.parameters.date;
25+
temp = e.parameters.temp;
26+
humid = e.parameters.humid;
27+
co2 = e.parameters.co2;
28+
29+
//----------------------------------------------------------------------------------
30+
logSheet.getRange("A" + nextRow).setValue(ssid);
31+
logSheet.getRange("B" + nextRow).setValue(date);
32+
logSheet.getRange("C" + nextRow).setValue(time);
33+
logSheet.getRange("D" + nextRow).setValue(temp);
34+
logSheet.getRange("E" + nextRow).setValue(humid);
35+
logSheet.getRange("F" + nextRow).setValue(co2);
36+
//----------------------------------------------------------------------------------
37+
38+
39+
copyTodayWeather();
40+
41+
findinWeatherHistory();
42+
43+
//returns response back to ESP32
44+
return ContentService.createTextOutput("Status Updated in Google Sheet");
45+
}
46+
47+
// get all the ID values we have in the sheet we want to check them. flat will convert all the returning
48+
// 2D array of values in a 1D array with all the IDs
49+
var idRange = historyWeatherSheet.getDataRange().getValues();
50+
51+
function findinWeatherHistory() {
52+
53+
// Get the new incoming data (ID and Ok/Nok) with each form submit by accessing
54+
// the trigger object e which is the submited and new form response row
55+
56+
// Iterate for 10 years ago
57+
Logger.log("Looking for hystorical weather value...");
58+
59+
for(i=0;i<idRange.length;i++){
60+
61+
if(idRange[i][0] == currentTimeDate10){
62+
Logger.log("Found a match 10ys!");
63+
// set its value to the one submitted by the form
64+
tempValueTemp10 = historyWeatherSheet.getRange(i+1, 2).getValue();
65+
logSheet.getRange(nextRow, 9).setValue(tempValueTemp10);
66+
67+
tempValueHumid10 = historyWeatherSheet.getRange(i+1, 3).getValue();
68+
logSheet.getRange(nextRow, 10).setValue(tempValueHumid10);
69+
}
70+
71+
if(idRange[i][0] == currentTimeDate20){
72+
Logger.log("Found a match 20ys!");
73+
// set its value to the one submitted by the form
74+
tempValueTemp20 = historyWeatherSheet.getRange(i+1, 2).getValue();
75+
logSheet.getRange(nextRow, 11).setValue(tempValueTemp20);
76+
77+
tempValueHumid20 = historyWeatherSheet.getRange(i+1, 3).getValue();
78+
logSheet.getRange(nextRow, 12).setValue(tempValueHumid20);
79+
}
80+
81+
if(idRange[i][0] == currentTimeDate30){
82+
Logger.log("Found a match 30ys!");
83+
// set its value to the one submitted by the form
84+
tempValueTemp30 = historyWeatherSheet.getRange(i+1, 2).getValue();
85+
logSheet.getRange(nextRow, 13).setValue(tempValueTemp30);
86+
87+
tempValueHumid30 = historyWeatherSheet.getRange(i+1, 3).getValue();
88+
logSheet.getRange(nextRow, 14).setValue(tempValueHumid30);
89+
}
90+
91+
if(idRange[i][0] == currentTimeDate40){
92+
Logger.log("Found a match 40ys!");
93+
// set its value to the one submitted by the form
94+
tempValueTemp40 = historyWeatherSheet.getRange(i+1, 2).getValue();
95+
logSheet.getRange(nextRow, 15).setValue(tempValueTemp40);
96+
97+
tempValueHumid40 = historyWeatherSheet.getRange(i+1, 3).getValue();
98+
logSheet.getRange(nextRow, 16).setValue(tempValueHumid40);
99+
}
100+
101+
}
102+
103+
}
104+
105+
function copyTodayWeather() {
106+
107+
Logger.log("Value to look for: " + todayTime)
108+
109+
110+
// get all the ID values we have in the sheet we want to check them. flat will convert all the returning
111+
// 2D array of values in a 1D array with all the IDs
112+
var idRange2 = taipeiToday.getDataRange().getDisplayValues();
113+
114+
Logger.log("Looking for today weather value...");
115+
116+
for(i=0;i<idRange2.length;i++){
117+
118+
if(idRange2[i][24] == todayTime){
119+
Logger.log("Found a match!");
120+
// set its value to the one submitted by the form
121+
tempValueTemp = taipeiToday.getRange(i+1, 5).getValue();
122+
logSheet.getRange(nextRow, 7).setValue(tempValueTemp);
123+
124+
tempValueHumid = taipeiToday.getRange(i+1, 12).getValue();
125+
logSheet.getRange(nextRow, 8).setValue(tempValueHumid);
126+
}
127+
}
128+
129+
}

README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# HealthDesk
2+
3+
## Revision History
4+
5+
## Rev1.0
6+
- Temp, Humidity and CO2 from SCD41 sensor
7+
- Publishing to GSheet
8+
- GSheet pulls data from historical weather database
9+
- LED ring effects with NeoPixel library
10+
11+
## Rev1.1 (TBD)
12+
- Add a HMI (e-paper or LCD display)
13+
- Add a way to let the user force the update (before the 30 mins timer)
14+
- Improve conditional formatting
15+
16+
## Rev1.2 (TBD)
17+
- Add TVOC sensor (SEN55 from Sensirion)
18+
- Create an eco-friendly enclosure for the device
19+
20+
## Description
21+
An embedded system based on ESP32 and Google Sheet.
22+
23+
Arduino IDE is used to flash the ESP32.
24+
25+
Google Script code for additional functions on the Google Spreadsheet.
26+
27+
The aim of this project is to get useful data about the environment.
28+
This device can be placed in an office to know when there's a need to ventilate (high CO2 values).
29+
It also helps having an idea of the climate change in Taipei by comparing the weather conditions of today, to those of the past.
30+
31+
## How does it work?
32+
33+
The device connects to a WiFi network with the credentials stored in its memory.
34+
If the saved network is out of range, or no credentials are present in the memory, the WiFi setup will begin.
35+
36+
The ESP32 enters a WiFi setup mode by turning on an access point.
37+
A smartphone or PC can be used to connect to the ESP32 WiFi network. An intuitive webpage lets you pick an SSID and insert a password to connect to.
38+
The device restarts if the connection is successful.
39+
40+
Once the device is connected to the internet, it gathers data every 30 minutes from a Sensirion SCD41 sensor connected via I2C interface.
41+
It then push the SSID name, current time and date, temperature, humidity and CO2 values to a Google Spreadsheet.
42+
43+
The GSheet runs a Google Script (doGet) to read incoming data from the ESP32.
44+
45+
An additional function is used to gather historical weather data from a different tab in the same sheet (10, 20, 30 and 40 years ago temperature and humidity data).
46+
47+
48+
## Setup
49+
50+
See the instruction in main.ino for hardware setup.
51+
Google Script code is found in this repository.
52+
53+
Google Spreadsheet template should be as below.
54+
55+
<img src="https://github.com/fusiandrea28/HealthDesk/blob/main/GSheet_template.jpg" alt="GSheet page"/>
56+
--------
57+
58+
MIT License
59+
60+
Copyright (c) 2023 Andrea Fusi
61+
62+
Permission is hereby granted, free of charge, to any person obtaining a copy
63+
of this software and associated documentation files (the "Software"), to deal
64+
in the Software without restriction, including without limitation the rights
65+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66+
copies of the Software, and to permit persons to whom the Software is
67+
furnished to do so, subject to the following conditions:
68+
69+
The above copyright notice and this permission notice shall be included in all
70+
copies or substantial portions of the Software.
71+
72+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
78+
SOFTWARE.

main/ledRingRGB.ino

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <FastLED.h>
2+
3+
#define NUM_LEDS 12 /* The amount of pixels/leds you have */
4+
#define DATA_PIN 19 /* The pin your data line is connected to */
5+
#define LED_TYPE WS2812B /* I assume you have WS2812B leds, if not just change it to whatever you have */
6+
#define BRIGHTNESS 50 /* Control the brightness of your leds */
7+
#define SATURATION 255 /* Control the saturation of your leds */
8+
9+
CRGB leds[NUM_LEDS];
10+
11+
void ledRingSetup() {
12+
FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
13+
}
14+
15+
void ledLoop() {
16+
for (int j = 0; j < 255; j++) {
17+
for (int i = 0; i < NUM_LEDS; i++) {
18+
leds[i] = CHSV(i - (j * 2), SATURATION, BRIGHTNESS); /* The higher the value 4 the less fade there is and vice versa */
19+
}
20+
FastLED.show();
21+
delay(50); /* Change this to your hearts desire, the lower the value the faster your colors move (and vice versa) */
22+
}
23+
}

0 commit comments

Comments
 (0)