I made a simple script to control a relay via local web server. It works, but I just want to read the "real" relay status, if it is on or off.
#include <ESP8266WiFi.h>
const char* ssid = "myssid";
const char* password = "mypwd";
#define RELAY 0
WiFiServer server(80);
void setup() {
Serial.begin(115200);
pinMode(RELAY,OUTPUT);
digitalWrite(RELAY, LOW);
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (!client) return;
while(!client.available()) delay(1);
String request = client.readStringUntil('\r');
int value = LOW;
if (request.indexOf("/RELAY=ON") != -1){
Serial.println("RELAY=ON");
digitalWrite(RELAY,LOW);
value = LOW;
}
if (request.indexOf("/RELAY=OFF") != -1){
Serial.println("RELAY=OFF");
digitalWrite(RELAY,HIGH);
value = HIGH;
}
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("");
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head><title>Test RELAY</title></head>");
client.print("Relay is now: ");
if(value == HIGH)
client.print("OFF");
else
client.print("ON");
client.println("<br><br>");
client.println("Turn OFF RELAY<br>");
client.println("Turn ON RELAY<br>");
client.println("</html>");
delay(1);
}
With this code, when I start the esp, the relay status is off by default.
Then, I reach the web page with my desktop pc at the local ip address of the esp, and what I see is:
Relay is now: OFF
Turn OFF RELAY
Turn ON RELAY
This is correct, then I click on "Turn ON RELAY", and I see:
Relay is now: ON
Turn OFF RELAY
Turn ON RELAY
At this point the relay is really ON, but I close my browser and I reach the web page from my phone. It say:
Relay is now: OFF
Turn OFF RELAY
Turn ON RELAY
This is incorrect, because the relay is ON... How can I read the real value? I also tried with digitalRead(RELAY), but it always return 0.
It's a silly bug it took me a while to spot it. The reason is int value = LOW; in your loop method. The best way to fix that is to put it as a global var on top. That way it will not get pre-set to LOW on every request.
#include <ESP8266WiFi.h>
const char* ssid = "myssid";
const char* password = "mypwd";
int value = LOW;
... // Rest of the code
and remove the declaration of int value from your loop method.
As a side note, I would suggest you to use server.on(route, httpMethod, arduinoMethod);
to handle to request rather than putting it in your loop method. That way it has better performance and the code is 10 times more clear.
Related
Goal
I am trying to send temperature data between two Esp8266 modules.
The Server reads a temperature value from the analog pin and is supposed to host this data on a website (I don´t know the correct term for that) over a wifi access point that also runs on the Esp. The Client is supposed to receive the temperature value and output it via serial.
What works
I can connect my phone to the access point and access the data on the IP of the access point. I also can connect the client Esp to my home wifi and it outputs code from different websites.
Problem
But when I try to connect it to the Esp wifi, the wifi login/connection works, but the http.GET function outputs -1 which corresponds to the error message "HTTPC_ERROR_CONNECTION_FAILED".
While the client is connected to the wifi of the Esp my phone displays a similar error message.
I also had the problem that the esp could not continually read A0 while using the Wifi, so I had to build in a delay.
Server Code
// Import required libraries
#include "ESPAsyncWebServer.h"
#include "WiFi.h"
#include <math.h>
#include <ESP8266WiFi.h>
//Constants for temperature calculation
double T;
float V_0 = 5.02;
float R_1 = 99700.0;
float a = 283786.2;
float b = 0.06593;
float c = 49886.0;
float set = 30;
int sensorValue;
float voltage;
// Set your access point network credentials
const char* ssid = "ESP32-Access-Point";
const char* password = "123456789";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
String readTemp() {
return String((-1.0/b)*(log(((R_1*voltage)/(a*(V_0-voltage)))-(c/a)))); //Function to calculate temperature from Voltage
}
void setup(){
Serial.begin(115200);
Serial.println();
// Setting the ESP as an access point
Serial.print("Setting AP (Access Point)…");
// Remove the password parameter, if you want the AP (Access Point) to be open
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readTemp().c_str());
});
// Start server
server.begin();
}
void loop()
{
//reading of A0
Serial.println(voltage);
Serial.println(readTemp().c_str());
sensorValue = analogRead(0); //?Wifi not working, when reading A0?
delay(10);
voltage = sensorValue * (3.3 / 1023.0);
}
Client Code
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti WiFiMulti;
const char* ssid = "ESP32-Access-Point";
const char* password = "123456789";
void setup () {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting..");
}
Serial.print("Connected to ");
Serial.println(ssid);
}
void loop() {
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
HTTPClient http; //Declare an object of class HTTPClient
http.begin("http://192.168.4.1/temperature"); //Specify request destination
int httpCode = http.GET(); //Send the request
if (httpCode > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println("/////////////////////////////////////////////////////////////");
Serial.println(payload); //Print the response payload
}
else{Serial.println("Error");}
http.end(); //Close connection
}
delay(30000); //Send a request every 30 seconds
}
I would really appreciate it if anybody could help me with this because I have been tearing my hair out for weeks over this. Thanks in advance and sorry for any grammatical or spelling mistakes in advance.
I have a project in which I use an Arduino UNO and an esp8266-01.
The Arduino is used to gather water high and water low sensor information and then transmit that information over to turn on/off a latching relay for a water valve to fill my pool. It also turns off and on a solar panel to charge my batteries and also turns off and on the esp8266.
I want to be able to connect to the wifi every time the esp8266 comes on and then send water level sensor information and battery level sensor information up to thingSpeak.
In the following code I have made it so that the first time the esp8266 is powered up it tries to connect to the local wifi but since no ip and password is provided it go to access point mode and opens a sign in page. I also provide the user to input their thingSpeak write api. This data is saved to the esp8266's eeprom so that in the future it will auto connect and send information to thingSpeak. This works fine.
My problem is getting the information from the water level sensor and the battery level into the esp8266. I was first gathering the data on the Arduino and then having the esp8266 connect and upload the information using AT commands using SerialSoftware. However to get the AUTOCONNECT to work I had to reprogram the esp8266 and now it doesn't respond to AT commands. I have tried to reprogram the RX and TX pins on the ESP but it only has two reading when there is water present it reads 1024 and no water is 0. Nothing in between. The battery level doesn't register anything. Can I do this using the TX and RX pins somehow as an analog input or can I take the information (numbers) gathered on the Arduino and had them off to the ESP8266 using the TX (arduino) and RX (ESP)to send them to ThingSpeak. I am at a loss and need help.
Here is the code on the ESP8266
#include <FS.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <EEPROM.h>
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>
//NEW STUFF START
char Password[36]="";
char apiKey[16]="";
WiFiClient client;
//eeprom new end
char defaultHost[100] = ""; //Thing Speak IP address (sometime the web address causes issues with ESP's :/
long itt = 500;
long itt2 = 500;
const byte wifiResetPin = 13;
int interruptPinDebounce = 0;
long debouncing_time = 1000;
volatile unsigned long wifiResetLastMillis = 0;
bool shouldSaveConfig = false;
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;}
void handleWifiReset(){
if(millis()<wifiResetLastMillis){
wifiResetLastMillis = millis();
}
if((millis() - wifiResetLastMillis)>= debouncing_time){
Serial.println("Clearing WiFi data resetting");
WiFiManager wifiManager;
wifiManager.resetSettings();
SPIFFS.format();
ESP.reset();
delay(1000);
}
wifiResetLastMillis = millis();
}
int addr = 0;
void setup() {
//EEPROM.begin(512); //Initialize EEPROM
WiFiManager wifiManager;
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(wifiResetPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(wifiResetPin), handleWifiReset,FALLING);
WiFiManagerParameter customAPIKey("apiKey", "ThingSpeakWriteAPI", apiKey, 16);
//END NEW STUFF
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
//WiFiManager wifiManager;
//NEW STUFF START
//wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&customAPIKey);
//END NEW STUFF
//reset saved settings
//wifiManager.resetSettings();
//set custom ip for portal
//wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
wifiManager.autoConnect("AutoConnectAP");
Serial.println("Connected");
//NEW STUFF START
strcpy(apiKey, customAPIKey.getValue());
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["defaultHost"] = defaultHost;
json["apiKey"] = apiKey;
Serial.println("API");
Serial.print(apiKey);
String apiKey2 = String(apiKey);
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(configFile);
json.printTo(Serial);
delay(1000);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
//END NEW STUFF
//or use this for auto generated name ESP + ChipID
//wifiManager.autoConnect();
//Serial.println("WriteApi");
//Serial.println(apiKey);
//if you get here you have connected to the WiFi
//Serial.println("K)");
//save the custom parameters to FS
strcpy(apiKey,customAPIKey.getValue());
EEPROM.begin(512); //Initialize EEPROM
// write appropriate byte of the EEPROM.
// these values will remain there when the board is
// turned off.
EEPROM.write(addr, 'A'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'B'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'C'); //Write character A
//Write string to eeprom
String www = apiKey;
for(int i=0;i<www.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x0F+i,www[i]); //Write one by one with starting address of 0x0F
}
EEPROM.commit(); //Store data to EEPROM
//Read string from eeprom
}
//callback notifying us of the need to save config
void loop() {
Serial.begin(115200);
WiFiManager wifiManager;
if (WiFi.status() == WL_DISCONNECTED) {
wifiManager.autoConnect("AutoConnectAP");}
delay(5000);
if (WiFi.status() == WL_CONNECTED) { Serial.println("Connected");
WiFiClient client;
long itt = 500;
long itt2 = 500;
char defaultHost[100] = "api.thingspeak.com";
//HERE IS WHERE I CHANGE THE TX AND RX PIN FUNCTION
pinMode(1, FUNCTION_3);
pinMode(3, FUNCTION_3);
//THEN I ASSIGN THEM AS INPUT PINS
pinMode(1,INPUT);
pinMode(3,INPUT);
//ASSIGN EACH PIN TO AN INTERGER
const int waterInPin = 3; // Analog input pin that the potentiometer is attached to
const int BatteryInPin = 1; // Analog input pin that the battery is attached to
int waterSensorInValue;//reading our water lever sensor
int waterSensorOutValue;//conversion of water sensor value
int BatterySensorInValue;//reading our water lever sensor
int BatterySensorOutValue;//conversion of water sensor value
// put your main code here, to run repeatedly:
waterSensorInValue = analogRead(waterInPin);
BatterySensorInValue = analogRead(BatteryInPin);
waterSensorOutValue = map(waterSensorInValue,0,1024,0,225);
BatterySensorOutValue = map(BatterySensorInValue,0,1024,0,225);
Serial.println("WaterOutValue = ");
Serial.println(waterSensorOutValue );
Serial.println("WaterInValue = ");
Serial.println(waterSensorInValue );
Serial.println("BatteryOutValue = ");
Serial.println(BatterySensorOutValue );
Serial.println("BatteryInValue = ");
Serial.println(BatterySensorInValue);
//ASSIGN THE INPUT VALUES TO UPLOAD LONGS
itt = waterSensorInValue;
itt2 = BatterySensorInValue;
EEPROM.begin(512);
Serial.println(""); //Goto next line, as ESP sends some garbage when you reset it
Serial.print(char(EEPROM.read(addr))); //Read from address 0x00
addr++; //Increment address
Serial.print(char(EEPROM.read(addr))); //Read from address 0x01
addr++; //Increment address
Serial.println(char(EEPROM.read(addr))); //Read from address 0x02
//Read string from eeprom
String www;
//Here we dont know how many bytes to read it is better practice to use some terminating character
//Lets do it manually www.circuits4you.com total length is 20 characters
for(int i=0;i<16;i++)
{
www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F
}
Serial.print(www); //Print the text on serial monitor
if (client.connect(defaultHost,80))
{ // "184.106.153.149" or api.thingspeak.com
itt++; //Replace with a sensor reading or something useful
//UPLOAD TO THINGSPEAK
String postStr = www;
postStr +="&field1=";
postStr += String(itt);
postStr +="&field2=";
postStr += String(itt2);
postStr += "\r\n\r\n\r\n";
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+String (www)+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(postStr.length());
client.print("\n\n\n");
client.print(postStr);
Serial.println("% send to Thingspeak");
}
client.stop();
Serial.println("Waiting…");
}
delay(55000);
}
As I said almost everything works ok. The ESP8266 comes on when the Arduino turns it on. The sensor comes on and gets the value. A value is uploaded to ThingSpeak (just not a useful one.
Any Ideas, suggestions, examples, tutorials will be greatly appreciated. Thanks.
My suggestion is use only one ESP32 to do all this work.
It´s much simpler and easier than using two micro-controllers.
You can use the ESP32 to read and send the sensor data and save the trouble of communicating two different micros.
I have a project about the automated gate. I'm using Cytron ESP8266 Wifi Shield. I'm using it to transmit and store the ultrasonic data to my xampp localhost port 80.
But there is an error in my code on the client side.
Here is my code:
#include <CytronWiFiShield.h>
#include <CytronWiFiClient.h>
#include <CytronWiFiServer.h>
#include <SoftwareSerial.h>
const int trigPin = 5;
const int echoPin = 4;
long duration;
int distance;
ESP8266Client client;
const char *ssid = "HRHS";
const char *pass = "06031960";
IPAddress ip(192, 168, 100, 9); //The IP address i got from cmd
ESP8266Server server(80);
const char htmlHeader[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n"
"<!DOCTYPE HTML>\r\n"
"<html>\r\n";
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect. Needed for Leonardo only
}
if (!wifi.begin(2, 3))
{
Serial.println(F("Error talking to shield"));
while (1)
;
}
Serial.println(wifi.firmwareVersion());
Serial.print(F("Mode: "));
Serial.println(wifi.getMode()); // 1- station mode, 2- softap mode, 3- both
Serial.println(F("Start wifi connection"));
if (!wifi.connectAP(ssid, pass))
{
Serial.println(F("Error connecting to WiFi"));
while (1)
;
}
Serial.print(F("Connected to "));
Serial.println(wifi.SSID());
Serial.println(F("IP address: "));
Serial.println(wifi.localIP());
wifi.updateStatus();
Serial.println(wifi.status()); //2- wifi connected with ip, 3- got connection with servers or clients, 4- disconnect with clients or servers, 5- no wifi
//clientTest();
espblink(100);
server.begin();
}
void loop()
{
//Start of Program
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance = duration * 0.034 / 2;
// Prints the distance on the Serial Monitor
delay(1000);
// Connect to the server (your computer or web page)
if (client.connect("192.168.100.9", 80)) //Same local ip address from cmd
{
client.print("GET /write_data.php?"); // This
client.print("value="); // This
client.print(distance); // And this is what we did in the testing section above. We are making a GET request just like we would from our browser but now with live data from the sensor
client.println(" HTTP/1.1"); // Part of the GET request
client.println("Host: "); // IMPORTANT: If you are using XAMPP you will have to find out the IP address of your computer and put it here (it is explained in previous article). If you have a web page, enter its address (ie.Host: "www.yourwebpage.com")
client.println("Connection: close"); // Part of the GET request telling the server that we are over transmitting the message
client.println(); // Empty line
client.println(); // Empty line
client.stop(); // Closing connection to server
}
else
{
// If Arduino can't connect to the server (your computer or web page)
Serial.println("--> connection failed\n");
}
// Give the server some time to receive the data and store it. I used 10 seconds here. Be advised when delaying. If u use a short delay, the server might not capture data because of Arduino transmitting new data too soon.
delay(10000);
}
void espblink(int time)
{
for (int i = 0; i < 12; i++)
{
wifi.digitalWrite(2, wifi.digitalRead(2) ^ 1);
delay(time);
}
}
}
Hello sorry again. I'm going to update the progress here can?
I have updated the code. Please correct me if I'm able or not to do this
Okay, the shield is connected to wifi. However, still cannot connect to database xampp localhost.
I have searched many on Google but most os the solutions are using ethernet shield and to webpage, not localhost.
Im stuck here. Any help is really appreciated.
You didn't declare a (global) variable server, like
const char server[] = "www.adafruit.com";
(Like you did in void clientTest() )
But I did something else. I made my wifiShield a server itself. I am able to control led from there and monitor the data from there. Unfortunately no data storage but as long as I can monitor it from distance I am happy lol
I've been trying to get the BME680 to work and for the most part it seems to be working great. I do have one issue and that is with the gas sensor.
I write all the contents of the BME680 out to a webpage and all of the other values remain consistent.
Temperature: 77.29 *F
Humidity: 59.12 %
Pressure: 1010.45 millibars
Air Quality: 3.24 KOhms
On every refresh of the page the values for Temperature, Humidity, and Pressure all remain close to their values. They correct for a little while and show the minor fluctuations correctly. When it starts to rain the pressure goes down, the humidity goes up, etc... The issue is the Gas Sensor. On ever refresh the value keeps increasing. Regardless of whether I refresh it once per minute or per hour it keeps increasing. I'm clearly doing something wrong.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <WiFi101.h>
#include <WiFiUdp.h>
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(80);
#define SEALEVELPRESSURE_HPA (1023.03)
Adafruit_BME680 bme; // I2C
void setup() {
//Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT); // set the LED pin mode
bme.begin();
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
//Serial.println("WiFi shield not present");
while (true); // don't continue
}
// attempt to connect to WiFi network:
while ( status != WL_CONNECTED) {
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
server.begin(); // start the web server on port 80
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
//Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
//Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
if (! bme.performReading()) {
client.print("Failed to perform reading :(<br>");
return;
}
// the current weather condidtions
client.print("Temperature: ");
client.print((bme.temperature * 9/5) + 32);
client.print(" *F<br>");
client.print("Humidity: ");
client.print(bme.humidity);
client.print(" %<br>");
client.print("Pressure: ");
client.print(bme.pressure / 100.0);
client.print(" millibars<br>");
client.print("Air Quality: ");
client.print(bme.gas_resistance / 1000.0);
client.print(" KOhms<br>");
delay(2000);
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// close the connection:
client.stop();
//Serial.println("client disonnected");
}
}
I see two important points. Two for the beginning. Missing the ambient temperature and the sea-level.
Default ambient is: 25deg.C
Default sea-level is: 500 meter
Add this with correct values to your code. Then you have todo some automatic calibrations after burn in time. My own experience is that 2 weeks 24/7 is needed to get the sensor much old as needed. Next step look in the BOSCH original library and example code. Then start over again. Currently i'm rewriting the driver for the BME and BMP series for Tasmota (github). Lot's of work believe me. And i'm from the physics and chemical side. So some research helps always.
I’m having some problem with a home automation project of mine. I bought a nodeMCU v3 from aliexpress that i want to control my blinds with.
This is the code I’m using on it. I use the Arduino IDE to push this code in to the nodeMCU.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SimpleTimer.h>
// MQTT Server
const char* ssid = "****";
const char* password = "****";
const char* mqtt_server = "****";
char message_buff[100];
int photoValue = 0;
int rainValue = 0;
int photo = A0;
int rain = D6;
int relayUp = D7;
int relayDown= D8;
long interval = 10000;
long previousMillis = 0;
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void setup() {
pinMode(photo, INPUT);
pinMode(rain, INPUT);
pinMode(relayUp, OUTPUT);
pinMode(relayDown, OUTPUT);
digitalWrite(relayUp ,LOW);
digitalWrite(relayDown, LOW);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
if (client.connect("ESP8266Client")) {
client.subscribe("home/relayBlinds");
} else {
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
// Connect (or reconnect) to mqtt broker on the openhab server
reconnect();
}
// Read Photo- and Rain-sensors
photoValue = analogRead(photo);
rainValue = analogRead(rain);
// publish Temperature reading every 10 seconds
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
// publish Photo
String pubStringPhoto = String(photoValue);
pubStringPhoto.toCharArray(message_buff, pubStringPhoto.length()+1);
client.publish("home/photo", message_buff);
// publish Rain
String pubStringRain = String(rainValue);
pubStringRain.toCharArray(message_buff, pubStringRain.length()+1);
client.publish("home/rain", message_buff);
}
client.loop();
}
void callback(char* topic, byte* payload, unsigned int length) {
// MQTT inbound Messaging
int i = 0;
// create character buffer with ending null terminator (string)
for(i=0; i<length; i++) {
message_buff[i] = payload[i];
}
message_buff[i] = '\0';
String msgString = String(message_buff);
if (msgString == "BLINDSUP") {
digitalWrite(relayUp ,HIGH);
delay(5000);
digitalWrite(relayUp ,LOW);
} else if (msgString == "BLINDSDOWN") {
digitalWrite(relayDown ,HIGH);
delay(5000);
digitalWrite(relayDown ,LOW);
}
}
The plan was to have a Raspberry Pi with openHAB as a controller. I have used several guides to setup mosquitto and openHAB and i always get the same result.
So this is what happens: the nodeMCU connects to my Wifi and publishes both the rain and photo values. I can read them in the openHAB GUI without problems.
When i press the activation button in openHAB to publish BLINDSUP or BLINDSDOWN the messages arrives without any problems and i can see the message on my mosquitto terminal. Now is when the unexpected result starts happening. The same message gets delivered multiple times to my nodeMCU without it showing up in the mosquitto terminal.
I have been trying to find out why it would act this way and I think it is because the line:
if (!client.connected()) {
is false and the nodeMCU reconnects and gets the same message somehow. But it is always the first message. If I send BLINDSUP and then BLINDSDOWN it will only register BLINDSUP forever.
I'm really out of ideas how to fix this and would appreciate any help, thanks.
URL to the nodeMCU if that helps anyhow: nodeMCU
Try connecting to MQTT broker with a clean session. Probably you published the topic with the retain flag set to true.
If you do like this, the broker will deliver the last retained message when the nodeMCU connects to the broker and subscribes to the retained topic.