Read from url

I have a device connected to my smart meter. When I send the command "http://192.168.1.3/e"
to this device I get back the JSON string:

"[{"tm":1527435280,"net": 6376.438,"pwr": 137,"p1": 3312.498,"p2": 3063.940,"n1": 0.000,"n2": 0.000,"gas": 1236.181,"gts":1805271700}]"

I wont to use the Ethernet shield to read the data.
How should I read this with the Arduino (code) have tried several approaches but without any result.

Thanks for any help.

how do you send the command "http://192.168.1.3/e" ?
have a look at the Ethernet library

Thanks for the replay.
How to send I have no clou.
This is what I found in the library example, but don't no how to fill in this call "http://192.168.1.3/e"
in the code below. Please can you help me out.

Thanks for any help.

Jan

// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
// 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();
} else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}

No major response to this problem?

what device/software did you use to get the information

PowerSoft:
I have a device connected to my smart meter. When I send the command "http://192.168.1.3/e"
to this device I get back the JSON string:

"[{"tm":1527435280,"net": 6376.438,"pwr": 137,"p1": 3312.498,"p2": 3063.940,"n1": 0.000,"n2": 0.000,"gas": 1236.181,"gts":1805271700}]"

what device/software did you use to get the JSON information

Thanks for the response.
I can read my device (Youless ls 120), witch is connect to my network. I read it out with an ESP32 and display the power value to a SSD1306.
It works great. See the code
The onley thing I need is to change the code to use the Ethernet Shield, but what I try no succes.
So I include my code!

Thanks again for any help.

/*
 * Read the contence of the Youless
 * Samples are taken every 10 seconds to update the real value
 * Archive values can taken at the beginning of the start of
 * the program (Todo).
 */

#include <ArduinoJson.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include "SSD1306.h"
#include "Dialog_plain_48.h"

SSD1306Wire  display(0x3d, 21, 22);

int pwr=0; //actual power Youless (global)

const char* ssid = "**********";   //Network name
const char* password = "**********"; //pasword for network

long previousMillis = 0;    // will store last time
long interval = 10000;      // 10 second interval 

void setup () {
  Serial.begin(115200);
  resetSSD1306(0x04); //resetpin is 0x04 for ESP32
  display.init();
  display.flipScreenVertically();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("Connecting..");
  }
}
 
void loop() {
  /*
   * [{"tm":1519654622,"net": 6091.867,"pwr": 159,"p1": 3175.239,"p2": 2916.628,"n1": 0.000,"n2": 0.000,"gas": 1185.058,"gts":1802261500}]
   */
  unsigned long currentMillis = millis();
  String payload="";
  bool error=false;
  if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status 
  { 
    if(currentMillis - previousMillis > interval) 
    {
      previousMillis = currentMillis; 
      HTTPClient http;  //Declare an object of class HTTPClient
      /* --------------------------------------------------------------- */
      http.begin("http://192.168.1.3/e");  //Specify request 
      int httpCode = http.GET(); //Send the request 
      if (httpCode > 0) //Check the returning code
      { 
        payload = http.getString(); //Get the request response payload
        int i1 = payload.indexOf("[");
        int i2 = payload.indexOf("]");
        if (i1 >= 0 and i2 > 0) 
        {       
          payload=payload.substring(i1+1,i2);
          Serial.println(payload);
          bool check =CheckJson(payload);
          if (check == true)
          {
            Serial.println(pwr);           
            display_text(String(pwr)); //output to SSD1306
            //display_text(String("9999")); //test output to SSD1306
          }
        }
      http.end();   //Close connection
      } 
    }
  }
}

bool CheckJson(String Youless) //parse the JSon data
{
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(Youless);
    // Test if parsing succeeds.
  if (!root.success()) 
    return false;
  else {
    pwr=root["pwr"]; //pwr is a global variable!!
    return true;
  }
}

void resetSSD1306(uint16_t pin)
/*
 * need for adafruit SSD1306 I2C breakout board
 */
{
  pinMode(pin,OUTPUT);
  digitalWrite(pin, HIGH);
  delay(1);
  digitalWrite(pin, LOW);
  delay(10);
  digitalWrite(pin, HIGH);
}

