im using a nodemcu, which is esp8266, and a d1 mini esp32.
Under the board manager i am selecting Nodemcu 1.0, or generic esp8266
and lolin d32 pro for the d1 mini.
After the comment of Stefan i realised it had to to with the espnow vs esp_now.
i now dont have the compilation error anymore, the code just doesn't work the way it should.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <espnow.h>
int espNowChannel = 1; // Set the desired communication channel
uint8_t espNowKey[16] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; // Set your encryption key
const char* ssid = "SquirrelAP"; // Access Point SSID
const char* password = "12345678"; // Access Point password
const int onboardLedPin = 2; // GPIO 2
ESP8266WebServer server(80);
unsigned long timerDuration = 0;
unsigned long timerStartTime = 0;
unsigned long elapsedTime = 0;
unsigned long buttonEndTimes[10][5] = {0};
bool isTimerStarted = false;
bool isRelayOn = false;
String selectedAnimal = ""; // Variable to store the selected animal
// Store the state of each button (true if active, false otherwise)
bool buttonStates[10][5] = {false}; // 10 animals, each with 5 durations
const int relayPin = 0; // GPIO 0 (connected to a relay, change as per your setup)
// Macros for button durations
const int DURATION_5_MINUTES = 300;
const int DURATION_10_MINUTES = 600;
const int DURATION_20_MINUTES = 1200;
const int DURATION_30_MINUTES = 1800;
const int DURATION_60_MINUTES = 3600;
struct __attribute__((packed)) espData {
char animal[20]; // Adjust the size based on the maximum length of the animal name
int duration;
};
// MAC addresses of the 10 ESP8266 devices
uint8_t esp8266Macs[10][6] = {
{0xEC, 0xFA, 0xBC, 0x27, 0x66, 0x4F}, // Elephant
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xDE}, // Panda
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xEF}, // Squirrel
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xF0}, // DogBrown
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xF1}, // Sabertooth
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xF2}, // DogYellow
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xF3}, // Chipmunk
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xF4}, // Octopus
{0xB4, 0xE6, 0x2D, 0x31, 0x3D, 0x67}, // Cow
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xF5} // AngryBird
// Add the MAC addresses for the other 8 ESP8266 devices
};
void OnDataRecv(uint8_t *mac_addr, uint8_t *data, uint8_t len) {
// Handle data received from ESP8266 devices if needed
if (len == sizeof(espData)) {
espData receivedData;
memcpy(&receivedData, data, sizeof(receivedData));
Serial.print("Received data from: ");
for (int i = 0; i < 6; i++) {
Serial.print(mac_addr[i], HEX);
if (i < 5) {
Serial.print(":");
}
}
Serial.println();
// Convert the MAC address to a String before concatenating
String macAddressStr;
for (int i = 0; i < 6; i++) {
macAddressStr += String(mac_addr[i], HEX);
if (i < 5) {
macAddressStr += ":";
}
}
Serial.println("Received Animal: " + String(receivedData.animal));
Serial.println("Received Duration: " + String(receivedData.duration));
Serial.println("Received MAC Address: " + macAddressStr); // Use the converted MAC address String
} else {
Serial.println("Invalid data length received");
}
}
void sendCommandToESP8266(String animal, int duration) {
int animalIndex = -1;
String animals[] = {"Elephant", "Panda", "Squirrel", "DogBrown", "Sabertooth", "DogYellow", "Chipmunk", "Octopus", "Cow", "AngryBird"};
for (int i = 0; i < 10; i++) {
if (animals[i] == animal) {
animalIndex = i;
break;
}
}
if (animalIndex != -1) {
espData data;
// Convert String to char array
animal.toCharArray(data.animal, sizeof(data.animal));
data.duration = duration;
// Turn on the onboard LED to indicate data transmission
digitalWrite(onboardLedPin, HIGH);
// Send data to the corresponding ESP8266
if (esp_now_send(esp8266Macs[animalIndex], (uint8_t*)&data, sizeof(data)) != 0) {
Serial.println("Failed to send data via ESP-NOW");
// Handle send failure
}
// Wait for a short time to make the LED blink noticeable
delay(500);
// Turn off the onboard LED
digitalWrite(onboardLedPin, LOW);
}
}
void handleStartAnimalTimer() {
String animal = server.arg("animal");
int duration = server.arg("duration").toInt();
if (duration > 0) {
// Send command to the corresponding ESP8266
sendCommandToESP8266(animal, duration);
// Local processing
timerDuration = duration;
timerStartTime = millis();
elapsedTime = 0;
isTimerStarted = true;
selectedAnimal = animal; // Update the selected animal
updateButtonState(animal, duration); // Set the button state to active
} else {
isTimerStarted = false;
}
server.sendHeader("Location", "/");
server.send(302, "text/plain", "");
}
void updateButtonState(String animal, int duration) {
String animals[] = {"Elephant", "Panda", "Squirrel", "DogBrown", "Sabertooth", "DogYellow", "Chipmunk", "Octopus", "Cow", "AngryBird"};
int animalIndex = -1;
for (int i = 0; i < 10; i++) {
if (animals[i] == animal) {
animalIndex = i;
break;
}
}
if (animalIndex != -1) {
// Reset the state for the animal
for (int i = 0; i < 5; i++) {
buttonStates[animalIndex][i] = false;
buttonEndTimes[animalIndex][i] = 0; // Reset end times
}
// Set the button state to active based on the provided duration
if (duration == DURATION_5_MINUTES) {
buttonStates[animalIndex][0] = true;
buttonEndTimes[animalIndex][0] = millis() + duration * 1000;
} else if (duration == DURATION_10_MINUTES) {
buttonStates[animalIndex][1] = true;
buttonEndTimes[animalIndex][1] = millis() + duration * 1000;
} else if (duration == DURATION_20_MINUTES) {
buttonStates[animalIndex][2] = true;
buttonEndTimes[animalIndex][2] = millis() + duration * 1000;
} else if (duration == DURATION_30_MINUTES) {
buttonStates[animalIndex][3] = true;
buttonEndTimes[animalIndex][3] = millis() + duration * 1000;
} else if (duration == DURATION_60_MINUTES) {
buttonStates[animalIndex][4] = true;
buttonEndTimes[animalIndex][4] = millis() + duration * 1000;
}
}
}
void handleTimer() {
if (server.method() == HTTP_POST) {
String durationStr = server.arg("duration");
timerDuration = durationStr.toInt();
if (timerDuration > 0) {
timerStartTime = millis();
elapsedTime = 0;
isTimerStarted = true;
} else {
isTimerStarted = false;
}
}
server.sendHeader("Location", "/");
server.send(302);
}
void handleAddThirtySeconds() {
if (isTimerStarted) {
unsigned long currentTime = millis();
unsigned long latestPressTime = 0;
// Find the latest pressed time among all active buttons
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
if (buttonStates[i][j] && (buttonEndTimes[i][j] > latestPressTime)) {
latestPressTime = buttonEndTimes[i][j];
}
}
}
// Add 30 seconds to all active buttons pressed within 15 seconds of the latest pressed button
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
if (buttonStates[i][j] && (latestPressTime - buttonEndTimes[i][j] <= 15000)) {
// Add 30 seconds to the timer for this button
buttonEndTimes[i][j] += 30 * 1000; // Update the button end time accordingly
}
}
}
// Also, update the overall timer duration
timerDuration += 30;
}
server.sendHeader("Location", "/");
server.send(302);
}
void handleAddOneMinute() {
if (isTimerStarted) {
timerDuration += 60; // Add 1 minute (60 seconds) to the timer
}
server.sendHeader("Location", "/");
server.send(302);
}
void handleAddFiveMinutes() {
if (isTimerStarted) {
timerDuration += 300; // Add 5 minutes (300 seconds) to the timer
}
server.sendHeader("Location", "/");
server.send(302);
}
void handleStartRelay() {
isRelayOn = true; // Turn on the relay
digitalWrite(relayPin, HIGH); // Set the GPIO pin to HIGH to activate the relay
server.sendHeader("Location", "/");
server.send(302);
}
void handleStopTimer() {
timerDuration = 0;
elapsedTime = 0;
isTimerStarted = false;
server.sendHeader("Location", "/");
server.send(302);
}
void handleRoot() {
String html = "<html><head><style>";
html += "body { font-size: 20px; }";
html += "input[type='submit'] { font-size: 20px; padding: 10px; }";
html += "table { border-collapse: collapse; width: 100%; }";
html += "th, td { border: 1px solid black; text-align: center; padding: 15px; }";
html += ".start-button { background-color: #3498db; color: #fff; }";
html += ".active-button { background-color: #2ecc71 !important; color: #fff; }";
html += "</style></head><body>";
html += "<h1>Manual Time Setting</h1>";
html += "<form action='/timer' method='POST'>";
html += "Timer Duration (in seconds): <input type='number' name='duration' min='0'><br><br>";
html += "<input type='submit' value='Start Timer'>";
html += "<input type='submit' value='Stop Timer' formaction='/stop-timer'>";
html += "<input type='submit' value='Start Relay' formaction='/start-relay'>";
html += "<input type='submit' value='Stop Relay' formaction='/stop-relay'>";
html += "</form>";
html += "<h2>Relay Status</h2>";
html += "<p>Status: " + getRelayStatusHTML() + "</p>";
html += "<h2>Animal Timers</h2>";
html += "<table>";
html += "<tr><th>Animal</th><th>5 Minutes</th><th>10 Minutes</th><th>20 Minutes</th><th>30 Minutes</th><th>60 Minutes</th></tr>";
String animals[] = {"Elephant", "Panda", "Squirrel", "DogBrown", "Sabertooth", "DogYellow", "Chipmunk", "Octopus", "Cow", "AngryBird"};
for (int i = 0; i < 10; i++) {
html += "<tr><td>" + animals[i] + "</td>";
int durations[] = {5, 10, 20, 30, 60};
for (int j = 0; j < 5; j++) {
html += "<td><form class='start-form' action='/start-animal-timer' method='POST'>";
html += "<input type='hidden' name='animal' value='" + animals[i] + "'>";
html += "<input type='hidden' name='duration' value='" + String(durations[j] * 60) + "'>";
html += "<input class='start-button";
if (buttonStates[i][j]) {
html += " active-button";
}
html += "' type='submit' value='Start'></form></td>";
}
html += "</tr>";
}
html += "</table>";
html += "<h2>Add Time</h2>";
html += "<form action='/add-thirty-seconds' method='POST'>";
html += "<input type='submit' value='Add 30 Seconds'>";
html += "</form>";
html += "<form action='/add-one-minute' method='POST'>";
html += "<input type='submit' value='Add 1 Minute'>";
html += "</form>";
html += "<form action='/add-five-minutes' method='POST'>";
html += "<input type='submit' value='Add 5 Minutes'>";
html += "</form>";
html += "<h2>Timer Information</h2>";
html += "<p>Duration: " + String(timerDuration / 60) + " minutes</p>";
if (isTimerStarted) {
html += "<p>Time Elapsed: " + String(getElapsedTime()) + " seconds</p>";
html += "<p>Time Remaining: " + String(getRemainingMinutes()) + " minutes " + String(getRemainingSeconds()) + " seconds</p>";
html += "<p>Selected Animal: " + selectedAnimal + "</p>";
} else {
html += "<p>Time Elapsed: Not started</p>";
html += "<p>Time Remaining: Not started</p>";
html += "<p>Selected Animal: Not selected</p>";
}
html += "<script>";
html += "document.addEventListener('DOMContentLoaded', function() {";
html += " var startButtons = document.querySelectorAll('.start-form');";
html += " startButtons.forEach(function(form) {";
html += " form.addEventListener('submit', function(event) {";
html += " event.preventDefault();";
html += " var buttons = form.querySelectorAll('.start-button');";
html += " buttons.forEach(function(button) {";
html += " button.classList.remove('active-button');";
html += " });";
html += " form.querySelector('.start-button').classList.add('active-button');";
html += " setTimeout(function() {";
html += " var duration = " + String(timerDuration * 1000) + ";";
html += " form.querySelector('.start-button').classList.add('active-button');";
html += " setTimeout(function() {";
html += " form.querySelector('.start-button').classList.remove('active-button');";
html += " }, duration);";
html += " });";
html += " });";
html += "});";
html += "</script>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleStopRelay() {
isRelayOn = false;
digitalWrite(relayPin, LOW);
server.sendHeader("Location", "/");
server.send(302);
}
void handleNotFound() {
server.send(404, "text/plain", "Not found");
}
unsigned long getElapsedTime() {
unsigned long currentTime = millis();
elapsedTime = (currentTime - timerStartTime) / 1000;
return elapsedTime;
}
long getRemainingTime() {
long remainingTime = timerDuration - getElapsedTime();
if (remainingTime < 0) {
remainingTime = 0;
}
return remainingTime;
}
int getRemainingMinutes() {
int remainingMinutes = getRemainingTime() / 60;
return remainingMinutes;
}
int getRemainingSeconds() {
int remainingSeconds = getRemainingTime() % 60;
return remainingSeconds;
}
String getRelayStatusHTML() {
if (isRelayOn) {
return "<span style='color: green;'>ON</span>";
} else {
return "<span style='color: red;'>OFF</span>";
}
}
void setup() {
Serial.begin(115200);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW);
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, password);
IPAddress apIP = WiFi.softAPIP();
Serial.print("Access Point IP address: ");
Serial.println(apIP);
pinMode(onboardLedPin, OUTPUT);
digitalWrite(onboardLedPin, LOW);
// Set ESP-NOW channel
wifi_set_channel(espNowChannel);
uint8_t key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
esp_now_add_peer(esp8266Macs[0], ESP_NOW_ROLE_COMBO, 1, key, 16);
server.on("/", HTTP_GET, handleRoot);
server.on("/timer", HTTP_POST, handleTimer);
server.on("/add-thirty-seconds", HTTP_POST, handleAddThirtySeconds);
server.on("/add-one-minute", HTTP_POST, handleAddOneMinute);
server.on("/add-five-minutes", HTTP_POST, handleAddFiveMinutes);
server.on("/start-relay", HTTP_POST, handleStartRelay);
server.on("/stop-timer", HTTP_POST, handleStopTimer);
server.on("/stop-relay", HTTP_POST, handleStopRelay);
server.on("/start-animal-timer", HTTP_POST, handleStartAnimalTimer);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
if (esp_now_init() != 0) {
Serial.println("ESP-NOW initialization failed");
} else {
Serial.println("ESP-NOW initialization successful");
}
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
server.handleClient();
unsigned long currentTime = millis();
if (isTimerStarted && !isRelayOn) {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
if (buttonStates[i][j] && currentTime >= buttonEndTimes[i][j]) {
buttonStates[i][j] = false;
}
}
}
if (currentTime - timerStartTime >= (timerDuration * 1000)) {
Serial.println("Timer expired!");
timerDuration = 0;
isTimerStarted = false;
isRelayOn = true;
digitalWrite(relayPin, HIGH);
}
}
}