A library based on WIFiClient

Hi all,

I have been trying implementing a library named as "Httpupstream" which is based on the WiFiClient.

The idea is following:

  1. Invocate the "Httpupstream" with one parameter Client&.
  2. The Client& is WiFiSSLClient type.

However, it doesn't work. The code is as following:

httpupstream.h:

#ifndef HttpUpstream_h
#define HttpUpstream_h

#include "Arduino.h"
#include <NTPClient.h>
#include <WiFiNINA.h>
#include <Base64.h>
#include <ArduinoJson.h>

class HttpUpstreamClient{

private:

char* _clientId;
char* _host;

public:

WiFiSSLClient _networkClient;

HttpUpstreamClient(Client& networkClient);

void registerDevice(char* deviceName, char* deviceType);

void sendMeasurement(char* fragment, char* series, char* value, char* unit, String timestamp);

};

#endif



httpupstream.cpp:

>  #include "Arduino.h"
> #include "HttpUpstream.h"
> #include <string.h>
> 
> 
> HttpUpstreamClient::HttpUpstreamClient(Client& networkClient){
> 
> 
> _networkClient = networkClient;
> 
> 
>   }
> 
> 
> HttpUpstreamClient::registerDevice(char* deviceName, char* URL){
> 
> if(networkClient.connect(URL,443)){
>     Serial.println("Connected to server");
>     networkClient.println("POST /inventory/managedObjects/ HTTP/1.1");
>     networkClient.println("Host: "+URL);
>     networkClient.println("Authorization: Basic bGl1eWluemU6bDExNjExNjExNg==");
>     networkClient.println("Content-Type: application/json");
>     networkClient.print("Content-Length: ");
>     networkClient.println(body2send.length());
>     networkClient.println("Accept: application/json");
>     networkClient.println();
>     //client.println("Connection: close");
>     client.println(body2send);  
>   
>     }    
>   }

  
The error is 


  HttpUpstream.cpp:10:18: error: no match for 'operator=' (operand types are 'WiFiSSLClient' and 'arduino::Client')
  _networkClient = networkClient;
                  ^~~~~~~~~~~~~

Full details please

The error is:

  HttpUpstream.cpp:10:18: error: no match for 'operator=' (operand types are 'WiFiSSLClient' and 'arduino::Client')
  _networkClient = networkClient;
                  ^~~~~~~~~~~~~

I think Client& doesn't contain the type WiFiSSLClient?

Which "Arduino" board?

Have you studied the inheritance relationship between the Client and WiFiSSLClient types?

just change it to

HttpUpstreamClient(WiFiSSLClient& networkClient)

for now.

and you have to initialize the reference this way

HttpUpstreamClient::HttpUpstreamClient(WiFiSSLClient& networkClient) 
  :  _networkClient(networkClient) 
{
}</s>

Hi,

I just wanted more boards to be included when users use WiFi. That's reason I used Client&. Is that possible that more boards could be included using Client&?

Thank you!

Is that possible that my library could be adapted to different boards? For example, MKR wifi 1010 using WiFiNINA, MKR1000 boards using WiFi101... Because as you can see that I am just experimenting with WIfININA and I need the "Client" to be more general.

I am testing with MKR WiFi 1010. But I want my library to be more general so that the users just need to include the corresponding WiFi library according to the board they use. If that is possible, how can I do it?

Looks like you missed my other question:

No, I didn't study it... I didn't find them on the internet...

Arduino is Open Source. All library source code is on your computer.

The structure is:

WiFiSSLClient
    ^
    |
WiFiClient
    ^
    |
 Client

Meaning that WiFiSSLClient indirectly inherits from Client. So, you just can't assign an object of the Client (base) class to an object of the WiFiSSLClient (inherited) class.

Thank you and that's really helpful!

I still have a question. Currently my library is based on WIFININA. What if users want to use WIFI101 or other WiFi library? How can I make my library more flexible? Thanks!

Hard to say since you haven't stated what the library is supposed to do or why it would even be useful in the first place.

Sorry for not indicating the purpose of making this library.

The library is supposed to wrap up the http header using "wificlient" from ANY wifi library. To this end, I need to introduce an argument with "WiFiClient" property when the user invocates the library at very beginning of their code. That's the reason I asked about it.

I guess you need study the source code of all those ANY libraries. The inheritance structures of WiFiNINA and WiFi101 are shown below. You'll see they start with common bases classes and then branch apart. It's still not clear to me exactly what you want to do or what value will be added.

I think the ONLY method to do it - force the user to use your library instead of ANY other.

Thanks! That's really helpful!

The code without using my library is like:

#include <NTPClient.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <WiFiNINA.h>

WiFiSSLClient client;
StaticJsonDocument<500> body;
StaticJsonDocument<500> body_2;
StaticJsonDocument<200> filter;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP,"pool.ntp.org");


void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    
    // wait 10 seconds for connection:
    delay(6000);
  }
   Serial.println("Connected to WiFi");
   timeClient.begin();
   httpsCreatDevice();
    }

void httpsCreatDevice(){
     client.stop();

     
     String body2send= "";
     body["name"] = "Arduino MKR wifi 1010 test_1";
     body["c8y_IsDevice"]="{}";
     //serializeJsonPretty(body, Serial);  
     serializeJsonPretty(body, body2send);
     Serial.println(body2send);  
   if(client.connect(url_cumulocity_test, 443)){
    Serial.println("Connected to server");
    client.println("POST /inventory/managedObjects/ HTTP/1.1");
    client.println("Host: yingzheliutest.cumulocity.com");
    client.println("Authorization: Basic 12346dasdasd613");
    client.println("Content-Type: application/json");
    client.print("Content-Length: ");
    client.println(body2send.length());
    client.println("Accept: application/json");
    client.println();
    //client.println("Connection: close");
    client.println(body2send);
    //client.println(serializeJson(body, Serial));
      

    }

With my library, the part "httpsCreatDevice()" will be handled by me and users don't have to take care of http header. Our users are not familiar with the network protocol and we don't hope them to spend too much time on "wrapping up" the undelaying header.

The final goal is as following,

WiFiSSLClient client;
Httpupstream upstreamClient(client); //For example, my library is called as Httpupstream.

char* username= "";
char* password= "";
char* deviceid= "";
char* URL= "";

Setup(){

//WiFi part is ignored here for sake of the simplicity
//WiFi part starts here
 .....
//WiFi part ends here

upstreamClient.registerDevice(username, password, deviceid, URL);

}

loop(){

}

As you can see, to this end, the user must indicate the WiFiclient and it depends on the board they use. That's the reason I ask this. Maybe the argument type on upstreamClient() could be Client& instead of being WiFiSSLClient.

upstreamClient(Client& networkclient) 

Hope this can solve your doubts.

Perhaps. Let us know how it works out.

1 Like

I guess

public:

Client* _networkClient;

would solve the problem.
then

 HttpUpstreamClient::HttpUpstreamClient(Client& networkClient) {
   _networkClient = &networkClient;
 }

and

if (_networkClient->connect(URL,443)){
1 Like