void display_text(String text){
  display.setColor(WHITE);
  display.clear();
  display.setFont(Dialog_plain_48);
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 5, text);
  display.display();
}

have you looked at ethernet WebClient

See if this helps.

IPAddress server(192, 168, 1, 3);

// if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET /e HTTP/1.1");
    client.println("Host: 192.168.1.3");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

Thanks all for your help, can now reed the Youless with the Ethernet shield.
Get as output

connecting...
connected
HTTP/1.0 200 OK
Content-Type: application/json

[{"tm":1527504351,"net": 6379.661,"pwr": 153,"p1": 3314.777,"p2": 3064.884,"n1": 0.000,"n2": 0.000,"gas": 1236.380,"gts":1805281200}]
disconnecting.

Is there a way to get the JSON part as a separate string?

I tend to read a line (terminated by \n) into a char array and then look for the JSON paramters irequired, e.g. use strstr() to search for substring "pwr" and the value 153 follows
an alternative is to use the string tokenizer strtok()

PowerSoft:
Is there a way to get the JSON part as a separate string?

Yes. Wait to save the response until after a blank line (double carriage return/line feed) is received.

Thanks so far!!
My next problem is to put the whole code into a procedure like

int getPWRfromYouless() so I can call it periodically!

All the examples find so far are using the loop to get the values from the ethernet shield.
I did this also in the example I enclose
Tried to do it with a while loop like

while (client.available()) {
char c = client.read();
readStr += c;
.....
}

but this is not working. Has anyone a solution for this?

#include <ArduinoJson.h>
#include <SPI.h>
#include <EthernetV2_0.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(192,168,1,3); // Youless

String readString;
int pwr=0; //actual power Youless (global)

// 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;
#define W5200_CS  10
#define SDCARD_CS 4
void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(115200);
  pinMode(SDCARD_CS,OUTPUT);
 digitalWrite(SDCARD_CS,HIGH);//Deselect the SD card
   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:
    for(;;)
      ;
  }
  // give the Ethernet shield a second to initialize:
  delay(100);
  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 /e HTTP/1.1");
    client.println("Host: 192.168.1.3");
    client.println("Connection: close");
    client.println();
  } 
  else {
    // if 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);
    readString += c;
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    //Serial.println("disconnecting.");
    client.stop();

    //Serial.println();
    //Serial.println(readString);
    int i1=readString.indexOf("[")+1;
    int i2=readString.indexOf("]");
    String payload = readString.substring(i1,i2);
    Serial.println(payload);
    Serial.print("JSON_Status = ");
    Serial.println(CheckJson(payload));
    Serial.print("pwr = ");
    Serial.println(pwr);
    Serial.println();
    // do nothing forevermore:
    for(;;)
      ;
  }
}

bool CheckJson(String Youless) //parse the JSon data
{
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(Youless);
    // Test if parsing succeeds.
  if (!root.success()) 
    return false;
  else {
    pwr=root["pwr"]; //pwr is a global variable!!
    return true;
  }
}

the following has a function byte getPage(int thisPort, const char* serverName, const char *page) which executes a HTTP GET and searches the response for a JSON string using strstr()

 /*    HTTP GET method from http://playground.arduino.cc/Code/WebClient */

 // test with http://httpbin.org/ip which responds with the originator IP address

// modifications to original
// 7/10/2017 update IP address and web page information
// 8/10/2017 replaced sprintf() with strcat() calls to build client data

#define SPRINTF       // comment out to use strcat() 

#include <SPI.h>
#include <Ethernet.h>

// this must be unique
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// change to your network settings
IPAddress ip(192,168,1,177);
IPAddress gateway(192, 168, 1, 254);
IPAddress subnet(255, 255, 255, 0);

// change to your server
IPAddress server(192,185,16,85);

//  change as required
char serverName[] = "httpbin.org";      // domain name of server
char pageToGet[]= "/ip";                // page to get
int serverPort = 80;                    // server port

