Wireless remote control - arduino-esp8266

I found nice code for nodeMCu for controlling my Hue bulb.
http://www.esp8266.com/viewtopic.php?f=11&t=4389
I changed it a bit and added two buttons ON and OFF.
If I open serial monitor in sketch everything works ok.
But if I try it without serial communication the lights turn on and immediately turn off. So I have to hold the button ON to keep bulb on.
Could you help me what I have to change in code?
#include <ESP8266WiFi.h>
//buttons
const int button_on = 4;
const int button_off = 13;
int buttonState_on = 0;
int buttonState_off = 0;
// Wifi Settings
const char* ssid = "********";
const char* password = "*********";
// Hue Settings
const char* bridge_ip = "192.168.0.20"; // Hue Bridge IP
const int port = 80;
String user="RQQroZ5hePrFdHHy-eBzMBv5d7Y30QZFsDW3ydw4"; // Hue Bridge user -To create a user check this page (http://support.intuilab.com/kb/connecte ... hue-lights)
String light="4";
// Commands
String hue_on="{\"on\":true}";
String hue_off="{\"on\":false}";
void setup() {
pinMode(button_on, INPUT);
pinMode(button_off, INPUT);
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// read the state of the pushbutton value:
buttonState_on = digitalRead(button_on);
//delay(50);
buttonState_off = digitalRead(button_off);
//delay(50);
if (buttonState_on == HIGH) {
hue_control_on();}
else if (buttonState_off == HIGH) {
hue_control_off();
}
}
void hue_control_on() {
Serial.print("Connecting to ");
Serial.println(bridge_ip);
// Use WiFiClient class to create TCP connections
WiFiClient client;
if (!client.connect(bridge_ip, port)) {
Serial.println("Connection failed");
return;
}
// This will send the request to the server
client.println("PUT /api/" + user + "/lights/" + light + "/state");
client.println("Host: " + String(bridge_ip) + ":" + String(port));
client.println("User-Agent: ESP8266/1.0");
client.println("Connection: close");
client.println("Content-type: text/xml; charset=\"utf-8\"");
client.print("Content-Length: ");
client.println(hue_on.length()); // PUT COMMAND HERE
client.println();
client.println(hue_on); // PUT COMMAND HERE
delay(10);
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("Closing connection");
}
void hue_control_off() {
Serial.print("Connecting to ");
Serial.println(bridge_ip);
// Use WiFiClient class to create TCP connections
WiFiClient client;
if (!client.connect(bridge_ip, port)) {
Serial.println("Connection failed");
return;
}
// This will send the request to the server
client.println("PUT /api/" + user + "/lights/" + light + "/state");
client.println("Host: " + String(bridge_ip) + ":" + String(port));
client.println("User-Agent: ESP8266/1.0");
client.println("Connection: close");
client.println("Content-type: text/xml; charset=\"utf-8\"");
client.print("Content-Length: ");
client.println(hue_off.length()); // PUT COMMAND HERE
client.println();
client.println(hue_off); // PUT COMMAND HERE
delay(10);
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("Closing connection");
}

Related

Socket.io transport close after client connects and sends pings. ESP32/WT32-ETH01 as client

