All examples communicate with the Virtuino Cloud HTTP REST API using the VirtuinoCloud Arduino library — a lightweight, open-source wrapper that handles HTTPS, JSON serialization and multi-board support so your sketches stay short and readable.
Each example sends or receives data over HTTPS to https://api.virtuino.com/api/data. If you prefer to call the API directly without a library, see the HTTP API Guide.
Supports ESP32, ESP8266, Uno WiFi Rev2, MKR WiFi 1010, Nano 33 IoT and Nano RP2040 Connect. The correct HTTP backend is selected automatically at compile time — no configuration needed.
iliaslamprou/VirtuinoCloud on GitHubhttps://arduino.esp8266.com/stable/package_esp8266com_index.json
DEVICE string in your sketch must match the device name in the Console exactly.
| Board | WiFi chip | WiFi include | Extra library |
|---|---|---|---|
| ESP32 (all variants) | built-in | #include <WiFi.h> | none |
| ESP8266 — NodeMCU, Wemos D1 Mini, etc. | built-in | #include <ESP8266WiFi.h> | none |
| Uno WiFi Rev2 | NINA-W102 | #include <WiFiNINA.h> | ArduinoHttpClient |
| MKR WiFi 1010 | NINA-W102 | #include <WiFiNINA.h> | ArduinoHttpClient |
| Nano 33 IoT | NINA-W102 | #include <WiFiNINA.h> | ArduinoHttpClient |
| Nano RP2040 Connect | NINA-W102 | #include <WiFiNINA.h> | ArduinoHttpClient |
Every sketch that includes VirtuinoCloud.h has access to all of the following methods.
r.ok before using the result.bool — false on network error, wrong API key, or field not found.float or int. e.g. 23.4 / 23String. e.g. "23.4"char[] — ISO 8601 UTC timestamp. e.g. "2024-06-15T14:30:00Z"String: {"value":"23.4","time":"2024-06-15T14:30:00Z"}count records. Returns "[]" on error.count ≤ 50 on ESP8266. Server max: 5000.true on HTTP 200.publish=true also pushes to the MQTT broker — live dashboard widgets update instantly (Essential+ plan).true = publish to MQTT. Max 16 fields per block.beginWrite can be called next loop.Start here. No sensor and no wiring needed — the sketch makes up a value around 25 and sends it every 3 seconds, so a gauge or chart on your dashboard starts moving straight away. Fill in your WiFi and API key, upload, and you are done.
demo_device and add a field named
demo_field_1. Use those exact names and the sketch below runs unmodified.
#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY"; // Console → API & Connections
const char* DEVICE = "demo_device"; // must match device name in Console exactly
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
float sensor_value = 25 + random(-5,+5); // replace with a real sensor read
bool ok = cloud.write(DEVICE, "demo_field_1", sensor_value);
Serial.println(ok ? "Uploaded" : "Upload failed — check WiFi and API key");
delay(3000); // upload every 3 seconds
}#include <WiFiNINA.h> // WiFiNINA boards — use this instead of <WiFi.h>
#include <VirtuinoCloud.h> // also install ArduinoHttpClient from Library Manager
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "demo_device";
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
float sensor_value = 25 + random(-5,+5); // replace with a real sensor read
bool ok = cloud.write(DEVICE, "demo_field_1", sensor_value);
Serial.println(ok ? "Uploaded" : "Failed");
delay(3000);
}Uploads three sensor values (temperature, humidity, pressure) in a single HTTP POST using beginWrite / add / send. Without block write, three fields would require three separate requests and three times the network latency.
temperature, humidity, pressure to your device.#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <DHT.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
#define DHT_PIN 4
DHT dht(DHT_PIN, DHT22);
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
float pressure = 1013.0; // replace with a real barometer read
if (isnan(temperature) || isnan(humidity)) {
Serial.println("DHT22 read failed"); delay(5000); return;
}
// beginWrite() starts a new block — does NOT send yet
cloud.beginWrite(DEVICE);
// add() queues a field value
// publish=true → also push to MQTT broker for live dashboard widgets
cloud.add("temperature", temperature, true);
cloud.add("humidity", humidity, true);
cloud.add("pressure", pressure); // no publish for this one
// Optional: set a shared timestamp for all fields in this block
// cloud.add("time", "2024-06-15T14:30:00Z");
// send() transmits all queued fields in ONE HTTP POST, then resets the queue
bool ok = cloud.send();
if (ok) Serial.printf("Uploaded — T:%.1f H:%.1f P:%.1f\n", temperature, humidity, pressure);
else Serial.println("Upload failed");
delay(30000);
}#include <WiFiNINA.h>
#include <DHT.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
#define DHT_PIN 2
DHT dht(DHT_PIN, DHT22);
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) { delay(5000); return; }
cloud.beginWrite(DEVICE);
cloud.add("temperature", temperature, true);
cloud.add("humidity", humidity, true);
bool ok = cloud.send();
Serial.println(ok ? "Uploaded" : "Failed");
delay(30000);
}Reads the state of two relay fields from the cloud every 5 seconds and switches the corresponding GPIO pins. A Toggle widget on the dashboard writes 1 (ON) or 0 (OFF) to each field.
relay1 and relay2.#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int RELAY1 = 26; // GPIO connected to relay module 1 (HIGH = ON)
const int RELAY2 = 27; // GPIO connected to relay module 2
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
// Read relay 1 state set by the dashboard toggle widget
VirtuinoResult r1 = cloud.read(DEVICE, "relay1");
if (r1.ok) {
digitalWrite(RELAY1, r1.asInt() ? HIGH : LOW);
Serial.print("relay1="); Serial.print(r1.asString());
Serial.print(" at "); Serial.println(r1.time); // ISO 8601 timestamp
// r1.asJson() → {"value":"1","time":"2024-06-15T14:30:00Z"}
}
VirtuinoResult r2 = cloud.read(DEVICE, "relay2");
if (r2.ok) digitalWrite(RELAY2, r2.asInt() ? HIGH : LOW);
if (!r1.ok && !r2.ok) Serial.println("Read failed — check WiFi and API key");
delay(5000); // poll every 5 seconds
}#include <WiFiNINA.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int RELAY1 = 2;
const int RELAY2 = 3;
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
VirtuinoResult r1 = cloud.read(DEVICE, "relay1");
if (r1.ok) digitalWrite(RELAY1, r1.asInt() ? HIGH : LOW);
VirtuinoResult r2 = cloud.read(DEVICE, "relay2");
if (r2.ok) digitalWrite(RELAY2, r2.asInt() ? HIGH : LOW);
delay(5000);
}Reads a speed setpoint (0–255) and a direction flag from the cloud every 2 seconds. Sets PWM on a motor driver (e.g. L298N) and a direction GPIO. A Slider widget on the dashboard controls the speed; a Toggle widget controls the direction.
speed (slider 0–255) and direction (toggle 0/1).#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int PWM_PIN = 18; // ENA pin on L298N (speed via LEDC PWM)
const int DIR_PIN = 19; // IN1 pin on L298N (direction)
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
ledcSetup(0, 1000, 8); // channel 0, 1 kHz, 8-bit resolution (0–255)
ledcAttachPin(PWM_PIN, 0);
pinMode(DIR_PIN, OUTPUT);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
// Read speed value (0–255) set by slider widget on dashboard
VirtuinoResult spd = cloud.read(DEVICE, "speed");
if (spd.ok) {
int pwm = constrain(spd.asInt(), 0, 255);
ledcWrite(0, pwm);
Serial.print("Speed: "); Serial.println(pwm);
}
// Read direction: 0 = forward, 1 = reverse
VirtuinoResult dir = cloud.read(DEVICE, "direction");
if (dir.ok) {
digitalWrite(DIR_PIN, dir.asInt() ? HIGH : LOW);
Serial.println(dir.asInt() ? "Direction: REVERSE" : "Direction: FORWARD");
}
delay(2000); // check every 2 seconds
}#include <WiFiNINA.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int PWM_PIN = 9;
const int DIR_PIN = 8;
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
pinMode(DIR_PIN, OUTPUT);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
VirtuinoResult spd = cloud.read(DEVICE, "speed");
if (spd.ok) analogWrite(PWM_PIN, constrain(spd.asInt(), 0, 255));
VirtuinoResult dir = cloud.read(DEVICE, "direction");
if (dir.ok) digitalWrite(DIR_PIN, dir.asInt() ? HIGH : LOW);
delay(2000);
}Syncs time from an NTP server and attaches an explicit ISO 8601 UTC timestamp to each block upload. Useful when you want precise control over the timestamp shown in charts, or when you are uploading historical data collected offline.
2024-06-15T14:30:00Z. If omitted, the server records the time of arrival.#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <time.h> // for configTime() and strftime()
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
VirtuinoCloud cloud(API_KEY);
// Fills buf with the current UTC time in ISO 8601 format: "2024-06-15T14:30:00Z"
void getTimestamp(char* buf, size_t len) {
time_t now = time(nullptr);
strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
}
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
// Sync time from NTP — waits until a valid epoch is received
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
Serial.print("Syncing NTP");
while (time(nullptr) < 1000000000UL) { delay(500); Serial.print("."); }
Serial.println(" done");
}
void loop() {
float temperature = 23.4; // replace with sensor read
float humidity = 61.0;
char ts[25];
getTimestamp(ts, sizeof(ts)); // e.g. "2024-06-15T14:30:00Z"
// All fields in this block share the same explicit timestamp
cloud.beginWrite(DEVICE);
cloud.add("temperature", temperature, true);
cloud.add("humidity", humidity, true);
cloud.add("time", ts); // attach the NTP timestamp
bool ok = cloud.send();
Serial.printf("%s at %s\n", ok ? "Uploaded" : "FAILED", ts);
delay(60000); // upload every minute
}#include <WiFiNINA.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
VirtuinoCloud cloud(API_KEY);
// WiFiNINA provides getTime() which returns Unix epoch seconds
// For production use consider an RTC module for a proper formatted timestamp
void getTimestamp(char* buf, size_t len) {
unsigned long ep = WiFi.getTime();
snprintf(buf, len, "epoch-%lu", ep); // simple form; convert to ISO 8601 if needed
}
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
char ts[32];
getTimestamp(ts, sizeof(ts));
cloud.beginWrite(DEVICE);
cloud.add("temperature", 23.4f, true);
cloud.add("time", ts);
Serial.println(cloud.send() ? "Uploaded" : "Failed");
delay(60000);
}Fetches the last 50 records of a field as a JSON array String, parses each entry with ArduinoJson and computes the average, minimum and maximum values. The same technique can be used to find anomalies, draw local charts, or make decisions based on trend data.
count ≤ 50 on ESP8266. ESP32 handles 500+ records comfortably.#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <ArduinoJson.h> // needed to parse the returned JSON array
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
VirtuinoCloud cloud(API_KEY);
bool fetched = false;
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected — fetching history...");
}
void loop() {
if (!fetched) {
// Returns: [{"time":"...","value":"23.4","source":"HTTP"}, ...]
// Returns "[]" on error or if the field has no data yet
String history = cloud.readHistory(DEVICE, "temperature", 50);
// Parse with ArduinoJson — allocate ~120 bytes × number of records
DynamicJsonDocument doc(8192);
DeserializationError err = deserializeJson(doc, history);
if (err) {
Serial.print("JSON parse error: "); Serial.println(err.c_str());
} else {
JsonArray arr = doc.as<JsonArray>();
float sum = 0, minVal = 1e9, maxVal = -1e9;
int n = 0;
for (JsonObject rec : arr) {
float v = atof(rec["value"] | "0");
sum += v;
minVal = min(minVal, v);
maxVal = max(maxVal, v);
Serial.printf("[%2d] %s → %.2f\n", n, (const char*)rec["time"], v);
n++;
}
if (n > 0) {
Serial.println("────────────────────────────────");
Serial.printf("Count: %d Avg: %.2f Min: %.2f Max: %.2f\n",
n, sum/n, minVal, maxVal);
} else {
Serial.println("No records — upload some data first (Example 1 or 2)");
}
}
fetched = true;
}
delay(1000);
}#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
VirtuinoCloud cloud(API_KEY);
bool fetched = false;
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nConnected");
}
void loop() {
if (!fetched) {
String history = cloud.readHistory(DEVICE, "temperature", 50);
DynamicJsonDocument doc(4096);
if (!deserializeJson(doc, history)) {
JsonArray arr = doc.as<JsonArray>();
float sum = 0; int n = 0;
for (JsonObject rec : arr) { sum += atof(rec["value"] | "0"); n++; }
if (n > 0) Serial.printf("Avg: %.2f over %d records\n", sum/n, n);
}
fetched = true;
}
delay(1000);
}A complete closed-loop control example: reads a temperature setpoint from the dashboard, measures actual temperature with a DHT22, controls a heater relay using bang-bang logic with hysteresis, and uploads all measurements in one request. Demonstrates read() and beginWrite/add/send working together.
setpoint, temperature, heater_state.setpoint | Gauge → temperature | LED → heater_state
#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <DHT.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int DHT_PIN = 4;
const int HEATER = 26; // relay controlling the heater (HIGH = ON)
DHT dht(DHT_PIN, DHT22);
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(HEATER, OUTPUT);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
// Step 1 — Read desired setpoint from dashboard (default 22°C if read fails)
VirtuinoResult sp = cloud.read(DEVICE, "setpoint");
float setpoint = sp.ok ? sp.asFloat() : 22.0f;
// Step 2 — Measure actual temperature
float actual = dht.readTemperature();
if (isnan(actual)) { Serial.println("DHT22 read failed"); delay(5000); return; }
// Step 3 — Bang-bang control with 0.5°C hysteresis
// Heater turns ON below (setpoint - 0.5) and OFF above (setpoint + 0.5)
// No change inside the 1°C deadband — prevents rapid switching
bool heaterOn = digitalRead(HEATER);
if (actual < setpoint - 0.5f) heaterOn = true;
if (actual > setpoint + 0.5f) heaterOn = false;
digitalWrite(HEATER, heaterOn ? HIGH : LOW);
// Step 4 — Upload measurements and heater state in ONE request
// publish=true → live dashboard widgets update immediately
cloud.beginWrite(DEVICE);
cloud.add("temperature", actual, true);
cloud.add("heater_state", heaterOn ? 1.0f : 0.0f, true);
bool ok = cloud.send();
Serial.printf("%s SP:%.1f Actual:%.1f Heater:%s\n",
ok ? "OK " : "FAIL", setpoint, actual, heaterOn ? "ON" : "OFF");
delay(10000); // control loop runs every 10 seconds
}#include <WiFiNINA.h>
#include <DHT.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int DHT_PIN = 2;
const int HEATER = 4;
DHT dht(DHT_PIN, DHT22);
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(HEATER, OUTPUT);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
VirtuinoResult sp = cloud.read(DEVICE, "setpoint");
float setpoint = sp.ok ? sp.asFloat() : 22.0f;
float actual = dht.readTemperature();
if (isnan(actual)) { delay(5000); return; }
bool heaterOn = digitalRead(HEATER);
if (actual < setpoint - 0.5f) heaterOn = true;
if (actual > setpoint + 0.5f) heaterOn = false;
digitalWrite(HEATER, heaterOn ? HIGH : LOW);
cloud.beginWrite(DEVICE);
cloud.add("temperature", actual, true);
cloud.add("heater_state", heaterOn ? 1.0f : 0.0f, true);
cloud.send();
delay(10000);
}A complete weather station sketch that combines multiple sensors: a DHT22 for temperature and humidity, a BMP280 for barometric pressure and altitude, and a photoresistor for light level. All six values are sent in one block write every minute. Also reads an alarm threshold from the dashboard and activates a buzzer if the temperature exceeds it.
temperature, humidity, pressure, altitude, light, alarm_threshold.#if defined(ESP32)
#include <WiFi.h> // ESP32
#else
#include <ESP8266WiFi.h> // ESP8266
#endif
#include <DHT.h>
#include <Adafruit_BMP280.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int DHT_PIN = 4;
const int LIGHT_PIN = 34; // ADC pin for photoresistor (0–4095)
const int BUZZER = 25; // alarm buzzer
DHT dht(DHT_PIN, DHT22);
Adafruit_BMP280 bmp; // I2C: SDA=21, SCL=22 on ESP32
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(BUZZER, OUTPUT);
if (!bmp.begin(0x76)) { // try 0x77 if 0x76 doesn't work
Serial.println("BMP280 not found — check wiring");
}
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
// ── Read all sensors ─────────────────────────────────────────────────────
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
float pressure = bmp.readPressure() / 100.0f; // Pa → hPa
float altitude = bmp.readAltitude(1013.25f); // sea-level pressure hPa
float light = analogRead(LIGHT_PIN) / 40.95f; // map 0–4095 → 0–100%
if (isnan(temperature) || isnan(humidity)) {
Serial.println("DHT22 read failed"); delay(5000); return;
}
// ── Check alarm threshold from dashboard ──────────────────────────────────
VirtuinoResult threshold = cloud.read(DEVICE, "alarm_threshold");
if (threshold.ok && temperature > threshold.asFloat()) {
tone(BUZZER, 1000, 500); // beep for 500 ms
Serial.printf("ALARM! Temp %.1f°C exceeds threshold %.1f°C\n",
temperature, threshold.asFloat());
}
// ── Upload all 5 sensor values in one HTTP request ────────────────────────
cloud.beginWrite(DEVICE);
cloud.add("temperature", temperature, true);
cloud.add("humidity", humidity, true);
cloud.add("pressure", pressure, true);
cloud.add("altitude", altitude);
cloud.add("light", light, true);
bool ok = cloud.send();
Serial.printf("%s T:%.1f H:%.1f P:%.1f Alt:%.0f Light:%.0f%%\n",
ok ? "OK" : "FAIL",
temperature, humidity, pressure, altitude, light);
delay(60000); // upload every minute
}#include <WiFiNINA.h>
#include <DHT.h>
#include <Adafruit_BMP280.h>
#include <VirtuinoCloud.h>
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
const char* API_KEY = "YOUR_API_KEY";
const char* DEVICE = "YOUR_DEVICE_ID";
const int DHT_PIN = 2;
const int BUZZER = 5;
DHT dht(DHT_PIN, DHT22);
Adafruit_BMP280 bmp;
VirtuinoCloud cloud(API_KEY);
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(BUZZER, OUTPUT);
if (!bmp.begin(0x76)) Serial.println("BMP280 not found");
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi connected");
}
void loop() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
float pressure = bmp.readPressure() / 100.0f;
float altitude = bmp.readAltitude(1013.25f);
float light = analogRead(A0) / 10.23f;
if (isnan(temperature) || isnan(humidity)) { delay(5000); return; }
VirtuinoResult threshold = cloud.read(DEVICE, "alarm_threshold");
if (threshold.ok && temperature > threshold.asFloat())
digitalWrite(BUZZER, HIGH);
else
digitalWrite(BUZZER, LOW);
cloud.beginWrite(DEVICE);
cloud.add("temperature", temperature, true);
cloud.add("humidity", humidity, true);
cloud.add("pressure", pressure, true);
cloud.add("altitude", altitude);
cloud.add("light", light, true);
Serial.println(cloud.send() ? "Uploaded" : "Failed");
delay(60000);
}