I am trying to make an arduino weather alert, from this website
and I need to find the contents of the quotation marks in "weather" after "main". I have looked for a text finder, but the one on the arduino website but it's so undescriptive that it might as well not exist.
Currently my code looks like this:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "api.openweathermap.org";
IPAddress ip(192,168,1,77);
EthernetClient client;
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
Ethernet.begin(mac, ip);
}
delay(1000);
if (client.connect(server, 80)) {
client.println("GET /data/2.5/weather?q=Melbourne,au HTTP/1.1");
client.println("Host: api.openweathermap.org");
client.println("Connection: close");
client.println();
}
else {
}
}
void loop()
{
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
client.stop();
while(true);
}
}
and it returns:
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 07 Jun 2015 21:17:44 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: close
X-Source: redis
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST
1d2
{"coord":{"lon":144.96,"lat":-37.81},"sys":{"message":0.0117,"country":"AU","sunrise":1433626204,"sunset":1433660872},"weather":[{"id":800,"main":"Clear","description":"Sky is Clear","icon":"01n"}],"base":"stations","main":{"temp":284.532,"temp_min":284.532,"temp_max":284.532,"pressure":1011.27,"sea_level":1030.68,"grnd_level":1011.27,"humidity":80},"wind":{"speed":4.43,"deg":331.501},"clouds":{"all":0},"dt":1433711139,"id":2158177,"name":"Melbourne","cod":200}
0
for this output I want it to say: Clear
A very easy way to get the data you want is with TextFinder from the Arduino playground. I believe this should work. Note that I haven't tested it, so fingers crossed.
Add this at the begining
#include <TextFinder.h>
#include <String.h>
String result = "";
TextFinder finder( client );
Then modify your loop() to this
if (client.connected()){
finder.find("\"weather\"");
finder.find("\"main\":\"");
char c = client.read();
while(c != '\"'){
result += c;
c = client.read();
}
Serial.print(result);
}
if (!client.connected()) {
Serial.println();
client.stop();
while(true);
}
More info below if you're interested.
The response you're getting is json, to properly interpret it you need a json parser. I found a library on github: ArduinoJson that parses json on the arduino. It seems quite easy to use too. If you need help with it, you can browse it's wiki
Before you start parson the json, you need to first strip the header from the response. To do that you could keep reading the characters until you get a double CRLF (\r\n\r\n)
Related
I have a uvicorn fastapi server that runs a file on port 8000 at address "example.com/sub/subsub" that returns either a 0 or a 1.
I also have an arduino running that tries to connect to this url and work with this binary value. I can't figure out why my code isn't working. The arduino keeps printing '0' to indicate that the client is not available, while my server keeps printing "Invalid HTTP request received". Can anyone help me as to what goes wrong here?
#include <SPI.h>
#include <Ethernet.h>
#include <HttpClient.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,y);
byte serverIP[] = {x, x, x, x};
EthernetClient client;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, ip);
delay(1000);
int res = client.connect(serverIP,8000);
Serial.println(res);
}
void loop(){
if (client.connected() == true) {
Serial.println("connected:)");
client.println("GET /sub/subsub HTTP/1.0");
if (client.available()) {
char c = client.read();
Serial.println(c);
} else {
Serial.println(client.available());
}
} else {
Serial.println("connection failed in loop: diconnecting...");
client.stop();
delay(1000);
client.connect(serverIP,8000);
}
delay(5000);
}
I have copied from several places portions of code and wrote this program that should connect to a server which I'm 100% sure is working, the IP address and the port are right, however client.connect(server, 8000) returns false, I'm new to networking so it's probably because of something basic
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte server[] = { 192, 168, 1, 100 };
IPAddress ip(192,168,1,127);
EthernetClient client;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, ip);
Serial.print("client is at ");
Serial.println(Ethernet.localIP());
if (client.connect(server, 8000)) { //false returned here, of course then it doesn't work
Serial.println("connected");
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
} else {
Serial.println("connection failed");
}
}
void loop() {
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;;)
;
}
client.stop();
}
After making it work I forgot about having asked it here, but here's how I made it work, no idea of what was wrong before.
Of course be sure to turn off the firewall, so, for debian based systems:
sudo ufw disable
sudo ufw reload
Then I messed up with the code until I managed to do a POST request, I know I've asked for a GET, but the error mentioned in the question is now gone (I've notice the port changed, but that's because I've changed it on the server as well):
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(192,168,1,100);
IPAddress ip(192,168,1,104);
IPAddress gateway(192,168,1,1);
IPAddress DNSServer(192,168,1,1);
IPAddress subnet(255, 255, 255, 0);
EthernetClient client;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, ip, gateway, DNSServer, subnet);
delay(5000);
Serial.println("connecting...");
}
void loop()
{
int correctValue;
String PostData = "foo";
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
if (client.connect(server, 5000)) {
Serial.println("connected");
client.println("POST / HTTP/1.1");
// Works either with or without any of the commented lines
// guess it's a great idea to un-comment them though
//client.println("Host: 192.168.1.100");
//client.println("User-Agent: Arduino/1.0");
//client.println("Connection: close");
client.print("Content-Length: ");
client.println(PostData.length());
client.println();
client.println(PostData);
client.println();
}
else {
Serial.println("connection failed");
}
delay(10000);
}
}
If you wanted to do a GET, it SHOULD be enough to change
client.println("POST / HTTP/1.1");
with
client.println("GET / HTTP/1.1");
then remove all the client.println(), the block with
if (client.available()) {
char c = client.read();
Serial.print(c);
}
should print it, since I'm not sure about it and can't confirm it I'll be more than happy to update the code if someone finds out the right way to do this
I have a little problem with function GET function of HTTP. The program reads ID number, and after enter(new line), it should get data from REST API. Problem is that I have to press enter twice for data from API. Here is code
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x90, 0x02, 0xBA, 0xEF, 0xCA, 0x33 };
char server[] = "xxx.xx";
EthernetClient client;
char tmp;
char buffer[30];
int bufferCounter = 0;
void setup() {
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
}
delay(1000);
Serial.println("Ready");
}
void getData(char* num ){
Serial.println("connecting...");
if (client.connect(server, 80)) {
Serial.println("connected");
client.print("GET /api/id/");
client.print(num);
client.println("/?format=json HTTP/1.1");
client.println("Host: xxx.xx");
client.println("Authorization: Token xxxxxxxxxxxxxxxxxxxxx");
client.println("Connection: close");
client.println();
} else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
while (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
}
void loop() {
if (Serial.available() > 0) {
tmp = Serial.read();
if(tmp == '\n'){
buffer[bufferCounter] = 0;
bufferCounter = 0;
Serial.println(buffer);
getData(buffer);
}
else{
buffer[bufferCounter] = tmp;
bufferCounter++;
}
}
}
On the serial link I get this message. At first
Ready
when I write there 35 and press enter I get this
35
connecting...
connected
then I have to press enter again, and finally I get the correct data but with connection failed and I dont know why
connecting...
connection failed
HTTP/1.1 404 NOT FOUND
Date: Tue, 22 Nov 2016 16:18:18 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: close
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Vary: Accept, Cookie
18
{"detail":"not found."}
0
disconnecting.
Could someone help me, where is the problem? Thank you.
I am testing the wifi module esp8266 with my arduino uno.
I made it work with direct connection RX/TX and through softwareserial.
This is my code:
#include <SoftwareSerial.h>
SoftwareSerial esp8266(3, 2); // RX | TX
#define DEBUG true
int ERROR_PIN = 7;
int OK_PIN = 6;
char serialbuffer[400];//serial buffer for request url
const String ssid = "XXX";
const String pw = "XXX";
int state = 0;
void setup()
{
delay(1000);
/**
// init leds
pinMode(ERROR_PIN, OUTPUT);
pinMode(OK_PIN, OUTPUT);
state = 0;
digitalWrite(ERROR_PIN, HIGH);
digitalWrite(OK_PIN, LOW);
/**/
// init ports
Serial.begin(19200);
Serial.println("initializing esp8266 port...");
esp8266.begin(19200);
delay(400);
// init WIFI
/**/
while(!esp8266.available())
{
Serial.print("...");
delay(300);
}
Serial.println();
Serial.println("FINISH esp8266 initializing!");
//
/**
digitalWrite(ERROR_PIN, LOW);
digitalWrite(OK_PIN, HIGH);
state = 1;
/**/
/**/
// Setup connection
sendData("AT+RST\r\n",2000,DEBUG);
sendData("AT+CWMODE?\r\n",1000,DEBUG);
//sendData("AT+CWMODE=1\r\n",2000,DEBUG);
//sendData("AT+RST\r\n",3000,DEBUG);
//sendData("AT+CWLAP\r\n",6000,DEBUG);
sendData("AT+CWJAP=\"" + ssid + "\",\""+ pw +"\"\r\n",12000,DEBUG);
sendData("AT+CIFSR\r\n",8000,DEBUG);
sendData("AT+CIPMUX=1\r\n", 6000, DEBUG);
webRequest("");
/**/
/**/
}
void loop()
{
if (esp8266.available())
{
char c = esp8266.read() ;
Serial.print(c);
/**
if(state == 0)
{
state = 1;
digitalWrite(ERROR_PIN, LOW);
digitalWrite(OK_PIN, HIGH);
}
/**/
}
else
{
/**
if(state > 0)
{
state = 0;
digitalWrite(ERROR_PIN, HIGH);
digitalWrite(OK_PIN, LOW);
}
/**/
}
if (Serial.available())
{
char c = Serial.read();
esp8266.print(c);
}
}
//////////////////////////////////////////////////////////////////////////////
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
esp8266.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(esp8266.available())
{
// The esp has data so display its output to the serial window
char c = esp8266.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.print(response);
}
return response;
}
//////////////////////////////////////////////////////////////////////////////////
String webRequest(String url)
{
String response = "";
url = "www.google.es";
//String tmpCommand = "AT+CIPSTART=4," + "\"TCP\",\"" + url + "\",80";
String tmpSTARTCommmand = "AT+CIPSTART=0,\"TCP\",\"retro.hackaday.com\",80\r\n\r\n";
String tmpGETCommand = "GET / HTTP/1.1\r\nHost: ";
tmpGETCommand += "retro.hackaday.com";
tmpGETCommand += ":80\r\n\r\n";
String tmpSENDCommand = "AT+CIPSEND=0," + String(tmpGETCommand.length()) + "\r\n";
sendData(tmpSTARTCommmand, 8000, DEBUG);
sendData(tmpSENDCommand, 8000, DEBUG);
sendData(tmpGETCommand, 15000, DEBUG);
}
This works until the point where I do the webrequest. I receive a Bad request response.
initializing esp8266 port...
.........
FINISH esp8266 initializing!
BâÂúØÐPÊþ^X8Â�Ä^Âú[8ÐûÈâ·CâËØè[8Ð{Èâ·GâÃØRÈ蚉5˜‰0
bÕ
ready
AT+CWMODE?
+CWMODE:3
OK
AV®)AB•«Ë—mX·et","XXX"
OK
AT+CIFSR
+CIFSR:APIP,"192.168.4.1"
+CIFSR:APMAC,"1a:fe:34:9b:c3:83"
+CIFSR:STAIP,"192.168.1.89"
+CIFSR:STAMAC,"18:fe:34:9b:c3:83"
OK
AT+CIPMUX=1
OK
AV%AMEÕÕ*$‘²troÐ…�‘½µ‰,80
0,CONNECT
OK
AVCIPSEND=0,47
> GE#/!QQAŠrŠ%åõÑ: ÊÑɽB�……¹½µÂ‚%\n\r\nbusy s...
SEND OK
+IPD,0,323:HTTP/1.1 400 Bad Request
Server: nginx/1.6.2
Date: Sat, 04 Apr 2015 16:17:29 GMT
Content-Type: text/html
Content-Length: 172
Connection: close
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.6.2</center>
</body>
</html>
OK
"qXÑzÂC!É1âø‚h[•�™cü ÐQ!}Ñfócú I]Ø÷ÃBj 1¤(ÑÃÖa”K!~CóbÕ
ready
Any idea?
I secceded using this code:
https://github.com/itead/ITEADLIB_Arduino_WeeESP8266/blob/master/ESP8266.cpp
but I have mega2560..
hardware connection:
https://github.com/McOffsky/Arduino_ESP8266_HTTP_Client
Check if it works perfectly, if you use Hardware serial Rx(pin0), Tx(pin1) and Serial monitor, ESP8266 responds properly.
Try lowering baud rate. Most the time SoftwareSerial and
Arduino Uno are not able to handle fast response and loose bit of
information.
If you still receiving the garbage response most likely you module have got damaged.
You shouldn't include port number in get command. Port already specified at cipstart.Something wrong in your http request text. Everything else (sending request and getting response )is ok.
http://en.m.wikipedia.org/wiki/Hypertext_Transfer_Protocol
Check your power supply. I have had these random characters showed up every once in a while when I simply connected the module directly to the Arduino power pins. Those seems like the module is resetting itself constantly and spits out the module info.
My solution was to connect another 3.3v regulator in parallel with Arduino. Connect the grounds together, and supply ESP8266 from that 3.3v power source. Problem solved.
I'm trying to connect my Arduino uno + Ethernet shield to a php script that gets a value from a database and then is sent back which then is displayed on a serial monitor. It works, it connects successfully and i get the value sent back however I'm having trouble displaying it on the serial monitor. It should just display what the server sends however it doesn't. Any one can help?
The Serial Output : It should just output "The Value", however there are numbers that shouldn't be there. If i output this to a LCD monitor i can't have them numbers present.
connecting...
connected
HTTP/1.1 200 OK
Server: cloudflare-nginx
Date: Sat, 04 Jan 2014 15:36:51 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
Set-Cookie: __cfduid=dcef101052b82760c1a2de019e6b076141388849811461; expires=Mon, 23-Dec-2019 23:50:00 GMT; path=/; domain=.linku.biz; HttpOnly
X-Powered-By: PHP/5.3.27
CF-RAY: e7901b6dec606e2
4
The
5
Value
0
disconnecting.
PHP Script
<?php
echo 'The Value';
?>
Arduino Script
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "www.linku.biz"; // name address for Google (using DNS)
// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192,168,0,177);
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("GET /arduino.php HTTP/1.1");
client.println("Host: www.linku.biz");
client.println("Connection: close");
client.println();
}
else {
// kf you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
while(true);
}
}
Don't know if this helps, but notice that the numbers are the count of available chars which are read out. 4 "The " and 5 "value"
I would expect that client.available returns the 4 and 5 values just after those chars are received. How they got converted to ASCI "4" and "5" and printed, I have no idea.
I parse data by this code
String readString;
//gets byte from ethernet buffer
readString += client.read(); //places captured byte in
//parse readString for request
index = readString.indexOf("text"); //finds location of first "text"
data_want = readString.substring(index+some char, index+some char); //captures data String
Serial.println(data_wand);