EthernetClient client;

// set this to the number of milliseconds delay between GET requests
#define delayMillis 30000UL
unsigned long thisMillis = 0;
unsigned long lastMillis = delayMillis;

void setup() {
   Serial.begin(115200);
   // disable SD SPI
   pinMode(4,OUTPUT);
   digitalWrite(4,HIGH);

   // Start ethernet
   Serial.println(F("Starting ethernet..."));
   //Ethernet.begin(mac, ip, gateway, gateway, subnet);
   // If using dhcp, comment out the line above 
   // and uncomment the next 2 lines plus the Ethernet.maintain call in loop

   if(!Ethernet.begin(mac)) Serial.println(F("failed"));
   else Serial.print(F("IP "));
   Serial.println(Ethernet.localIP());
   delay(2000);
   Serial.println(F("Ready"));
}

void loop()
{
   Ethernet.maintain();   // If using dhcp to get an IP, uncomment line
   // send data every delayMillis 
   thisMillis = millis();
   if(thisMillis - lastMillis > delayMillis)
   {
      // GET the page
      if(!getPage(serverPort, serverName, pageToGet)) Serial.print(F("Fail "));
      else { Serial.print(F("Pass ")); lastMillis=millis(); }
   }   
}

char inChar;
char data[100]={0};   // << add these
int index=0;

// HTTP GET from page on server serverName using  thisPort 
byte getPage(int thisPort, const char* serverName, const char *page)
{
  int inChar;
  char outBuf[128]="GET ";
  Serial.print(F("\n\nconnecting to "));
    Serial.println(serverName);
  // connect to server
  if(client.connect(serverName, thisPort) == 1)
  {
    Serial.println(F("connected"));
 #ifdef SPRINTF   
     // form HTTP GET and send it - replace sprint() with strcat()
     sprintf(outBuf,"GET %s HTTP/1.1",page);
     client.println(outBuf);
     Serial.println(outBuf);
     // form  server and send it
     sprintf(outBuf,"Host: %s",serverName);
     client.println(outBuf);
#else
    client.println(strcat(strcat(outBuf, page), " HTTP/1.1"));
    Serial.println(outBuf);
    outBuf[0]=0;
    client.println(strcat(strcat(outBuf, "Host: "), serverName));
 #endif
    Serial.println(outBuf);
    client.println(F("Connection: close\r\n"));
  } 
  else
  {
    Serial.println(F("failed"));
    return 0;
  }

  // connectLoop controls the hardware fail timeout
  int connectLoop = 0;
  while(client.connected())
  {
    while(client.available())
    {
      // copy a line of characters into array data
      inChar = client.read();
      if(inChar < ' ')   // if end of line search for "origin": "xxx.xxx.xxx.xxx"
       {
       if(strstr(data, "\"origin") > 0)
              { Serial.print("\n   found > "); Serial.println(data); }
       //Serial.print(" index = "); Serial.println(index);
        index=0;
        }
      else data[index++]=inChar;  // add character to buffer

      data[index]=0;              // add NULL to array
      Serial.write(inChar);       // and display character
      // set connectLoop to zero if a packet arrives
      connectLoop = 0;
    }
    connectLoop++;
    // if more than 10000 milliseconds since the last packet
    if(connectLoop > 10000)
    {
      // then close the connection from this end.
      Serial.println();
      Serial.println(F("Timeout"));
      client.stop();
    }
    // this is a delay for the connectLoop timing
    delay(1);
  }
  Serial.println();
  Serial.println(F("disconnecting."));
  // close client end
  client.stop();
  return 1;
}

a run gives the origin IP address

Starting ethernet...
IP 192.168.1.177
Ready


connecting to httpbin.org
connected
GET /ip HTTP/1.1
Host: httpbin.org
HTTP/1.1 200 OK
Connection: close
Server: gunicorn/19.8.1
Date: Mon, 28 May 2018 17:51:48 GMT
Content-Type: application/json
Content-Length: 29
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur

{"origin":"xxx.xxx.xxx.xxx"}
   found > {"origin":"xxx.xxx.xxx.xxx"}