I am absolutely bewildered right now, I have been using this library WebSocket_generic (https://github.com/khoih-prog/WebSockets_Generic) for my WT32-ETH01 and it even has examples just for the board. Ive used both the server and client examples, it connects just fine, but after three messages, or roughly 90 secs give or take it suddenly and abruptly disconnects. Give it 5 minutes it reconnects, sends some more pings and it disconnects, and does so in a cycle. Here is the serverside code:
const app = require('express');
const http = require('http').createServer(app);
const io = require('socket.io')(http);
io.on('connection', (socket) => {
console.log('Connected');
console.log(socket.id);
console.log("JWT token test: ",socket.handshake.headers)
socket.on('event_name', (data) => {
console.log("Message from Client : ", data);
socket.broadcast.emit("Send Message socket.broadcast.emit : ", data);
io.emit("Send Message io.emit Broadcasted : ", data);
socket.emit("Send Message : ", data);
})
socket.on('disconnect', (reason) => {
console.log('Disconnected');
console.log(reason);
})
})
http.listen(8080, () => {
console.log("Server launched on port 8080");
})
WT32-ETH01 code (Arduino ide)
#if !defined(ESP32)
#error This code is intended to run only on the ESP32 boards ! Please check your Tools->Board setting.
#endif
#define _WEBSOCKETS_LOGLEVEL_ 2
#include <WebServer_WT32_ETH01.h> // https://github.com/khoih-prog/WebServer_WT32_ETH01
#include <ArduinoJson.h>
#include <WebSocketsClient_Generic.h>
#include <SocketIOclient_Generic.h>
SocketIOclient socketIO;
/////////////////////////////////////////////
// Select the Server's IP address according to your local network
IPAddress serverIP(192, 168, 100, 59);
uint16_t serverPort = 8080;
/////////////////////////////////////////////
// Select the IP address according to your local network
IPAddress myIP(192, 168, 100, 99);
IPAddress myGW(192, 168, 100, 1);
IPAddress mySN(255, 255, 255, 0);
// Google DNS Server IP
IPAddress myDNS(8, 8, 8, 8);
/////////////////////////////////////////////
void hexdump(const void *mem, const uint32_t& len, const uint8_t& cols = 16)
{
const uint8_t* src = (const uint8_t*) mem;
Serial.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for (uint32_t i = 0; i < len; i++)
{
if (i % cols == 0)
{
Serial.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
Serial.printf("%02X ", *src);
src++;
}
Serial.printf("\n");
}
void socketIOEvent(const socketIOmessageType_t& type, uint8_t * payload, const size_t& length)
{
switch (type)
{
case sIOtype_DISCONNECT:
Serial.println("[IOc] Disconnected");
break;
case sIOtype_CONNECT:
Serial.print("[IOc] Connected to url: ");
Serial.println((char*) payload);
// join default namespace (no auto join in Socket.IO V3)
socketIO.send(sIOtype_CONNECT, "/");
break;
case sIOtype_EVENT:
Serial.print("[IOc] Get event: ");
Serial.println((char*) payload);
break;
case sIOtype_ACK:
Serial.print("[IOc] Get ack: ");
Serial.println(length);
hexdump(payload, length);
break;
case sIOtype_ERROR:
Serial.print("[IOc] Get error: ");
Serial.println(length);
hexdump(payload, length);
break;
case sIOtype_BINARY_EVENT:
Serial.print("[IOc] Get binary: ");
Serial.println(length);
hexdump(payload, length);
break;
case sIOtype_BINARY_ACK:
Serial.print("[IOc] Get binary ack: ");
Serial.println(length);
hexdump(payload, length);
break;
case sIOtype_PING:
Serial.println("[IOc] Get PING");
break;
case sIOtype_PONG:
Serial.println("[IOc] Get PONG");
break;
default:
break;
}
}
void setup()
{
// Serial.begin(921600);
Serial.begin(115200);
while (!Serial);
Serial.print("\nStart WT32_ETH01_WebSocketClientSocketIO on ");
Serial.print(ARDUINO_BOARD);
Serial.print(" with ");
Serial.println(SHIELD_TYPE);
Serial.println(WEBSERVER_WT32_ETH01_VERSION);
Serial.println(WEBSOCKETS_GENERIC_VERSION);
Serial.setDebugOutput(true);
// To be called before ETH.begin()
WT32_ETH01_onEvent();
//bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO,
// eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE);
//ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLK_MODE);
ETH.begin(ETH_PHY_ADDR, ETH_PHY_POWER);
// Static IP, leave without this line to get IP via DHCP
//bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0);
ETH.config(myIP, myGW, mySN, myDNS);
WT32_ETH01_waitForConnect();
// Client address
Serial.print("WebSockets Client started # IP address: ");
Serial.println(ETH.localIP());
// server address, port and URL
Serial.print("Connecting to WebSockets Server # IP address: ");
Serial.print(serverIP);
Serial.print(", port: ");
Serial.println(serverPort);
// setReconnectInterval to 10s, new from v2.5.1 to avoid flooding server. Default is 0.5s
socketIO.setReconnectInterval(10000);
socketIO.setExtraHeaders("Authorization: 1234567890");
// server address, port and URL
// void begin(IPAddress host, uint16_t port, String url = "/socket.io/?EIO=4", String protocol = "arduino");
// To use default EIO=4 fron v2.5.1
socketIO.begin(serverIP, serverPort);
// event handler
socketIO.onEvent(socketIOEvent);
}
unsigned long messageTimestamp = 0;
void loop()
{
socketIO.loop();
uint64_t now = millis();
if (now - messageTimestamp > 30000)
{
messageTimestamp = now;
// creat JSON message for Socket.IO (event)
DynamicJsonDocument doc(1024);
JsonArray array = doc.to<JsonArray>();
// add evnet name
// Hint: socket.on('event_name', ....
array.add("event_name");
// add payload (parameters) for the event
JsonObject param1 = array.createNestedObject();
param1["now"] = (uint32_t) now;
// JSON to String (serializion)
String output;
serializeJson(doc, output);
// Send event
socketIO.sendEVENT(output);
// Print JSON for debugging
Serial.println(output);
}
}
I am lost, ive used different socket.io verisions such as v1, v2, v3 and v4.
What I expect to happen is for it to have a stable connection, it connects but it disconnects after a short while.

RFID not reading any card

My RFID wont read any card. The Rfid card is on with red led at D1. I do not know what is the problem though. Below is my code. Please assist
The picture is connection between the rfid and esp8266
//*******************************libraries********************************
//RFID-----------------------------
#include <SPI.h>
#include <MFRC522.h>
//NodeMCU--------------------------
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
//************************************************************************
#define SS_PIN D2 //D2
#define RST_PIN D1 //D1
//************************************************************************
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
//************************************************************************
/* Set these to your desired credentials. */
const char *ssid = "***";
const char *password = "***";
const char* device_token = " 4876407e7cbc0c2b";
//************************************************************************
String URL = "http://192.168.0.110/rfidattendance/getdata.php"; //computer IP or the server domain
String getData, Link;
String OldCardID = "";
unsigned long previousMillis = 0;
//************************************************************************
void setup() {
delay(1000);
Serial.begin(115200);
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
//---------------------------------------------
connectToWiFi();
}
//************************************************************************
void loop() {
//check if there's a connection to Wi-Fi or not
if(!WiFi.isConnected()){
connectToWiFi(); //Retry to connect to Wi-Fi
}
//---------------------------------------------
if (millis() - previousMillis >= 15000) {
previousMillis = millis();
OldCardID="";
}
delay(50);
//---------------------------------------------
//look for new card
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;//got to start of loop if there is no card present
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;//if read card serial(0) returns 1, the uid struct contians the ID of the read card.
}
String CardID ="";
for (byte i = 0; i < mfrc522.uid.size; i++) {
CardID += mfrc522.uid.uidByte[i];
}
//---------------------------------------------
if( CardID == OldCardID ){
return;
}
else{
OldCardID = CardID;
}
//---------------------------------------------
// Serial.println(CardID);
SendCardID(CardID);
delay(1000);
}
//************send the Card UID to the website*************
void SendCardID( String Card_uid ){
Serial.println("Sending the Card ID");
if(WiFi.isConnected()){
HTTPClient http; //Declare object of class HTTPClient
//GET Data
getData = "?card_uid=" + String(Card_uid) + "&device_token=" + String(device_token); // Add the Card ID to the GET array in order to send it
//GET methode
Link = URL + getData;
// http.begin(Link); //initiate HTTP request //Specify content-type header
int httpCode = http.GET(); //Send the request
String payload = http.getString(); //Get the response payload
// Serial.println(Link); //Print HTTP return code
Serial.println(httpCode); //Print HTTP return code
Serial.println(Card_uid); //Print Card ID
Serial.println(payload); //Print request response payload
if (httpCode == 200) {
if (payload.substring(0, 5) == "login") {
String user_name = payload.substring(5);
// Serial.println(user_name);
}
else if (payload.substring(0, 6) == "logout") {
String user_name = payload.substring(6);
// Serial.println(user_name);
}
else if (payload == "succesful") {
}
else if (payload == "available") {
}
delay(100);
http.end(); //Close connection
}
}
}
//********************connect to the WiFi******************
void connectToWiFi(){
WiFi.mode(WIFI_OFF); //Prevents reconnection issue (taking too long to connect)
delay(1000);
WiFi.mode(WIFI_STA);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
delay(1000);
}
//=======================================================================
When I execute it, the rfid scanner is turn on but it does not read any card. I am using MFRC522, The wifi is connected successfully. I already pin the connection correctly

Not able to use GET method in WiFi initialization of program

I have a function to send logs to Telegram.
This function works fine, when I call it from void setup() or void loop() function or some function defined by me.
I would also like to get a message to Telegram, when my esp32 connects to Wifi.
This is how my code looks.
void telegram_report(String error_message) {
String url = "";
url += "https://api.telegram.org/bot";
url += TELEGRAM_TOKEN;
url += "/sendMessage?chat_id=";
url += TELEGRAM_CHAT_ID;
url += "&parse_mode=Markdown&text=";
url += "[ ESP32(1) ] ";
url += error_message;
HTTPClient http;
http.begin(url);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int countTries = 0;
int httpCode = -1;
while(httpCode == -1){
if (countTries > 3) {
Serial.println("[ ERR ] Could not send Error Report to Telegram. Max number of tries reached");
http.end();
Serial.println(error_message);
return;
}
httpCode = http.GET();
countTries++;
}
}
void connectToWiFi() {
Serial.println(" ");
Serial.print("[ INF ] Connencting to WiFi");
Serial.print(" ");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);
unsigned long startAttemptTime = millis();
while(WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 20000) {
Serial.print(".");
delay(500);
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("[ ERR ] Failed connect to WiFi!");
delay(5000);
}
else {
String connected = "";
connected += "[ SUCC ] Connected to WiFi:";
connected += String(WIFI_NETWORK);
connected += " - with IP address ";
connected += String(WiFi.localIP());
telegram_report(connected); // This is where I'm struggling
}
}
When I call the function telegram_report() somewhere from my code Im able to get a response to Telegram.
But I'm getting nothing when I try to call the function from Wifi connection function.
My Wifi connection is already established when I call the telegram_report(connected);.
Could it be that I'm passing String to function and not reference?
Also I'm getting weird output from String(WiFi.localIP()) when I try to print it. Is it because I'm converting it to the String?
The secure connection (https) requires to check validity of certificates. This includes checking of the dates. The ESP32 SDK retrieves internet time right after it connects to Internet, but it takes some milliseconds.
You can check if the time has been retrieved by comparing it to some timestamp larger than 1970-01-01 (which is the default 'unset' time).
time_t now = time(nullptr);
uint8_t timeoutCounter = 0;
while (now < SECS_YR_2000 && timeoutCounter < 10) {
timeoutCounter++
delay(100);
now = time(nullptr);
}
#define SECS_YR_2000 ((time_t)(946684800UL))

