Loading...
Pages: [1]   Go Down
Author Topic: How to get substrings from char pointer array  (Read 946 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the ethercard library (https://github.com/jcw/ethercard) to set the Arduino up as a web client so I can read data from a website.
All this is working correctly and the demo webClient sketch (https://github.com/jcw/ethercard/blob/master/examples/webClient/webClient.ino) works perfectly.
I have even change the web site and page to be access and the correct output is sent to the serial monitor.

My problem is that my knowledge of C and pointers is very limited.

I know that Ethernet::buffer is an array of bytes using pointers.

What I am trying to do is read the Google XML weather data from http://www.google.com//ig/api?weather=London
Extract the current temp_c, humidity, icon and wind_condition data and use them to create an output.

Where I am failing is how to parsing a char.  Any advice or pointers (sorry for pun) on how to do this would be appreciated.

Below is the webclient code I am working from

// Demo using DHCP and DNS to perform a web client request.
// 2011-06-08 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer[700];
static uint32_t timer;

char website[] PROGMEM = "www.google.com";

// called when the client request is complete
static void my_callback (byte status, word off, word len) {
  Serial.println(">>>");
  Ethernet::buffer[off+300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
}

void setup () {
  Serial.begin(57600);
  Serial.println("\n[webClient]");

  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");
  if (!ether.dhcpSetup())
    Serial.println("DHCP failed");

  ether.printIp("IP: ", ether.myip);
  ether.printIp("GW: ", ether.gwip);
  ether.printIp("DNS: ", ether.dnsip);

  if (!ether.dnsLookup(website))
    Serial.println("DNS failed");
   
  ether.printIp("SRV: ", ether.hisip);
}

void loop () {
  ether.packetLoop(ether.packetReceive());
 
  if (millis() > timer) {
    timer = millis() + 5000;
    Serial.println();
    Serial.print("<<< REQ ");
    ether.browseUrl(PSTR("/foo/"), "bar", website, my_callback);
  }
}
Logged

United Kingdom
Offline Offline
Faraday Member
**
Karma: 131
Posts: 4690
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Please use the # button when posting code, it makes it easier to read.

I found a library for parsing XML on arduino at http://john.crouchley.com/blog/archives/454. Alternatively, you can search for strings and characters inside a null terminated string using the strstr and strchr functions from the standard C library.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. http://www.eschertech.com

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you got a sample of the output ?
Logged

India
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
OS Developer, ASIC and FPGA designer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I generally use strstr() function:
char buffer[]="+CBC: 0,99,4190" ; // this is a return string by GSM modem  0,charge level, millivolt
char *ptr;  //temp pointer variable for pointer artihmetic
char *fieldPtr; //temp pointer  variable for pointer artihmetic
:
:
:
:
ptr=strstr(buffer,"+CBC:"); // if substring found in buffer it return address ofstart character of matched string
                      // if not matched it returned NULL
if(ptr!=NULL)
{
   ptr=strstr(ptr,",");
   Serial.println(ptr);         // will print :",99,4190"
                       // you can use pointer arithmetic to get the field
   while(ptr!=NULL)
   {
    ptr++;
    fieldPtr=ptr;
    ptr=strstr(ptr,",");
    *ptr='\0';
    Serial.println(fieldPtr);
   }
}
--------Output---------------------------------
,99,4190
99
4190
Logged

UK
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I generally use strstr() function:
char buffer[]="+CBC: 0,99,4190" ; // this is a return string by GSM modem  0,charge level, millivolt
char *ptr;  //temp pointer variable for pointer artihmetic
char *fieldPtr; //temp pointer  variable for pointer artihmetic
:
:
:
:
ptr=strstr(buffer,"+CBC:"); // if substring found in buffer it return address ofstart character of matched string
                      // if not matched it returned NULL
if(ptr!=NULL)
{
   ptr=strstr(ptr,",");
   Serial.println(ptr);         // will print :",99,4190"
                       // you can use pointer arithmetic to get the field
   while(ptr!=NULL)
   {
    ptr++;
    fieldPtr=ptr;
    ptr=strstr(ptr,",");
    *ptr='\0';
    Serial.println(fieldPtr);
   }
}
--------Output---------------------------------
,99,4190
99
4190


pravas - Thanks.
This looks like the kind of thing I'm trying to do but for a web page rather than GPS.
I think some experimenting over the weekend will see if I understand what you are saying.

Albert.

Logged

India
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
OS Developer, ASIC and FPGA designer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes you can use the webpage XML data  into the buffer.

char buffer[]="------------------------------XML DATA-----------------------------------------"; //This is a character array buffer.

In logic you must Identify the token, FieldName, FieldValue etc.

Goodluck for your experiment..
Logged

Ontario
Offline Offline
God Member
*****
Karma: 15
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The data returned from "http://www.google.com//ig/api?weather=London" is 1371 bytes, not counting headers.  It us unlikely you will be 100% successful with the approach of loading the whole response into a string and searching around in it with stsrstr().

I would structure this as a parser like below that uses a small buffer to recognize just one tag at a time, and then feed all the data you receive into it.  This allows you to avoid saving huge swaths of the response at once.  You just feed your data into handle_input() one character at a time and it does the rest.

Code:
char token[TOKEN_LEN];
uint8_t input_len = 0;

void handle_input(uint8_t c)
{
 int temp;

    /* c = '<', then a new tag sequence is starting
     */
    if (c == '<') {
        input_len = 0;
        return;
    }

    /* c = '>', a tag sequence is complete.
     * Check if this is a specific tag
     */
    if (c == '>') {
       token[input_len] = 0;

       if (strncmp(token, "temp_c data=\"", 13) != 0)
           return;

       temp = atoi(token + 13);

// Now what?
//
Serial.print("got temperature ");
Serial.print(temp);

    }

    /* otherwise we have an input character
     */
    if (input_len <= TOKEN_LEN - 1)
       token[input_len++] = c;
}
Logged

UK
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for the advice.
I have a feeling for me I'm  byting off more than I can chew for now.
I think I need to learn a bit more C++ before I can get my head around this.

Again, thanks for the advice.
Albert.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey, I have same problem with reading the array – have you found a solution ?
I can call a web page, and in my serial monitor can I read that I receive the correct data from the web server, but how can “work” with my received data ?
/Per
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 316
Posts: 35590
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but how can “work” with my received data ?
Collecting the data in an array is the first step. Then, define what ""work" with my received data" means.

There are plenty of examples around of parsing the data that a client sends to the Arduino server, or that an Arduino client fetches from a server.
Logged

Pages: [1]   Go Up
Print
 
Jump to: