Im working on a project with an Arduino and Ethernet Shield.
I would like to execute a php script (residing on my server) in the loop.
#include <SPI.h>
#include <Ethernet.h>
// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,77); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
String HTTP_req; // stores the HTTP request
void setup()
{
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
Serial.begin(9600); // for diagnostics
}
void loop()
{
EthernetClient client = server.available(); // try to get client
if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
HTTP_req += c; // save the HTTP request 1 char at a time
Serial.print("connected");
client.println("GET http://domain.com/arduino/scripts/script_motion_detection_driveway.php HTTP/1.0");
client.println();
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
When I run the code and load the page, instead of executing the script it just prints the line:
GET http://domain.com/arduino/scripts/script_motion_detection_driveway.php HTTP/1.0
over and over again...
The reason its in the loop as opposed to setup is because eventually the GET request will be placed inside an if statement to test a condition.
What do I need to change to execute the script?
You should check this example: http://www.arduino.cc/en/Tutorial/WebClient
You want to execute a GET request without telling the client to connect to the server at the port 80.
if (client.connect(server, 80)) {
Then you make your http request
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println("Connection: close");
client.println();
Then you try to read the request
if (client.available()) {
char c = client.read();
Serial.print(c);
}
By putting these parts together in a better way than your script above, you will successfully get the output of your php script.
Related
I've been tinkering with the MFRC-522 (RC-522) RFID module for a project.
I'm testing authentication using an old key to check if the RFID's key A for a sector (in my case, Sector 2) is different from the original, if it was, then I would continue, if not I would like to "register" the card by changing the key.
I was caught at the beginning on checking different keys authentication, if I tested a working key and then an incorrect key, it works as expected, but if I test with the incorrect key first, it doesn't allow even the correct key to authenticate.
If I ran the code below everything in serial is
PCD_Authenticate() failed NEW(read): Timeout in communication.
PCD_Authenticate() failed OLD(read): Timeout in communication.
repeatedly but if I flipped old() and neww() I get
OLD WORKS
PCD_Authenticate() failed NEW(read): Timeout in communication.
Why does it work as such?
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 22 // Configurable, see typical pin layout above
#define SS_PIN 21 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
MFRC522::MIFARE_Key old_key = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
MFRC522::MIFARE_Key new_key = {0x23,0x54,0x64,0x3a,0x32,0x66};
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
delay(4); // Optional delay. Some board do need more time after init to be ready, see Readme
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}
void loop() {
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
neww();
old();
}
void old(){
//authentication of the desired block for access
byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &old_key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed OLD(read): ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status));
return;
}else {Serial.println("OLD WORKS");}
//delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
void neww() {
//authentication of the desired block for access
byte status_new = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &new_key, &(mfrc522.uid));
if (status_new != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed NEW(read): ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status_new));
return;
} else {Serial.println("NEW WORKS");}
//delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}
So, after reading the datasheet extra hard I came to the conclusion that the state of the card was not ready for the next read, so I came with a fire-all-guns solution that helped my case, The Serial prints are for debugging so if using the code feel free to comment them out.
bool reselect_Card() {
//-------------------------------------------------------
// Can also be used to see if card still available,
// true means it is false means card isnt there anymore
//-------------------------------------------------------
byte s;
byte req_buff[2];
byte req_buff_size=2;
mfrc522.PCD_StopCrypto1();
s = mfrc522.PICC_HaltA();
Serial.print("Halt Status: ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
delay(100);
s = mfrc522.PICC_WakeupA(req_buff,&req_buff_size);
Serial.print("Request: ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
Serial.print("ATQA : ");
Serial.println(dump_byte_array_to_string(req_buff,req_buff_size));
delay(100);
s = mfrc522.PICC_Select( &(mfrc522.uid),0);
Serial.print("Selected : ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
if( mfrc522.GetStatusCodeName((MFRC522::StatusCode)s) == F("Timeout in communication.") ) { return false;}
return true;
}
I am struggling to get ESP8266 connected to an Arduino Uno working reliably as a webserver. The firmware of my ESP8266 is 1.1.1 - I don't have the option (or knowledge) to update it at the moment. Below is my code. It works, barely, if I serve a small string. However, it usually closes the connection or just loads forever (crashes?) if I try to load the page from the browser three or four times. Ultimately I need to serve a webpage with json embedded in it that will load a second page served by the esp8266, a json file. I have a working demo of that but it crashes after a few retrievals. I understand that my html page is too long for strings so have been attempting to shift across to PROGMEM, initially testing with just a short string. I am storing and retrieving that correctly (I think, at least I can Serial.print it) but as soon as I try to write it to the ESP8266 I get a never ending load in my browser.
Where am I going wrong here? Is it the string/PROGMEM that is causing the issues or is there something else I'm missing in the AT commands (like some sort of ping to keep the connection open)?
//load softserial library
#include <SoftwareSerial.h>
#include <avr/pgmspace.h>
//set a boolean constant variable to true
//#define DEBUG true
const boolean DEBUG = true;
//RX (pin 2) goes to TX on esp8266, TX (pin 3) goes to RX on esp8266
SoftwareSerial esp8266(2, 3);
//input from the photoresistor
//int photoresistorpin = 0;
//create a PROGMEM variable
//String WEBPAGE = "hello";
static const char PROGMEM WEBPAGE[] = {"hello"};
/*
static const char WEBPAGE[] PROGMEM = R"rawliteral(
<html>
<head>
<meta name="viewport" content="width=device-width, minimumscale=1, maximum-scale=1, initial-scale=1">
</head>
<h1>Light:</h1><div id="light"></div>
<script>
function loadDoc()
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
{
var obj = JSON.parse(this.responseText);
document.getElementById('light').innerHTML = obj.data[0].datavalue;
}
};
xhttp.open('GET', 'data.json', true); xhttp.send();
}
var timedEvent = setInterval(function() { loadDoc(); }, 5000);
</script>
</body>
</html>
)rawliteral";
*/
//const int WEBPAGE_len = sizeof(WEBPAGE)/sizeof(WEBPAGE[0]);
void setup()
{
//open the serial port
Serial.begin(115200);
//print setup started in the serial monitor
Serial.println("Setup started");
//start esp8266 module (note: your esp's baud rate might be different)
esp8266.begin(115200);
//reset esp8266 module
senddata("AT+RST\r\n", 2000, DEBUG);
//set esp8266 as access point mode
//1 = Station mode (client)
//2 = Access point mode (host)
//3 = Access point mode + Station mode
senddata("AT+CWMODE=2\r\n", 1000, DEBUG);
//get ip address for esp8266
senddata("AT+CIFSR\r\n", 2000, DEBUG);
//configure esp8266 for multiple connections
senddata("AT+CIPMUX=1\r\n", 1000, DEBUG);
//turn on esp8266 server on port 80
senddata("AT+CIPSERVER=1,80\r\n", 1000, DEBUG);
//setup completed
Serial.println("Setup done");
}
void loop()
{
//take a reading from the photoresistor
//int lightval = analogRead(photoresistorpin);
int lightval = random(1000);
//to test
//Serial.println(lightval);
//is the esp8266 sending a message
if (esp8266.available())
{
//if received data from esp8266
if (esp8266.find("+IPD,"))
{
//subtract 48 because the read() function returns the ASCII decimal
//value and 0 (the first decimal number) starts at 48
int connectionid = esp8266.read() - 48;
//Serial.println("");
//Serial.println("*****");
//Serial.print("string = ");
//read the url sent by the client, look for the variable (/)
String msg;
esp8266.find("/");
delay(100);
msg = esp8266.readStringUntil(' ');
String pathrequested = msg.substring(0);
Serial.println("*****");
Serial.println(pathrequested);
Serial.println("*****");
//create a senddata string to send the webpage to the esp8266
String cipsend = "AT+CIPSEND=" + String(connectionid) + ",";
//cipsend += WEBPAGE.length();
cipsend += strlen_P(WEBPAGE);
cipsend += "\r\n";
Serial.println(cipsend);
char buffer[1000];
strcpy_P(buffer, WEBPAGE);
Serial.println(buffer);
//senddata(cipsend, 500, DEBUG);
//senddata(WEBPAGE, 500, DEBUG);
senddata(buffer, 500, DEBUG);
//create a string closecommand with the connection id and send it
String closecommand = "AT+CIPCLOSE=" + String(connectionid) + "\r\n";
senddata(closecommand, 500, DEBUG);
//increment the count
//count++;
}
}
}
void senddata(String command, const int timeout, boolean debug)
{
//send the received command to the esp8266
esp8266.print(command);
//set int variable to the number of millisends since Arduino began
long int time = millis();
//while the time and the timeout is less than the number of millisends since Arduino began
while((time + timeout) > millis())
{
//while the esp8266 is sending messages
while(esp8266.available())
{
//display output in the serial window
Serial.write(esp8266.read());
}
}
}
Assuming that "get a never ending load in my browser" means no display in the browser - check the following:
1. Get rid of String amd String constructors (+=) in your code and replace it with a fixed char array for the building of messages. Read more: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/
2. My experience with the AT interface was - more than 9600 baud is not reliable and this is not sufficient for doing what you want.
3. If your Esp module has min 512kb (most likely up to 4Mb) host your code there and use the UNO only as sigmal receiver/sender from the attached hardware/ sensors. Save yourself a lot of trouble and problems - most of the examples with AT com are not really working and more of a pain in the ***. I ditched the AT interface within 2 days and never in the last 4 years missed anything. By flashing code to the Esp module you also have full control and visibility on whats going on due to the debug possiblitie AND you can even host html/css/js on the File system there (LittleFS / SPIFFS)
I have been trying to establish connection between two HC-06 Bluetooth modules. Pairing has been done. The two modules are communicating. My aim is to send a letter from one module and receive acknowledgment from the other module. The code for the master module is below.
#include <SoftwareSerial.h>
SoftwareSerial BTserial(2,3); // RX, TX
char c;
char s[]="Matched";
int t[]="NotMatched";
void setup()
{
// start the serial communication with the computer
Serial.begin(9600);
Serial.println("Arduino with HC-06 is ready");
// start communication with the HC-06 using 38400
BTserial.begin(38400);
Serial.println("Bluetooth serial started at 38400");
}
void loop()
{
// Read from HC-06 and send to Arduino Serial Monitor
if (BTserial.available())
{
c=(BTserial.read());
if (c=='a')
{
Serial.write(s);
}
else
{
Serial.write(t);
}
}
// Read from Arduino Serial Monitor and send to HC-06
if (Serial.available())
{
c = Serial.read();
Serial.write(c);
BTserial.write(c);
}
}
Similar code is used for the slave module. Except for the 'else' part in the code everything runs right. I receive acknowledgement along with the else portion being printed twice for both the if and else portion of the code i.e 'matched not matched not matched' is printed when it receives char 'a' and 'not matched not matched not matched' is printed when it receives anything other than 'a' . Can you please give me suggestions on what could be wrong.
Have you printed the characters that you are reading?
I had a similar problem and I found that the Bluetooth was receiving garbage characters. The reason was because the standard baudrate, of HC-06 modules, is 9600, so if you change:
BTserial.begin(38400);
to
BTserial.begin(9600);
In both master and slave, it might work.
Having a weird problem with an UWP app I'm trying to create when creating a socket and reading back data from it. Here's the basic scenario:
_commandSocket = new StreamSocket();
await _commandSocket.ConnectAsync(new HostName("192.168.1.1"), "15740", SocketProtectionLevel.PlainSocket);
_commandOutput = _commandSocket.OutputStream;
_commandInput = _commandSocket.InputStream;
await _commandOutput.WriteAsync(initCommandBuffer);
var lengthBytes = new byte[4].AsBuffer();
await input.ReadAsync(lengthBytes, 4, InputStreamOptions.None);
etc..etc...etc...
I'm basically opening a socket and sending an initialization command to my device. The idea is that it'll reply by first sending me the length of the reply as an uint.
This all works perfectly well when I debug/run the app on my desktop, but if I try to run this on my Window 10 Mobile device (Nokia 930) it seems not a single byte is being read (I've tried reading 1 byte instead of 4). Since app development should be 'Universal' and it's all working perfectly on my desktop I have no idea where to start fixing this.
Opening the connection on the mobile device works, I'm also not getting any errors when sending the initialization command, it just keeps blocking on the await ReadAsync command (as if nothing is being sent back).
I don't have any influence on the device that I'm connecting to, but again since this is all working flawlessly on the desktop and the device doesn't know who's asking I'm pretty clueless.
Cannot confirm my answer for sure, becasue I only tested in on an emulator, but I used stream socket listener.
private async void StartServer()
{
int Port = 80;
try
{
//Bound to port 80
await listener.BindServiceNameAsync(Port.ToString());
}
catch (System.Runtime.InteropServices.COMException)
{
//Port 80 for communication is blocked.
}
listener.ConnectionReceived += async (s, e) =>
{
using (IInputStream input = e.Socket.InputStream)
{
var buffer = new Windows.Storage.Streams.Buffer(200);
await input.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial);
//reads incoming stream
string data = Encoding.ASCII.GetString(buffer.ToArray(), 0, (int) buffer.Length);
}
using (IOutputStream output = e.Socket.OutputStream)
{
using (Stream response = output.AsStreamForWrite())
{
response.Write(Encoding.ASCII.GetBytes("Response."), 0, 1);
}
}
};
}
I'm trying to make a small WiFi control board with the use of an ESP8266 ESP-201 board.
I used the example provided for WebSocket for Arduino, with a little bit of modification to be able to handle JSON messages. This is the code I got to:
/*
* WebSocketClient.ino
*
* Created on: 24.05.2015
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>
#include <Hash.h>
ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial
ArduinoJson::StaticJsonBuffer<200> jsonBuffer;
void webSocketEvent(WStype_t type, uint8_t * payload, size_t lenght) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[WSc] Disconnected!\n");
break;
case WStype_CONNECTED: {
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
// send message to server when Connected
}
break;
case WStype_TEXT: {
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
String text = String((char *) &payload[0]);
USE_SERIAL.println(text);
JsonObject& root = jsonBuffer.parseObject(text);
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", root["r"]);
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", root["g"]);
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", root["b"]);
}
// send message to server
break;
case WStype_BIN:
USE_SERIAL.printf("[WSc] get binary lenght: %u\n", lenght);
hexdump(payload, lenght);
// send data to server
break;
}
}
void setup() {
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
WiFiMulti.addAP("GamersHeavenLow", "nCore4Life");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
webSocket.begin("192.168.0.104", 3000);
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}
And this is the server side I used to:
var express = require('express');
var app = express();
var url = require('url');
var http = require('http').Server(app);
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: http });
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.use(express.static('public'));
wss.on('error', function(error) {
console.log(error);
});
wss.on('connection', function connection(ws) {
var location = url.parse(ws.upgradeReq.url, true);
// you might use location.query.access_token to authenticate or share sessions
// or ws.upgradeReq.headers.cookie (see http://stackoverflow.com/a/16395220/151312)
console.log('connected');
ws.on('message', function incoming(message) {
console.log(message);
wss.clients.forEach(function each(client) {
client.send(JSON.stringify(message));
});
});
//ws.send('something');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Before I started to work with the JSON encoding it was working for a while, but now it's not. I get the following error:
[SETUP] BOOT WAIT 4...
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 2
cnt
connected with GamersHeavenLow, channel 6
dhcp client start...
ip:192.168.0.101,mask:255.255.255.0,gw:192.168.0.1
[SETUP] BOOT WAIT 3...
[SETUP] BOOT WAIT 2...
[SETUP] BOOT WAIT 1...
[WS-Client] connect ws...
[WS-Client] connection to 192.168.0.104:3000 Faild
[WS-Client] client disconnected.
[WSc] Disconnected!
[WS-Client] connect ws...
[WS-Client] connection to 192.168.0.104:3000 Faild
[WS-Client] client disconnected.
[WSc] Disconnected!
I believed it must have been the JSON decoding, so I reverted back to the default example, but I still get the same message, connection failed.
So I tried to use the echo websocket server, with which the Arduino code started working.
So I figured out it must be a server side issue, so I tested my node.js websocket server with a pure WebSocket client, but that is also working without a problem.
So basically I have two separate sets of code, which are running in isolation from one another without a problem, but they don't want to play along together.
Any idea what might be causing this?
WebSocket server used: https://github.com/websockets/ws
WebSocket client used on ardruino: https://github.com/Links2004/arduinoWebSockets
You need to use the WS module instead of the socket.io.