Thanks Horace for the help.
Have change the code a bit as I think it should working but without the result I wont :frowning:

Have include the changed code, please can you take a look :slight_smile:

Thanks in advance

Jan

#include <ArduinoJson.h>
#include <SPI.h>
#include <EthernetV2_0.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// 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;
#define W5200_CS  10
#define SDCARD_CS 4

// set this to the number of milliseconds delay between GET requests
#define delayMillis 1000UL
unsigned long thisMillis = 0;
unsigned long lastMillis = delayMillis;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  pinMode(SDCARD_CS,OUTPUT);
  digitalWrite(SDCARD_CS,HIGH);//Deselect the SD card

  // Start ethernet
   Serial.println(F("Starting ethernet..."));

   if(!Ethernet.begin(mac)) Serial.println(F("failed"));
   else Serial.print(F("IP "));
   Serial.println(Ethernet.localIP());
   delay(2000);
   Serial.println(F("Ready"));
}

void loop() {
  Ethernet.maintain();
  // send data every delayMillis 
   thisMillis = millis();
   if(thisMillis - lastMillis > delayMillis)
   {
      // GET the page
      if(!getPage()) Serial.print(F("Fail "));
      else { Serial.print(F("Pass ")); lastMillis=millis(); }
   }   
}


// HTTP GET from page on server serverName using  thisPort 
byte getPage()
{
  String readString;
  // Make a HTTP request:
  client.println("GET /e HTTP/1.1");
  client.println("Host: 192.168.1.3");
  client.println("Connection: close");
  client.println();
  while(client.connected())
  {
    while(client.available())
    {
      char c = client.read();
      //Serial.print(c);
      readString += c;
    }
  }
  delay(1);
  Serial.println();
  Serial.println(F("disconnecting."));
  // close client end
  client.stop();
  Serial.println(readString);
  return 1;
}

if the loop where you are reading text transmitted from the remote server you need to read a line of text (terminated by \n) and look for JSON in the line, e.g. sometging like

  while(client.connected())
  {
    while(client.available())
    {
      char c = client.read();
      if(c >= ' ')
          readString += c;  // printable character
      else
         {  // end of line check for JSON start characters
          if(readString.subString(0,2) == "[{")
              // JSON found process it
              
         }
     readString="";   // new line clear string
    }
  }

it is not recommended to use String it can cause problems - use character arrays see post #12

Thanks, it is still not working.
There will not be a connection when I call get page().

After making the HTTP request I have make an output of

Serial.println(client.connected());

The printed value is "0", that means no connection.
Is my HTTP request wrong?

byte getPage()
{
  String readString="";
  // Make a HTTP request:
  client.println("GET /e HTTP/1.1");
  client.println("Host: 192.168.1.3");
  client.println("Connection: close");
  client.println();
  Serial.print("client.connected : ");
  Serial.println(client.connected());
  while(client.connected())
  {
    
    while(client.available())
    {
      char c = client.read();
      Serial.print(c);
      readString += c;
    }
  }
  delay(1);
  Serial.println();
  Serial.println(F("disconnecting."));
  // close client end
  client.stop();
  Serial.println(readString);
  return 1;
}

It will still not work. Build in a check after the HTTP request. Print the value of client.connected().
This value is "0".
Is my HTTP request perhaps wrong on this place?

byte getPage()
{
  String readString="";
  // Make a HTTP request:
  client.println("GET /e HTTP/1.1");
  client.println("Host: 192.168.1.3");
  client.println("Connection: close");
  client.println();
  Serial.print("client.connected : ");
  Serial.println(client.connected());
  while(client.connected())
  {
    
    while(client.available())
    {
      char c = client.read();
      Serial.print(c);
      readString += c;
    }
  }
  delay(1);
  Serial.println();
  Serial.println(F("disconnecting."));
  // close client end
  client.stop();
  Serial.println(readString);
  return 1;
}

I don't think you have called client.connect() before transmiting the GET etc

Thanks for all the help, it's now working. Perfect :slight_smile: