Pass extra variables to ethercard callback function

The default callback function is defined as follows:

static void my_callback (byte status, word off, word len) {
  delay(50);
  Serial.println(">>>");
  Ethernet::buffer[off + 300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
}

and this is called from browseUrl, for example:

ether.browseUrl(PSTR("/foo/"), "bar", website, my_callback);

However, I'd like to expand the my_callback function, for example (note the addition of _query and _state variables):

static void my_callback (byte status, word off, word len, int _query, int _state) {
  Serial.print(">> Callback ");
  Serial.print(_query);
  Serial.println(" >>");
  Ethernet::buffer[off + 300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
  state = _state; // Move to state that causes next browseUrl
}

In the browseUrl statement, the function is called with no variables (status,off and len - which seem to be defined in the library somewhere). Is there an easy way of doing this?

spandit: In the browseUrl statement, the function is called with no variables (status,off and len - which seem to be defined in the library somewhere). Is there an easy way of doing this?

it actually is not called there; It's a callback. so you give the system a pointer to the function you want to call back later when something has happened and what is passed to that function is defined by the library.

the code in the ethercard/tcpip.cpp file where the client_browser_cb (this is your callback) is used is:

static uint8_t www_client_internal_result_cb(uint8_t fd, uint8_t statuscode, uint16_t datapos, uint16_t len_of_data) {
    if (fd!=www_fd)
        (*client_browser_cb)(4,0,0);
    else if (statuscode==0 && len_of_data>12 && client_browser_cb) {
        uint8_t f = strncmp("200",(char *)&(gPB[datapos+9]),3) != 0;
        (*client_browser_cb)(f, ((uint16_t)TCP_SRC_PORT_H_P+(gPB[TCP_HEADER_LEN_P]>>4)*4),len_of_data);
    }
    return 0;
}

so you would need to modify the library to get your extra parameters stored when you do call browseUrl (that where it remembers in the variable client_browser_cb your callback)

void EtherCard::browseUrl (const char *urlbuf, const char *urlbuf_varpart, const char *hoststr, const char *additionalheaderline, void (*callback)(uint8_t,uint16_t,uint16_t)) {
    client_urlbuf = urlbuf;
    client_urlbuf_var = urlbuf_varpart;
    client_hoststr = hoststr;
    client_additionalheaderline = additionalheaderline;
    client_postval = 0;
    client_browser_cb = callback;
    www_fd = clientTcpReq(&www_client_internal_result_cb,&www_client_internal_datafill_cb,hisport);
}

and pass them back at cal back time

(*client_browser_cb)(f, ((uint16_t)TCP_SRC_PORT_H_P+(gPB[TCP_HEADER_LEN_P]>>4)*4),len_of_data, [color=red]_query[/color], [color=red]_state[/color]);

or find a way to store the info for later use in your code

spandit: Is there an easy way of doing this?

:D

I'm guessing you and I have very different definitions of "easy" :lol:

Just thought it would make things neater doing it this way rather than having several my_callback functions defined to do the same thing

LOL :slight_smile:

it’s actually not that difficult but understand it can be scary :wink:

I’m curious why the _query and _state info can’t be just available in the callback?

J-M-L: LOL :)

it's actually not that difficult but understand it can be scary ;)

I'm curious why the _query and _state info can't be just available in the callback?

Ah, because now that you've helped me get my browseUrl thing working, I want to be able to return multiple web queries. Using the code from here

you can see he uses two distinct callback functions. They only differ in the way that they change the _state (in his case state) variables and print Callback 1 or Callback 2 (the "1" or "2" would be the _query variable).

I'm sure I could modify the library but then every other project I wanted to use the ethercard library in, I'd have to remember to define/post extra variables into the callback function.

well his code is to do only do one thing... wait without blocking the main loop until the callback from the first browseUrl call has happened before sending the second one... it actually feels pretty complicated to me to get there... I'm unsure why he just does not check the value of state which is set in the first call back to decide to trigger the next request... feels weird

so he still sends them serially...

Are you saying there's a way to send them non-serially (parallelly?) :)

I think I've modified his code sufficiently to do what I want but haven't had a chance to try it with all the hardware yet

No I'm saying that they are serial.

send a request wait for the call back send another request wait for the call back send another request wait for the call back

that's how it woks.

if you don't want to do an active wait because that's not good for your program, then just set a flag in the call back to remember in which state you are and don't forget to do the ether.packetLoop(ether.packetReceive()); at each loop to keep things moving.

I think that's what I've done... Not easy to test with children and dogs tripping over the Cat6 PoE cable...