-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Not really a bug report or "issue", just wanted to open a discussion on this. It's along the same lines as the "has connection"/"pull out wifi" discussed in #8
Description of the problem.
Maintaining multiple versions of the same sets of code is tough. I've looked into ways that the library might be able to be consolidated, but I haven't found anything that would map 1:1 directly, because the ESP8266 seems to use BearSSL whereas that is currently unsupported on the ESP32 (as far as I can tell). I'm also not sure if other methods of connectivity would be able to be implemented in a similar way, in which case having a "per-board" implementation seems to make a lot of sense (with perhaps pulling out what is common between them, such as certain functions like getWorkSpaces I've referenced in #7.
Take for example the current implementation of getUserData. The only difference is as follows:
// ESP8266
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setFingerprint(Fingerprint);
HTTPClient https;
https.begin(*client, BaseUrl + "/me");
https.addHeader("Authorization", AuthorizationKey, true);
//ESP32
HTTPClient https;
https.begin(BaseUrl + "/me", root_ca);
https.addHeader("Authorization", AuthorizationKey);Describe the solution you'd like
Given that the differences between the methods are very minor as they stand, pulling out the connection method into it's own per-device function seems like a good call.
- A separate c++ file (let's call it "Connections.cpp") with
#ifdefsfor each board supported. For each board, avoid connect(String &URL)function would be implemented. - The Toggl class would have a global private HTTPClient object. For the 8266, the "WiFiClientSecure" unique pointer could likely also be pulled out of the connect() method (or left in, but it could no longer be a unique pointer in that case and would need to be cleared after each call). I don't know if headers need to be added for each call (for example setting the Authorization header - it'd be good if that only needed to be written once), but that could be left up to implementation.
- The example listed above would be converted to contain something similar to the following in the "Connections.cpp"
void Toggl::connect(){
#if defined (ESP8266)
https.begin(*client, URL);
https.addHeader("Authorization", AuthorizationKey, true);
# elif defined(ESP32)
https.begin(URL", root_ca);
https.addHeader("Authorization", AuthorizationKey);
# endif
}The BearSSL client for the ESP8266 code would be created as a global when the library initialized.
There would then only be a single getUserData function to maintain, and it would be easier to incorporate additional boards/connection methods. The following would work for any board/connection method when added:
...
connect();
https.addHeader("Content-Type", " application/json");
...Memory
The above suggested implementation ends up with slightly less memory in the ROM (387680 as opposed to 387776), but I'm unsure of that HTTPClient variable (and WiFiClientSecure variable in the case of the ESP8266) sitting permanently instantiated. I'm not sure if it makes much of a difference either, I have neither the tools or knowledge to profile it, and it's beyond my knowledge if I'm honest. There's a case to be made for memory optimization in either scenario - with globals we are guaranteed we are able to make requests, with locals we have more memory for other things. I know embedded practice generally advises against globals, but sometimes they are unavoidable.
Additional comments
I think the movement to a single code base that easily allows boards and connection methods to be added is important, and that is the motivation of this discussion.
That being said, I think it is a trade off between memory management and complexity. I don't think the memory management would go too "off the wall" with a global HTTPClient, though I haven't run any in-depth profiling and I think it would be fine (though it would probably be worth asking someone more experienced and knowledgeable).
Another option entirely is to write something like a Python script to generate code for a list of boards as an alternative to the solution given above, but that feels like it would just be doing the job of the pre-processor anyway.