#include "DHT.h"
#include "HomeSpan.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <vector>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
DHT dhtBalcony(12,DHT22);
DHT dhtBedroom(13,DHT22);
DHT dhtBathroom(14,DHT22);
DHT dthLivingroom(15,DHT22);
DHT dhtKitchen(2,DHT22);
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// 'ESP32 HomeOultine', 50x48px
static const unsigned char epd_bitmap_ESP32_HomeOultine [] PROGMEM = {
0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x30,
0x00, 0x00, 0x3e, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x3e, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x00,
0x3e, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x3e, 0x00, 0xc0, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x30, 0x00, 0x00,
0x00, 0x00, 0xc0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80,
0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x02,
0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x03, 0x01, 0xf8, 0x0f, 0xc0, 0x80, 0x30, 0x00, 0x00, 0x80,
0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0,
0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x80, 0x00,
0x00, 0x00, 0x80, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00,
0x80, 0x00, 0xc0, 0x80, 0x30, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x80, 0x30, 0x00, 0x00, 0x80, 0x03,
0xc0, 0x80, 0x30, 0x00, 0x00, 0x80, 0x03, 0xc0, 0x80, 0x30, 0x00, 0x00, 0x80, 0x03, 0xc0, 0xff,
0xf0, 0x00, 0x00, 0x80, 0x03, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x80, 0x03, 0xc0, 0x00, 0x30, 0x00,
0x00, 0xff, 0xff, 0xc0, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x30, 0x00, 0x00, 0xc0,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x00
};
enum Room {
Balcony,
Bedroom,
Bathroom,
Livingroom,
Kitchen
};
enum Room selectedRoom;
static const char *ROOM_STRING[] = {
"Balcony", "Bedroom", "Bathroom", "Livingroom", "Kitchen",
};
struct dhtValue
{
float temperature;
float humidity;
};
struct dhtValue roomsValue[5] = {
{25,50},
{25,50},
{25,50},
{25,50},
{25,50}
};
int lastState = HIGH; // the previous state from the input pin
int currentState; // the current reading from the input pin
struct DHTTempSensor : Service::TemperatureSensor{
int myDhtID;
SpanCharacteristic *temp;
SpanCharacteristic *name;
DHTTempSensor(int dhtID) : Service::TemperatureSensor(){
temp=new Characteristic::CurrentTemperature();
temp->setRange(-50,100);
name=new Characteristic::ConfiguredName(ROOM_STRING[dhtID]);
myDhtID=dhtID;
} // end constructor()
boolean update(){
name->getNewVal();
return(true);
}
boolean setNewValue(){
temp->setVal(roomsValue[myDhtID].temperature);
return(true);
}
};
std::vector<DHTTempSensor*> dhtTempSensors;
void setup()
{
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
pinMode(4, INPUT_PULLUP);
pinMode(18, OUTPUT);
selectedRoom = (Room)1;
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
homeSpan.begin(Category::Sensors,"Weather Station");
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
dhtTempSensors.push_back(new DHTTempSensor(0));
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
dhtTempSensors.push_back(new DHTTempSensor(1));
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
dhtTempSensors.push_back(new DHTTempSensor(2));
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
dhtTempSensors.push_back(new DHTTempSensor(3));
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
dhtTempSensors.push_back(new DHTTempSensor(4));
drawRoom();
}
unsigned long prevTime_Readings = millis();
long readingInterval = 30000;
void loop()
{
unsigned long currentTime = millis();
currentState = digitalRead(4);
if(lastState == LOW && currentState == HIGH){
Serial.println("The state changed from LOW to HIGH");
buttonPressed();
}
lastState = currentState;
if(currentTime - prevTime_Readings > readingInterval){
dhtReadings();
drawValues();
prevTime_Readings=currentTime;
}
homeSpan.poll();
}
void buttonPressed(void) {
Serial.println("Button Pressed");
//digitalWrite(18, HIGH);
//delay(100);
//digitalWrite(18, LOW);
switch(selectedRoom) {
case Balcony:
selectedRoom = (Room)1;
break;
case Bedroom:
selectedRoom = (Room)2;
break;
case Bathroom:
selectedRoom = (Room)3;
break;
case Livingroom:
selectedRoom = (Room)4;
break;
case Kitchen:
selectedRoom = (Room)0;
break;
default:
selectedRoom = (Room)0;
break;
}
drawRoom();
}
void drawRoom(void) {
Serial.println("Draw UI");
display.clearDisplay();
display.drawBitmap(
0, 16, epd_bitmap_ESP32_HomeOultine, 50, 48, 1);
display.display();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println(ROOM_STRING[selectedRoom]);
display.display();
drawValues();
switch(selectedRoom) {
case Balcony:
display.fillRect( 2, 24, 7, 32, WHITE);
display.display();
break;
case Bedroom:
display.fillRect( 13, 41, 8, 5, WHITE);
display.display();
display.fillRect( 13, 46, 18, 15, WHITE);
display.display();
break;
case Bathroom:
display.fillRect( 34, 46, 13, 7, WHITE);
display.display();
display.fillRect( 34, 53, 11, 5, WHITE);
display.display();
break;
case Livingroom:
display.fillRect( 13, 19, 20, 19, WHITE);
display.display();
display.fillRect( 24, 38, 9, 5, WHITE);
display.display();
break;
case Kitchen:
display.fillRect( 40, 19, 7, 4, WHITE);
display.display();
display.fillRect( 34, 23, 13, 20, WHITE);
display.display();
break;
}
}
void drawValues(void) {
Serial.println("Draw Values");
display.fillRect(54, 16, 74, 48, BLACK);
display.display();
char temperatureStr[6]; // Buffer for temperature string
char humidityStr[5]; // Buffer for humidity string
if (roomsValue[selectedRoom].temperature < 0) {
// If temperature is negative, display without decimals
snprintf(temperatureStr, sizeof(temperatureStr), "%d", (int)roomsValue[selectedRoom].temperature);
} else {
// If temperature is positive, display with one decimal place
dtostrf(roomsValue[selectedRoom].temperature, 4, 1, temperatureStr);
}
dtostrf(roomsValue[selectedRoom].humidity, 3, 1, humidityStr); // Convert humidity to string with one decimal place
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(54, 16);
display.println(temperatureStr); // Print formatted temperature
display.display();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(54, 40);
display.print(humidityStr); // Print formatted humidity
display.println("%"); // Add percentage symbol
display.display();
}
void dhtReadings(){
Serial.println("DHT Update");
roomsValue[0].temperature = dhtBalcony.readTemperature();
roomsValue[0].humidity = dhtBalcony.readHumidity();
roomsValue[1].temperature = dhtBedroom.readTemperature();
roomsValue[1].humidity = dhtBedroom.readHumidity();
roomsValue[2].temperature = dhtBathroom.readTemperature();
roomsValue[2].humidity = dhtBathroom.readHumidity();
roomsValue[3].temperature = dthLivingroom.readTemperature();
roomsValue[3].humidity = dthLivingroom.readHumidity();
roomsValue[4].temperature = dhtKitchen.readTemperature();
roomsValue[4].humidity = dhtKitchen.readHumidity();
for (auto sensor : dhtTempSensors) {
sensor->setNewValue();
}
}