Http client library not working


#1

Hi,

I was trying to use the http client library for a project but it does not compile. I have used the library example to be sure it is not my code which produces the error.
You can find the library here: https://github.com/nmattisson/HttpClient

Is there an easy way to fix this issue?

The error message:

HttpClient/HttpClient.cpp: In member function ‘void HttpClient::request(http_request_t&, http_response_t&, http_header_t*, const char*)’:
HttpClient/HttpClient.cpp:176:19: warning: unused variable ‘firstRead’ [-Wunused-variable]
unsigned long firstRead = millis();
^
…/…/…/build/target/wiring/platform-103-m//libwiring.a(spark_wiring_tcpclient.o): In function TCPClient::connect(char const*, unsigned short, unsigned long)': /mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:62: undefined reference toinet_gethostbyname’
/mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:70: undefined reference to spark::Network' ../../../build/target/wiring/platform-103-m//libwiring.a(spark_wiring_tcpclient.o): In functionTCPClient::available()’:
/mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:147: undefined reference to spark::Network' ../../../build/target/wiring/platform-103-m//libwiring.a(spark_wiring_tcpclient.o): In functionTCPClient::connect(IPAddress, unsigned short, unsigned long)’:
/mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:97: undefined reference to HAL_WLAN_SetNetWatchDog' /mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:101: undefined reference toHAL_WLAN_SetNetWatchDog’
/mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:110: undefined reference to spark::Network' ../../../build/target/wiring/platform-103-m//libwiring.a(spark_wiring_tcpclient.o): In functionTCPClient::status()’:
/mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/wiring/src/spark_wiring_tcpclient.cpp:219: undefined reference to `spark::Network’
collect2: error: ld returned 1 exit status
make[1]: *** [ebc10991d7345156d5c1e22bd938cff92a72a946e5cdc38b1f2a31edd94f.elf] Error 1
make: *** [/mnt/compile-service-shared-workspace/103_bluz_34_1/firmware/modules/bluz/user-part/makefile] Error 2
Error: Could not compile. Please review your code.


#2

Howdy

In short, nope. Sorry. This one is not going to be easy to fix.

The BluzDK is a BlueTooth LE device. That is to say, it communicates with the world via BT protocols, not TCP/IP. Therefore, it has no TCP/IP capabilities, in and of itself – whereas the SparkCore and Photon are. Thus, it seems to me that you’ll not be able to make a direct connection to an HTTP server.

That said, I believe Particle’s “Web Hooks” system may fill your need …

EDIT: See my next reply for a working example of WebHooks on a BluzDK

https://docs.particle.io/guide/tools-and-features/webhooks/. The Particle Cloud will then take care of the HTTP requests and relay the data back to your BluzDK. (I haven’t used it yet, but will test it now.)

Aside from that, it would certainly be possible to set up some kind of bridge get HTTP connections going through a Bluz Gateway device. But I’m not aware of any efforts to make that happen, yet – and given the WebHooks engine, I doubt it’s worth the effort and the extra battery drain on your BLE device.

EDIT: Oh … for those who Googled here later on … that has been implemented already. See @eric’s post concerning BLE.send, below.


#3

@hl68fx … I’ve managed to get WebHooks working on the BluzDK. It’s not especially stable, but the following code seems to handle most the current pitfalls …

#include <stdlib.h> // strstr()

/**
 * @brief Handle the webhook event we subscribed to in loop()'s one_shot
 * @desc  Our WebHook is set up to HTTP GET from URL: http://api.icndb.com/jokes/random
 *        An example response follows ...
 *
 *           { \"type\": \"success\", \"value\": { \"id\": 215, \"joke\": \"Chuck Norris just says
 *             &quot;no&quot; to drugs. If he said &quot;yes&quot;, it would collapse
 *             Colombia's infrastructure.\", \"categories\": [] } }
 *
 *        Note that the Particle WebHook system adds the backslash escapes to each " *shrug*
 *
 *        We will locate the Joke's text between \"joke\": \"  and  the following \"
 *        and re-publish on the Particle clou, just to prive it all works.
 **/
#define START_MARKER "\"joke\": \""
#define END_MARKER "\\\""
void myHandler(const char *event, const char *data) {

  // locate the Joke's text in the JSON data -- ugly hack style ;-)
  char *jokeText = strstr(data, START_MARKER)+strlen(START_MARKER);

  // null terminate the string at the next '\"'
  *strstr(jokeText, END_MARKER) = '\0';

  delay(1000); // try to be a nice netizen

  digitalWrite(D7, 1); // blink the on board LED around the publish event

  Particle.publish("Incoming Joke!", jokeText); // Publish the Joke's text, to show things are working

  delay(500); // give the LED a chance to outlive a human blink
  digitalWrite(D7, 0);

}

void setup() {

  // set pin D7 (the on board LED) as an output
  pinMode(D7, OUTPUT);

}

void loop() {

  // Wait until the Particle Cloud comes online, then subscribe to our WebHook event (only once!)
  static bool online = false;
  if (!online && Particle.connected()) {
    online = true;
    Particle.subscribe("hook-response/chuck_norris", myHandler, MY_DEVICES);

    delay(1000); // be polite

  }

  if (online) {

    // trigger Web Hook, which will retrieve the response from GET http://api.icndb.com/jokes/random
        // and broadcast a hook-response/chuck_norris WebHook event -- the one we have subscribed  to above
        Particle.publish("chuck_norris", "Gimme Joke!", PRIVATE);

        // Wait 60 seconds before doing it all again
        delay(60000); // wait out the remainder of a minute to be a polite netizen

        // NOTE: For some reason, the first trigger after coming online never seems to result in a return event
        //       until after the second trigger, when two events usually come in back-to-back. So hurry up and
        //       a minute before you conclude this aint working, mmmkay?

  } else {

    delay(500); // back off some while we wait for the Particle Cloud to (re)connect, perhaps
  
  }

}

The Particle WebHook itself is configured thusly …

… and a snippet from my Particle Dashboard logs …

Hope that helps!


#4

Hi @gruvin,

thank you very much for your detailed answer! Currently I am logging sensor data from several Photons to my InfluxDB via http post on my homeserver. I am working on a small project where I would like to monitor my vegetables. The BluzDK is ideal because of its low power consumption. I am powering it with an Adafruit solar charger which works very well.
Your explanation why the http client library will not work on the BluzDK makes a lot of sense. So I will have to wait until webhooks support posting to an InfluxDB.

But I have another idea for a small usefull project where your code will be very helpful for me! I will post it when it is ready and working :slight_smile:

Thank you very much!


#5

Well, it pretty much already does, with just a little bit of fuss. :slight_smile:

A WebHook can connect to any HTTP port and send whatever data you want, more or less.

In your case, I imagine you would need the WebHook server to connect to your local machine. For that, you set up a port forward on your Internet router. Forward external port 8086 to your.machines.internal.ip.address (EG. 10.0.1.100) on the same port 8086. You might wish to Google port forwarding or look into the documentation for your specific router/modem.

Now, so that the WebHook server can locate your router on big wide 'net, you’ll want to use a dynamic IP service. Options include http://www.noip.com and http://dyn.com. The former (noip) is very popular and has free options, I believe. I happen to have a paid Dyn account.

Once you have that set up, you would create a WebHook in the Particle Dashboard, something like this …

and

Then, taking my previous example as a starting point, you might do something like this …

    Particle.publish("influx_write", "field=water_level value=full", PRIVATE);

… to write the value “full” to some InfluxDB data field named, “water_level” … bearing in mind that I know nothing about InfluxDB, other than what I quickly gleaned via Google, just now. :wink:

The second/middle parameter in the publish call will be passed on by the WebHook system as the POST data it sends. Taking an example from the InfluxDB docs, this …

curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'

… should translate to …

    Particle.publish('influx_write', 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000', PRIVATE);

So in summary – your Particle.publish(...) on your BluzDK will send a trigger to your Particle WebHook, via publish(). Upon receiving that trigger, the Particle WebHook server will make a connection to your local machine – finding it via your noip dynamic IP.

The rest should be familiar, as if you were connecting to http://localhost:8086, locally.


In a similar fashion, there are a number of Cloud based data repositories that may work for you, instead of relying on a local installation of InfluxDB, say. One such example, as showcased in the Particle WebHooks documentation, is ThingSpeak.


Seems you have some homework! :wink:

If you get stuck, I’d be happy to set up a working example of the above, when I have the time.

Oh – one last thing. I would suggest you prototype all that using a Photon, as those are currently much more stable than BluzDK. Once you have it working, you can adapt it to the Bluz. It ought to Just Work™ – so long as you check Particle.connected() before attempting the publish part. (See my original example, in the loop() part. Not doing that currently sends the Bluz firmware into a bit of a tiz.


#6

@gruvin @hl68fx: There is actually a much simpler way to do this. I need to document this better, but bluz DK can send custom data to the Photon (or P1, Electron or Core) on the gateway/gateway shield, and the Photon/P1/Electron/Core can then use the HTTP library to send the data to your database.

All you need to do is use the current BLE.send command, this will send data from the DK to the gateway. Currently, the gateway code doesn’t use it, but I just uploaded a new sketch to handle this. You can look here: https://github.com/bluzDK/particle-gateway-shield-code/blob/master/particle-gateway-code/particle-gateway-code.cpp#L75

So you can add code in here to handle the data and send it to your local webserver, just as you would using the Photon normally. Flash that to the Photon on your gateway shield, and you are good to go.

The data that is handed to the function comes from bluz DK by calling BLE.send, as you can see in this example: https://github.com/bluzDK/bluzDK-firmware/blob/develop/user/applications/custom_data_service/custom_data_service.cpp#L21

So collect your sensor data in bluz DK, send it to the Photon/P1/Electron/Core and let it handle the sending to your local webserver.

I will try and document this better today so it is clear this can be done. I am copying @peekay123 as well since he had asked about this in the past.

EDIT: One note, you will need 1.1.47 to make this work. This is part of the release, so you can do all of this from the Web IDE, not need to local compile. Just make sure you are using 1.1.47 on bluz.


#7

Oh! I mentioned that would be possible in my first reply. I didn’t know it had already been done. Cool. Should be much less fuss. Just use the Gateway’s Photon to do the httpClient stuff, using sensor data send from Bluz using BLE.send. Yay \o/

You’re a hard man to keep up with @eric! I don’t know how you do it.


#8

@eric, as usual, you rock! Today is Maker Faire travel day for me so I will take a look during the course of the week. The Bluz is really shaping up to be a killer BLE device :wink:


#9

Ok, I added some documentation around all of this. You can see how to use the functions here: http://docs.bluz.io/reference/ble/#senddata

I also added a tutorial on local communication between bluz DK and the gateways here: http://docs.bluz.io/tutorials/local_communication/

Clearly some people are using this with apps as well, and that is totally fine. I didn’t add that here specifically yet because we don’t have the other side of it completed, which is the Android and iOS SDK (and, maybe, possibly Windows Phone…). Once we have a really good SDK on the app side, then people can just add it into their apps and call things like bluz.connect() and bluz.sendData() from their own code.

Hmmmm… that sounds like a great idea for a Bounty actually…


#10

@eric … just wondering … do you ever sleep? Or do you have a bunch of @eric clones helping you or something? Whatever it is … I want what you have! :stuck_out_tongue:


#11

Hi @gruvin,

thank you very much for your example. I have tried to get it working but my attempts where not successful so far.
Port forwarding works, because i am using it already with three Photons who post data via http client to my InfluxDB.
I have set up my Webhook like your example. I am using one BluzDK and one Particle Core with your Particle.publish example.

I can see the published data in the dashboard:

Event name: hook-sent/influx_write
{"data":"undefined","ttl":"60","published_at":"2016-05-18T14:53:10.929Z","coreid":"particle-internal","name":"hook-sent/influx_write"}

Event name: influx_write
{"data":"sensors,Location=testlocation Moisture=0 1434055562000000000","ttl":"60","published_at":"2016-05-18T14:53:10.947Z","coreid":"removed","name":"influx_write"}

My webhook:

My Particle.publish:
String data = “sensors,Location=testlocation Moisture=” + String(moisture) + " 1434055562000000000";
Particle.publish(“influx_write”, data, PRIVATE);

Both my database and my measurement are called sensors.
I am using influxDB 0.12 with Grafana 3.0.1

Could it be that it is nor working because I can remember that Particle announced Webhooks for InfluxDB for the future?

Kind regards,
Tom


#12

I am using local communication now and my gateway sends the data to my InfluxDB. This works very good so far :slight_smile:


#13

@hl68fx … so, those 3 photons are outside your local network? Using http://???ddns.net address in httpClient?

If not, like if they are just using the local IP address of your InfluxDB server … then port forwarding is not involved, at all – but needs to be for the WebHook inbound connection from outside your local net.

Are we confused on this point?


#14

Two of my three Photons are outside my local Network and all of them use the dyn dns address.
All the traffic to this address with port 8086 is forwarded to the static ip of my home server with port 8086.
This works fine with the http client library.


#15

Understood. Not sure what the problem could be then. In any case …

… just in case you didn’t catch it in the longer comment above, I’m now working on bringing TCPClient to Bluz.