TfL API - no response for HTTP GET request (arduino/esp8266)

I am trying to display information from the TfL API using the ESP8266 WiFi module. To do this I modified the example provided (which was successfully receiving data) and modified the host and url. It compiles, but I am not getting a response to the request.
Using postman for the url gives no error code.
See the code below; thanks for any help
/*
* HTTP over TLS (HTTPS) example sketch
*
* This example demonstrates how to use
* WiFiClientSecure class to access HTTPS API.
* We fetch and display the status of
* esp8266/Arduino project continuous integration
* build.
*
* Created by Ivan Grokhotkov, 2015.
* This example is in public domain.
*/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>
const char* ssid = "VM*******";
const char* password = "v******";
const char* host = "api.tfl.gov.uk";
const int httpsPort = 80;
// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";
void setup() {
Serial.begin(115200);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Use WiFiClientSecure class to create TLS connection
WiFiClient client;
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
//https fingerprint verification
//if (client.verify(fingerprint, host)) {
// Serial.println("certificate matches");
//} else {
// Serial.println("certificate doesn't match");
//}
String url = "/StopPoint/940GZZLUODS/Arrivals?mode=tube";
Serial.print("requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
StaticJsonBuffer<200> jsonBuffer;
while (client.connected()) {
String line = client.readString();
Serial.println("processing response...");
if (line == "\r") {
Serial.println("headers received");
break;
}
}
String line = client.readString();
Serial.println("processing response...");
JsonObject& root = jsonBuffer.parseObject(line);
Serial.print(line);
if (line.startsWith("{\"state\":\"success\"")) {
Serial.println("esp8266/Arduino CI successfull!");
} else {
Serial.println("esp8266/Arduino CI has failed");
}
const char* lineID = root["lineID"];
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.print(lineID);
Serial.println("==========");
Serial.println("closing connection");
}
void loop() {
}

UDP server and multiple clients (1v1 game)

I'm trying to create an UDP server with two slots per new instance of the game and clients.
It has to be UDP cause of the game mechanics. I wrote this:
public class Server {
private static HashSet<Integer> ports = new HashSet<Integer>(); // these are player's IDs
static ArrayList<InetAddress> addresses = new ArrayList<InetAddress>();
public static boolean player1_active = false, player2_active = false;
public static PlayerCredits p1, p2, temp;
public static void main(String[] args) throws Exception {
// The default port
int serverport = 8888;
DatagramSocket udpServerSocket = new DatagramSocket(serverport);
DatagramPacket sendpacket;
System.out.println("Server started...\n");
while(true)
{
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
udpServerSocket.receive(receivePacket);
String clientMessage = (new String(receivePacket.getData())).trim();
System.out.println("Client Connected - Socket Address: " + receivePacket.getSocketAddress());
System.out.println("Client message: \"" + clientMessage + "\"");
InetAddress clientIP = receivePacket.getAddress();
addresses.add(clientIP);
System.out.println("Client IP Address & Hostname: " + clientIP + ", " + clientIP.getHostName() + "\n");
// Get the port number which the recieved connection came from
int clientport = receivePacket.getPort();
System.out.println("Adding "+clientport);
ports.add(clientport);
// Response message
String returnMessage = clientMessage.toUpperCase();
System.out.println(returnMessage);
// Create an empty buffer/array of bytes to send back
byte[] sendData = new byte[1024];
temp = new PlayerCredits(clientport, clientIP);
if(!player1_active){
p1 = new PlayerCredits(clientport, clientIP);
player1_active = true;
}
if(temp.port != p1.port && temp.ad != p1.ad)
if(!player2_active){
p2 = new PlayerCredits(clientport, clientIP);
player2_active = true;
}
DatagramPacket sendPacket;
if(p2 == null){
String awaiting = "WAITING FOR SECOND PLAYER";
sendData = awaiting.getBytes();
sendPacket= new DatagramPacket(sendData, sendData.length, p1.ad, p1.port);
udpServerSocket.send(sendPacket);
}
else{
String awaiting = "SECOND PLAYER INCOMING";
sendData = awaiting.getBytes();
if(p2!=null){
sendPacket = new DatagramPacket(sendData, sendData.length, p2.ad, p2.port);
udpServerSocket.send(sendPacket);
}
sendPacket = new DatagramPacket(sendData, sendData.length, p1.ad, p1.port);
udpServerSocket.send(sendPacket);
}
}
}
public static class PlayerCredits{
int port;
InetAddress ad;
public PlayerCredits(int p, InetAddress a){
this.port = p;
this.ad = a;
}
}
For now I have two people connected - but as you will probably say - it's WRONG. I need to somehow implement every player on the Multisocket or something (or connect them via TCP and then listen on a new thread with a new datagram).
As I know, the best way is to create a listener server (TCP) on a main thread - accept connections and pass them to 'Player's constructors' and in Player's class make the whole fun.
If there is someone that could help and tell me, how it should be done like in 3 steps like (I don't need code):
Connection with TCP
Create new threads with players and listen on UDP
Start the game when 2 players are connected
Also, how to stop the 'third connection' and redirect it to a new game instance? (cause it's 1v1).

Resources