diff --git a/.github/workflows/platformio-ci.yml b/.github/workflows/platformio-ci.yml
index 2b1b710d..31536c8e 100644
--- a/.github/workflows/platformio-ci.yml
+++ b/.github/workflows/platformio-ci.yml
@@ -83,9 +83,9 @@ jobs:
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- - name: Install SDL2
- run: sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" && sudo apt-get update -y -qq && sudo apt-get install libsdl2-dev
-
+ - name: Install SDL2 and libcurl
+ run: sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" && sudo apt-get update -y -qq && sudo apt-get install libsdl2-dev && sudo apt-get install libcurl4-openssl-dev
+
- name: Run tests for Linux
run: pio test -e linux --json-output-path linux-test-report.json --junit-output-path linux-test-report.xml
diff --git a/README.md b/README.md
index fa0f8818..12f8fd2f 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,162 @@
-# PaxOS 9
+# Build Instructions
-![logo](https://github.com/paxo-phone/PaxOS-9/assets/45568523/ddb3b517-605c-41b4-8c1e-c8e5d156431b)
+If you are using CLion, please use the [CLion Instructions](#clion-instructions).
[![PlatformIO CI](https://github.com/paxo-phone/PaxOS-9/actions/workflows/platformio-ci.yml/badge.svg)](https://github.com/paxo-phone/PaxOS-9/actions/workflows/platformio-ci.yml)
-**PaxOS 9** est la dernière version du **PaxOS**, un système d'exploitation léger destiné aux PaxoPhones.
+### Install PlatformIO Core
-- [Licence](#licence)
-- [Contact](#contact)
-- [En savoir plus](#see-more)
-- [Contributeurs](#contributors)
+> https://docs.platformio.org/en/latest/core/installation/methods/installer-script.html#local-download-macos-linux-windows
-# Licence
-Ce projet est distribué sous licence AGPL-3.0.
+> https://docs.platformio.org/en/latest/core/installation/shell-commands.html#piocore-install-shell-commands
-# Contact
+### Install SDL2
-Vous pouvez nous contacter via notre [site internet](https://www.paxo.fr) ou notre [serveur Discord](https://discord.com/invite/MpqbWr3pUG).
+_(If you are on Windows, skip this step)_
-# En savoir plus
-En savoir plus sur [paxo.fr](https://www.paxo.fr)
+```shell
+# for linux
+sudo apt-get install libsdl2-dev
+# for macos using homebrew
+brew install sdl2
+```
-# Contributeurs
+### Install libcurl
-
-
-
+_(If you are on Windows, skip this step)_
+
+
+```shell
+# for linux
+sudo apt-get install libcurl4-openssl-dev
+# for macos using homebrew
+brew install curl
+```
+
+## Clone the repository
+
+```shell
+git clone https://github.com/paxo-phone/PaxOS-9.git
+```
+
+## Initialize the project
+
+```shell
+pio project init
+```
+
+## Build
+
+```shell
+# Build for ESP32
+pio run -e esp32dev
+
+# Build for Windows
+pio run -e windows
+
+# Build for Linux
+pio run -e linux
+
+# Build for MacOS
+pio run -e macos
+```
+
+## Run on ESP32
+
+```shell
+pio run -t upload -e esp32dev
+```
+
+## Run Tests
+
+```shell
+pio test -e test
+```
+
+## Troubleshooting
+
+### macOS
+- If you get a popup saying that the program is from an unidentified developer, do `xattr -d com.apple.quarantine program` in the same directory as the `program`.
+- If no program is launching at the end of the build when calling `pio run -e macos`, try to run the executable using `.pio/build/macos/program`.
+- If you get an error similar to
+ ```
+ dyld[xxxxx]: Library not loaded: @rpath/libSDL2-2.0.0.dylib
+ Referenced from: /Users/username/PaxOS-9/.pio/build/macos/program
+ Reason: no LC_RPATH's found
+ zsh: abort .pio/build/macos/program
+ ```
+ Try to do ```DYLD_LIBRARY_PATH="`brew --prefix sdl2`/lib" .pio/build/macos/program``` and if it still doesn't work and you haven't installed SDL2 locally as decribed in the next bullet point (otherwise run ```DYLD_LIBRARY_PATH="`eval echo ~$USER`/sdl2/lib" .pio/build/macos/program```) do:
+ 1. Get the location of SDL's dynamic library by executing `brew info sdl2`, you should get a path similar to `/opt/homebrew/Cellar/sdl2/2.28.5`
+ 2. Run `ls {the path you got from the last command}/lib/libSDL2-2.0.0.dylib`. If you get the exact same path as an output you're ready to go. Otherwise install SDL as described above in this document and retry the procedure.
+ 3. Re-run the command by adding `DYLD_LIBRARY_PATH="{the path you got from step 1}/lib/"` as a prefix before the command like this `DYLD_LIBRARY_PATH="{the path you got from step 1}/lib/ .pio/build/macos/program`
+- When compiling the project using pio you might encounter an error where your shell can't find `pio` even if you installed it via the quick-setup. To fix that, execute `pio` directly from the binaries path that is located at `/Users/username/.platformio/penv/bin/pio`. If you have PaxOS9 installed directly in your home (i.e. `/Users/username/PaxOS9`), run pio via `../.platformio/penv/bin/pio`. To build for macOS it would give something similar this `../.platformio/penv/bin/pio run -e macos`.
+- If you get the `unknown platform` error when compiling, that probalby means that SDL2 is not installed where it should or even just not installed at all. If you have admin permissions for your machine run `brew install sdl2`. If you don't, then install SDL2 locally by following those steps:
+ 1. Execute the following command (don't worry it won't hack into your computer)
+ ```
+ cd `eval echo ~$USER` && rm -rf sdl2-build && rm -rf sdl2 && mkdir sdl2 && git clone https://github.com/libsdl-org/SDL.git -b SDL2 sdl2-build && cd sdl2-build && mkdir build && cd build && ../configure --prefix=`eval echo ~$USER`/sdl2 && make -j`sysctl -n hw.ncpu` && make install && cd `eval echo ~$USER` && rm -rf sdl2-build && echo "Installed SDL at `eval echo ~$USER`/sdl2" && echo "\033[0;32mThe two lines to add to the macos target (\033[1;34mbuild_flags\033[0;32m) of the \033[1;34mplatform.ini\033[0;32m in your PaxOS9 directory are \033[1;33m-I`eval echo ~$USER`/sdl2/include\033[0;32m and \033[1;33m-L`eval echo ~$USER`/sdl2/lib\033[0;32m"
+ ```
+ 2. Follow the instructions that the command gave you (add the two lines). The place where you should put the lines looks like this (the filename is called `platform.ini` and is present in the `PaxOS9` directory):
+ ```
+ [env:macos]
+ platform = native
+ lib_deps =
+ x
+ x
+ x
+ test_framework = googletest
+ build_flags =
+ x
+ x
+ x
+ x
+ -I/opt/homebrew/include/SDL2
+ -L/opt/homebrew/lib
+ -->PLACE THE LINES SEPARATED BY A NEW LINE HERE <--
+ ```
+
+# CLion Instructions
+
+## Install dependencies
+
+### Install PlatformIO plugin
+
+* Launch CLion
+* Install the ``PlatformIO for CLion`` Plugin by ``JetBrains``
+* Restart the IDE
+
+### Install MinGW-w64
+
+Even if CLion comes with a full MinGW installation.\
+This is required by PlatformIO, because it uses ``g++`` for compilation.\
+You _may_ want to try to add the CLion's MinGW installation to Path, but it's not recommended.
+
+* Go to https://winlibs.com/
+* Select the ``Zip archive`` for ``GCC 13.2.0 (with POSIX threads) + LLVM/Clang/LLD/LLDB 17.0.6 + MinGW-w64 11.0.1 (UCRT) - release 4`` for ``Win64``, or [direct download](https://github.com/brechtsanders/winlibs_mingw/releases/download/13.2.0posix-17.0.6-11.0.1-ucrt-r4/winlibs-x86_64-posix-seh-gcc-13.2.0-llvm-17.0.6-mingw-w64ucrt-11.0.1-r4.zip)
+* Extract it in ``C:\mingw64`` (So you have the ``bin`` folder at ``C:\mingw64\bin``)
+* Add ``C:\mingw64\bin`` to your PATH
+
+## Clone the repository
+
+* On the ``Welcome to CLion`` window, select ``Get from VCS`` (or go to ``File -> New -> Project from Version Control...``)
+* Enter the repository URL (``https://github.com/paxo-phone/PaxOS-9.git``)
+* Open the project as a ``PlatformIO`` project, not ``CMake`` (this step is very important)
+* Wait the IDE to import the project (this can take several minutes)
+
+## Build
+
+Don't forget to re-build the project before running it,\
+you can get weird behaviors by not doing so.
+
+* Select the correct target
+* Click the ``Build`` button
+
+## Run on ESP32
+
+* Select the ``esp32dev`` target
+* Click on the ``Run`` button _(don't forget to build before)_
+
+## Run Tests
+
+* Select the ``test`` target
+* Click on the ``Run`` button _(don't forget to build before)_
diff --git a/lib/applications/src/app.hpp b/lib/applications/src/app.hpp
index b04fab14..e0452514 100644
--- a/lib/applications/src/app.hpp
+++ b/lib/applications/src/app.hpp
@@ -144,4 +144,4 @@ namespace AppManager
#include
-#endif
\ No newline at end of file
+#endif
diff --git a/lib/backtrace/src/backtrace.cpp b/lib/backtrace/src/backtrace.cpp
index 42c34e27..c26103b5 100644
--- a/lib/backtrace/src/backtrace.cpp
+++ b/lib/backtrace/src/backtrace.cpp
@@ -52,7 +52,7 @@ namespace backtrace_saver {
}
- re_restart_debug_t getCurrentBacktrace()
+ /*re_restart_debug_t getCurrentBacktrace()
{
re_restart_debug_t oldData = _debug_info;
debugUpdate();
@@ -62,7 +62,7 @@ namespace backtrace_saver {
_debug_info = oldData;
return returnData;
- }
+ }*/
bool saveBacktrace()
{
diff --git a/lib/backtrace/src/backtrace.hpp b/lib/backtrace/src/backtrace.hpp
index 0c829a0c..d9d6c6ff 100644
--- a/lib/backtrace/src/backtrace.hpp
+++ b/lib/backtrace/src/backtrace.hpp
@@ -19,8 +19,6 @@ namespace backtrace_saver {
std::string getBacktraceMessage();
- backtrace_saver::re_restart_debug_t getCurrentBacktrace();
-
bool saveBacktrace();
void backtraceMessageGUI();
diff --git a/lib/gsm/src/gsm.cpp b/lib/gsm/src/gsm.cpp
index 9e803659..8dec79e2 100644
--- a/lib/gsm/src/gsm.cpp
+++ b/lib/gsm/src/gsm.cpp
@@ -1144,6 +1144,9 @@ namespace GSM
if(o.find("+CSQ:") != std::string::npos)
{
networkQuality = atoi(o.substr(o.find("+CSQ: ") + 5, o.find(",") - o.find("+CSQ: ") - 5).c_str());
+ } else
+ {
+ networkQuality = 0;
}
//std::cout << "networkQuality: " << networkQuality << std::endl;
}
@@ -1201,7 +1204,7 @@ namespace GSM
keys.push_back({"+CMTI:", &GSM::onMessage});
keys.push_back({"VOICE CALL: END", &GSM::onHangOff});
keys.push_back({"VOICE CALL: BEGIN", [](){ state.callState = CallState::CALLING; }});
- keys.push_back({"+HTTPACTION: ", &GSM::HttpRequest::received});
+ keys.push_back({"+HTTPACTION: ", &GSM::handleIncomingResponse});
coresync.lock();
@@ -1221,7 +1224,7 @@ namespace GSM
data = "";
checkRequest();
- HttpRequest::manage();
+ requestsLoopCycle();
}
}
};
diff --git a/lib/gsm/src/gsm.hpp b/lib/gsm/src/gsm.hpp
index 37f96c77..d5cef224 100644
--- a/lib/gsm/src/gsm.hpp
+++ b/lib/gsm/src/gsm.hpp
@@ -6,6 +6,8 @@
#include
#include
#include
+#include
+#include
#define BAUDRATE 921600
@@ -127,57 +129,22 @@ namespace GSM
// set flight mode
void setFlightMode(bool mode);
+
// Network
- struct HttpHeader
- {
- enum Method
- {
- GET,
- POST
- };
-
- std::string url;
- Method httpMethod;
- std::string body;
- };
- class HttpRequest // todo add a timeout if the callback is never called + add inner buffer for 2 cores requests
- {
- public:
- HttpRequest(HttpHeader header);
- ~HttpRequest();
+ extern std::shared_ptr currentRequest;
- void send(std::function callback); // return callback
+ extern std::vector> hTTPRequests;
- HttpHeader header;
- size_t readChunk(char* buffer);
- void close();
-
- enum RequestState
- {
- SETUP, // the data is set up
- WAITING, // waiting for the system to send the request
- SENT, // the request has been sent, wait for the result
- RECEIVED, // the request has been received, waiting for the callback to read
- END,
- ENDED // the request has ended, need to be deleted
- };
-
- RequestState state = RequestState::SETUP;
- std::function callback;
-
- static std::vector requests;
- static HttpRequest* currentRequest;
- static void manage();
- static void received();
-
- private:
- uint64_t dataSize = 0;
- uint64_t timeout = 0; // date at which the request will timeout
- uint64_t readed = 0;
-
- void fastKill(uint8_t code = 400);
- };
+ void requestsLoopCycle();
+
+ void sendRequest(std::shared_ptr request);
+
+ void handleIncomingResponse();
+
+ size_t readResponseDataChunk(char* buffer);
+
+ void closeRequest(uint16_t code);
std::string getCurrentTimestamp(); // return the current timestamp formated
std::string getCurrentTimestampNoSpaces(); // return the current timestamp formated without spaces
diff --git a/lib/gsm/src/gsm_network.cpp b/lib/gsm/src/gsm_network.cpp
index 41d0566d..8017aa8a 100644
--- a/lib/gsm/src/gsm_network.cpp
+++ b/lib/gsm/src/gsm_network.cpp
@@ -1,4 +1,5 @@
#include "gsm.hpp"
+#include
#include
#include
@@ -8,48 +9,46 @@
namespace GSM
{
- std::vector HttpRequest::requests;
- HttpRequest* HttpRequest::currentRequest = nullptr;
+ std::shared_ptr currentRequest = nullptr;
+ std::vector> hTTPRequests;
- HttpRequest::HttpRequest(HttpHeader header) : header(header)
+ void sendRequest(std::shared_ptr request)
{
- }
+ hTTPRequests.push_back(request);
+ request->state = network::URLSessionDataTask::State::Waiting;
- HttpRequest::~HttpRequest()
- {
- close();
+ request->updateTimeout();
}
- void HttpRequest::send(std::function callback)
+ size_t readResponseDataChunk(char* buffer) // read a single chunk of 1024 bytes
{
- if(callback == nullptr)
- {
- state = RequestState::ENDED;
- }
-
- requests.push_back(this);
+ std::cout << "---1" << std::endl;
+ if (currentRequest.get() == nullptr && currentRequest->response != std::nullopt)
+ return 0;
- state = RequestState::WAITING;
- timeout = millis() + 10000;
- this->callback = callback;
- }
+ std::cout << "---2" << std::endl;
- size_t HttpRequest::readChunk(char* buffer) // read a single chunk of 1024 bytes
- {
- if(state != RequestState::RECEIVED)
+ if(currentRequest->state != network::URLSessionDataTask::State::ResponseReceived)
return 0;
+ std::cout << "---3" << std::endl;
+
+ network::URLResponse requestResponse = currentRequest->response.value();
+
#ifdef ESP_PLATFORM
- timeout = millis() + 10000;
+ currentRequest->updateTimeout();
GSM::coresync.lock();
uint64_t timer = millis(); // pour le timeout
- uint64_t timeout_block = 3000; // timeout de 1 secondes
+ uint64_t timeout_block = 3000; // timeout de 3 secondes
+
+ uint64_t nextBlockSize = std::min(uint64_t(1024), requestResponse.responseBodySize - requestResponse.readPosition);
- uint64_t nextBlockSize = std::min(uint64_t(1024), dataSize - readed);
+ std::cout << "---4" << std::endl;
- //std::cout << "Reading chunk: " << nextBlockSize << std::endl;
+ download();
+ std::cout << "Reading chunk: " << nextBlockSize << std::endl;
gsm.println("AT+HTTPREAD=0,1024\r");
@@ -65,7 +64,9 @@ namespace GSM
{
std::cout << "Timeout" << std::endl;
nextBlockSize = 0;
- close();
+ GSM::coresync.unlock();
+ closeRequest(705);
+ return 0;
}
else
{
@@ -74,15 +75,20 @@ namespace GSM
GSM::data += gsm.readString().c_str();
- //std::cout << "Chunk readed" << std::endl;
+ std::cout << "Chunk readed" << std::endl;
- readed += nextBlockSize;
+ requestResponse.readPosition += nextBlockSize;
- if (readed == dataSize)
+ if (requestResponse.readPosition == requestResponse.responseBodySize)
{
- close();
+ GSM::coresync.unlock();
+ currentRequest->response = std::make_optional(requestResponse);
+ closeRequest(requestResponse.statusCode); // response code is not important here as the response has already been handled
+ return nextBlockSize;
}
+ currentRequest->response = std::make_optional(requestResponse);
+
GSM::coresync.unlock();
return nextBlockSize;
@@ -91,108 +97,112 @@ namespace GSM
return 0;
}
- void HttpRequest::close()
- {
- if(state == RequestState::ENDED)
- return;
-
- GSM::send("AT+HTTPTERM", "AT+HTTPTERM", 1000);
-
- state = RequestState::ENDED;
- requests.erase(std::remove(requests.begin(), requests.end(), this), requests.end());
- }
-
- void HttpRequest::fastKill(uint8_t code)
- {
- close();
- callback(code, 0);
+ void closeRequest(uint16_t code)
+ {
+ if (currentRequest.get() != nullptr)
+ {
+ if (currentRequest->state != network::URLSessionDataTask::State::Finished && currentRequest->state != network::URLSessionDataTask::State::Waiting)
+ {
+ // request already sent, we need to close it
+ GSM::send("AT+HTTPTERM", "AT+HTTPTERM", 1000);
+ currentRequest->state = network::URLSessionDataTask::State::Finished;
+ } else if (currentRequest->state == network::URLSessionDataTask::State::Waiting) {
+ // request has not been sent yet
+ currentRequest->state = network::URLSessionDataTask::State::Finished;
+ }
+ hTTPRequests.erase(std::remove(hTTPRequests.begin(), hTTPRequests.end(), currentRequest), hTTPRequests.end());
+ currentRequest->handleResponse(code, 0); // handle the response if it has not been done yet
+ currentRequest = nullptr;
+ }
}
- void HttpRequest::manage()
+ void requestsLoopCycle()
{
- if(currentRequest == nullptr)
+ if(GSM::currentRequest.get() == nullptr)
{
- for (uint8_t i = 0; i < requests.size(); i++)
+ for (uint8_t i = 0; i < hTTPRequests.size(); i++)
{
- if(requests[i]->state == HttpRequest::RequestState::WAITING)
+ if(hTTPRequests[i]->state == network::URLSessionDataTask::State::Waiting)
{
- currentRequest = requests[i];
+ currentRequest = hTTPRequests[i];
break;
}
}
}
- if(currentRequest != nullptr)
+ if(GSM::currentRequest.get() != nullptr)
{
switch (currentRequest->state)
{
- case HttpRequest::RequestState::WAITING:
- if(GSM::send("AT+HTTPINIT", "AT+HTTPINIT", 500).find("OK") == std::string::npos) // setup http
+ case network::URLSessionDataTask::State::Waiting: // request should be sent
{
- currentRequest->fastKill();
- break;
- }
- else
- {
- if(currentRequest->header.httpMethod == HttpHeader::Method::GET)
+ std::string o = GSM::send("AT+HTTPINIT", "AT+HTTPINIT", 1000);
+ currentRequest->state = network::URLSessionDataTask::State::Running;
+ if(currentRequest->isOverTimeout()) // setup http
+ {
+ closeRequest(708); // timout exceeded
+ break;
+ }
+ else
{
- GSM::send("AT+HTTPPARA=\"URL\",\"" + currentRequest->header.url + "\"\r", "AT+HTTPPARA", 500);
- if(GSM::send("AT+HTTPACTION=0", "AT+HTTPACTION", 5000).find("OK") == std::string::npos)
+ if(currentRequest->request.method == network::URLRequest::HTTPMethod::GET)
{
- currentRequest->fastKill();
- break;
+ GSM::send("AT+HTTPPARA=\"URL\",\"" + currentRequest->request.url.absoluteString + "\"\r", "AT+HTTPPARA", 500);
+ if(GSM::send("AT+HTTPACTION=0", "AT+HTTPACTION", 5000).find("OK") == std::string::npos)
+ {
+ closeRequest(706);
+ break;
+ }
}
- }
- else if(currentRequest->header.httpMethod == HttpHeader::Method::POST)
- {
- // Set URL for POST request
- GSM::send("AT+HTTPPARA=\"URL\",\"" + currentRequest->header.url + "\"\r", "AT+HTTPPARA", 500);
-
- // Set content type (assuming JSON, adjust if needed)
- GSM::send("AT+HTTPPARA=\"CONTENT\",\"application/json\"\r", "AT+HTTPPARA", 500);
-
- // Prepare to send data
- int dataLength = currentRequest->header.body.length();
- GSM::send("AT+HTTPDATA=" + std::to_string(dataLength) + ",10000", "DOWNLOAD", 1000);
-
- // Send the actual POST data
- GSM::send(currentRequest->header.body, "OK", 500 + dataLength * 8 * BAUDRATE); // wait for the full data transfer
-
- // Perform POST action
- if(GSM::send("AT+HTTPACTION=1", "AT+HTTPACTION", 5000).find("OK") == std::string::npos)
+ else if(currentRequest->request.method == network::URLRequest::HTTPMethod::POST)
{
- currentRequest->fastKill();
+ // Set URL for POST request
+ GSM::send("AT+HTTPPARA=\"URL\",\"" + currentRequest->request.url.absoluteString + "\"\r", "AT+HTTPPARA", 500);
+
+ // Set content type (assuming JSON, adjust if needed)
+ GSM::send("AT+HTTPPARA=\"CONTENT\",\"application/json\"\r", "AT+HTTPPARA", 500);
+
+ // Prepare to send data
+ int dataLength = currentRequest->request.httpBody.length();
+ GSM::send("AT+HTTPDATA=" + std::to_string(dataLength) + ",10000", "DOWNLOAD", 1000);
+
+ // Send the actual POST data
+ GSM::send(currentRequest->request.httpBody, "OK", 500 + dataLength * 8 * BAUDRATE); // wait for the full data transfer
+
+ // Perform POST action
+ if((GSM::send("AT+HTTPACTION=1", "AT+HTTPACTION", 5000)).find("OK") == std::string::npos)
+ {
+ closeRequest(707);
+ break;
+ }
+ } else {
+ closeRequest(704); // unsupported method
break;
}
- }
- currentRequest->state = HttpRequest::RequestState::SENT;
- }
-
- break;
- case HttpRequest::RequestState::SENT:
- // let the key be received
- if(millis() > currentRequest->timeout)
- {
- currentRequest->fastKill(504);
+ currentRequest->updateTimeout();
+ }
}
break;
- case HttpRequest::RequestState::RECEIVED:
+ case network::URLSessionDataTask::State::Paused: // TODO? but as the simcom can handle only 1 request at a time it might not be useful
+ case network::URLSessionDataTask::State::Running:
+ case network::URLSessionDataTask::State::ResponseReceived:
// let the app read the data
- if(millis() > currentRequest->timeout)
+ if(currentRequest->isOverTimeout())
{
- currentRequest->close();
- break;
+ closeRequest(708);
}
break;
- case HttpRequest::RequestState::END:
- currentRequest = nullptr;
+ case network::URLSessionDataTask::State::Cancelled:
+ case network::URLSessionDataTask::State::Finished:
+ closeRequest(709); // should happen rarely as the request should have already been removed from the list
break;
+
}
}
}
- void HttpRequest::received()
+ void handleIncomingResponse()
{
std::regex pattern(".*\\+HTTPACTION: (\\d+),(\\d+),(\\d+)\\r\\n.*");
std::smatch match;
@@ -203,14 +213,15 @@ namespace GSM
int status = std::stoi(match[2].str());
int size = std::stoi(match[3].str());
+ std::cout << data << std::endl;
+
std::cout << "action: " << action << " status: " << status << " size: " << size << std::endl;
- if(currentRequest != nullptr)
+ if(currentRequest.get() != nullptr)
{
- currentRequest->state = RequestState::RECEIVED;
- currentRequest->dataSize = size;
- currentRequest->timeout = millis() + 10000;
- currentRequest->callback(status, size);
+ currentRequest->updateTimeout();
+ //currentRequest->handleResponse(status, size);
+ eventHandlerApp.setTimeout(new Callback<>(std::bind(&network::URLSessionDataTask::handleResponse, currentRequest, status, size)), 0);
}
}
}
diff --git a/lib/network/README.md b/lib/network/README.md
index e69de29b..153fc617 100644
--- a/lib/network/README.md
+++ b/lib/network/README.md
@@ -0,0 +1,73 @@
+Based on Swift's Networking Foundation
+
+class URLSession {
+ URLSession defaultInstance;
+
+ URLSession();
+ // URLSession(URLSessionConfiguration sessionWithConfiguration);
+
+ // URLSessionConfiguration configuration; -> donnerait les configs de base des tasks sans URLRequest mais juste URL
+
+ (URLSessionDataTask *) dataTaskWithURL(URL url, (void (^)(Data *data, URLResponse *response, Error *error)), completionHandler);
+ (URLSessionDataTask *) dataTaskWithRequest(URLRequest request, (void (^)(Data *data, URLResponse *response, Error *error)), completionHandler);
+
+
+ (URLSessionDownloadTask *) downloadTaskWithURL(URL url, (void (^)(URL location, URLResponse *response, Error *error)) completionHandler);
+ (URLSessionDownloadTask *) downloadTaskWithRequest(URLRequest request, (void (^)(URL *location, URLResponse *response, Error *error)) completionHandler);
+
+
+ (URLSessionUploadTask *) uploadTaskWithRequest(URLRequest request, Data *bodyData, (void (^)(Data *data, URLResponse *response, Error *error)) completionHandler);
+ (URLSessionUploadTask *) uploadTaskFromFileWithRequest(URLRequest request, URL fileURL, (void (^)(Data *data, URLResponse *response, Error *error)) completionHandler);
+
+
+ (URLSessionWebSocketTask *) webSocketTaskWithURL(URL url); // avec des closure delegate en plus
+ (URLSessionWebSocketTask *) webSocketTaskWithRequest(URLRequest request); // avec des closure delegate en plus
+
+ vector getAllTasks();
+}
+
+struct URLRequest {
+ URLRequest(URL url, HTTPMethod httpMethod = GET, Data* httpBody = nullptr) // et le reste peut être set avec des options
+
+ HTTPMethod httpMethod;
+
+ URL url;
+
+ Data* httpBody;
+
+ map allHTTPHeaderFields;
+
+ uint64_t timeoutInterval;
+
+ enum HTTPMethod {
+ GET, POST, PUT, DELETE
+ }
+}
+
+virtual class URLSessionTask {
+ void cancel();
+
+ void resume();
+
+ void suspend();
+
+ State state;
+
+ double progress; // y'aura aussi des callbacks pour observer ça
+
+ uint64_t countOfBytesReceived;
+
+ uint64_t countOfBytesExpectedToSend;
+
+ enum State {
+ running, suspended, cancelling, completed
+ }
+}
+
+Pour ce qui est des URLSessionDataTask, URLSessionDownloadTask, URLSessionUploadTask et URLSessionWebSocketTask qui sont toutes dérivées de URLSessionTask, elles ont des callbacks en plus de base en fonction de ce qu'elles font.
+
+
+
+
+
+
diff --git a/lib/network/network.hpp b/lib/network/network.hpp
index e69de29b..4ab482d8 100644
--- a/lib/network/network.hpp
+++ b/lib/network/network.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "src/NetworkManager.hpp"
+#include "src/URL.hpp"
+#include "src/URLRequest.hpp"
+#include "src/URLResponse.hpp"
+#include "src/URLSession.hpp"
+#include "src/URLSessionDataTask.hpp"
+#include "src/URLSessionTask.hpp"
\ No newline at end of file
diff --git a/lib/network/src/NetworkManager.cpp b/lib/network/src/NetworkManager.cpp
new file mode 100644
index 00000000..c2210a82
--- /dev/null
+++ b/lib/network/src/NetworkManager.cpp
@@ -0,0 +1,103 @@
+#include "NetworkManager.hpp"
+
+#ifdef ESP_PLATFORM
+ #include
+#endif
+#include
+#include
+#include
+
+#include
+
+namespace network
+{
+ std::shared_ptr NetworkManager::sharedInstance/* = std::make_shared()*/;
+
+ void init()
+ {
+ NetworkManager::sharedInstance = std::make_shared();
+ URLSession::defaultInstance = std::make_shared();
+ }
+
+ NetworkManager::NetworkManager()
+ {
+ #ifdef ESP_PLATFORM
+ this->turnOFFWiFi();
+ #endif
+ curl_global_init(CURL_GLOBAL_ALL);
+ }
+
+ const void NetworkManager::connectToWiFi(const std::string& ssid)
+ {
+ #ifdef ESP_PLATFORM
+ WiFi.begin(ssid.c_str());
+ #endif
+ }
+
+ const void NetworkManager::connectToWiFi(const std::string& ssid, const std::string& password)
+ {
+ #ifdef ESP_PLATFORM
+ WiFi.begin(ssid.c_str(), password.c_str());
+ #endif
+ }
+
+ const void NetworkManager::disconnectWiFi(void)
+ {
+ #ifdef ESP_PLATFORM
+ WiFi.disconnect();
+ #endif
+ }
+
+ const void NetworkManager::turnOFFWiFi(void)
+ {
+ #ifdef ESP_PLATFORM
+ WiFi.mode(WIFI_OFF);
+ #endif
+ }
+
+ const void NetworkManager::turnONWiFi(void)
+ {
+ #ifdef ESP_PLATFORM
+ WiFi.mode(WIFI_STA);
+ #endif
+ }
+
+ const std::string NetworkManager::currentWiFiSSID()
+ {
+ #ifdef ESP_PLATFORM
+ return WiFi.SSID().c_str();
+ #else
+ return "";
+ #endif
+ }
+
+ const bool NetworkManager::isConnected()
+ {
+ return this->isWiFiConnected() || this->isGSMConnected();
+ }
+
+ const bool NetworkManager::isWiFiConnected()
+ {
+ #ifdef ESP_PLATFORM
+ return WiFi.status() == WL_CONNECTED;
+ #else
+ int pingExitCode = system("ping -c1 -s1 8.8.8.8 > /dev/null 2>&1"); // ping Google's DNS server and return the exit code
+ if (pingExitCode == 0)
+ {
+ return true;
+ } else
+ {
+ return false;
+ }
+ #endif
+ }
+
+ const bool NetworkManager::isGSMConnected()
+ {
+ #ifdef ESP_PLATFORM
+ return GSM::getNetworkStatus() > 0;
+ #else
+ return false;
+ #endif
+ }
+}
\ No newline at end of file
diff --git a/lib/network/src/NetworkManager.hpp b/lib/network/src/NetworkManager.hpp
new file mode 100644
index 00000000..aa45dc05
--- /dev/null
+++ b/lib/network/src/NetworkManager.hpp
@@ -0,0 +1,41 @@
+#ifndef NETWORKMANAGER_HPP
+#define NETWORKMANAGER_HPP
+
+#include
+#include
+#include
+
+namespace network
+{
+ void init ();
+
+ class NetworkManager
+ {
+ public:
+ NetworkManager();
+
+ static std::shared_ptr sharedInstance;
+
+ const void connectToWiFi(const std::string& ssid);
+
+ const void connectToWiFi(const std::string& ssid, const std::string& passwd);
+
+ const void disconnectWiFi();
+
+ const void turnOFFWiFi();
+
+ const void turnONWiFi();
+
+ const std::string currentWiFiSSID();
+
+ const bool isConnected();
+
+ const bool isWiFiConnected();
+
+ const bool isGSMConnected();
+
+ private:
+ };
+}
+
+#endif // NETWORKMANAGER_HPP
\ No newline at end of file
diff --git a/lib/network/src/ProgressHandler.hpp b/lib/network/src/ProgressHandler.hpp
new file mode 100644
index 00000000..24c9fc8c
--- /dev/null
+++ b/lib/network/src/ProgressHandler.hpp
@@ -0,0 +1,11 @@
+#ifndef PROGRESSHANDLER_HPP
+#define PROGRESSHANDLER_HPP
+
+#include
+
+namespace network
+{
+ typedef std::function ProgressHandler;
+}
+
+#endif // PROGRESSHANDLER_HPP
\ No newline at end of file
diff --git a/lib/network/src/URL.cpp b/lib/network/src/URL.cpp
new file mode 100644
index 00000000..b609bc61
--- /dev/null
+++ b/lib/network/src/URL.cpp
@@ -0,0 +1,14 @@
+#include "URL.hpp"
+
+#include
+
+
+namespace network
+{
+ URL::URL(const std::string& string) : absoluteString(string) {}
+
+ bool URL::isValid() const
+ {
+ return std::regex_match(absoluteString, std::regex("([a-zA-Z]+)://([^/ :]+)(:([0-9]+))?(/([^ #?]+)?([^ #]+)?)?"));
+ }
+}
\ No newline at end of file
diff --git a/lib/network/src/URL.hpp b/lib/network/src/URL.hpp
new file mode 100644
index 00000000..69cdcf5d
--- /dev/null
+++ b/lib/network/src/URL.hpp
@@ -0,0 +1,18 @@
+#ifndef URL_HPP
+#define URL_HPP
+
+#include
+
+namespace network
+{
+ struct URL
+ {
+ URL(const std::string& string);
+
+ const std::string absoluteString;
+
+ bool isValid() const;
+ };
+}
+
+#endif // URL_HPP
\ No newline at end of file
diff --git a/lib/network/src/URLRequest.hpp b/lib/network/src/URLRequest.hpp
new file mode 100644
index 00000000..997a57e0
--- /dev/null
+++ b/lib/network/src/URLRequest.hpp
@@ -0,0 +1,32 @@
+#ifndef URLREQUEST_HPP
+#define URLREQUEST_HPP
+
+#include