Création du module DolibarrClient avec ses différentes routes & création du module WarehouseGUI pour le LCD M5Stack #7
4
.env.example
Normal file
4
.env.example
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TIME_ZONE='Europe/Paris'
|
||||||
|
DOLI_URL='http://0.0.0.0'
|
||||||
|
DB_NAME="dolibarr"
|
||||||
|
DB_PASS="password"
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,6 +7,8 @@
|
|||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
|
.idea/
|
||||||
|
|
||||||
# Aptatio/Platformio specifics
|
# Aptatio/Platformio specifics
|
||||||
secrets.ini
|
secrets.ini
|
||||||
|
.env
|
||||||
|
@ -13,7 +13,4 @@ build_flags =
|
|||||||
; DO NOT TOUCH --- START
|
; DO NOT TOUCH --- START
|
||||||
Nicolas marked this conversation as resolved
Outdated
|
|||||||
-D MONITOR_SPEED=${config.monitor_speed}
|
-D MONITOR_SPEED=${config.monitor_speed}
|
||||||
; DO NOT TOUCH --- END
|
; DO NOT TOUCH --- END
|
||||||
|
-D WAITING_WIFI_DELAY=1000
|
||||||
-D EXAMPLE_NUMBER=69
|
|
||||||
|
|
||||||
-D EXAMPLE_STRING=\"Pouet\"
|
|
||||||
|
10
config_api.ini
Normal file
10
config_api.ini
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[config_api]
|
||||||
|
build_flags =
|
||||||
|
-D API_LOGIN_URL=\"/users/info\"
|
||||||
|
-D API_LIST_PRODUCT_URL=\"/products/\"
|
||||||
|
-D API_GET_PRODUCT_URL=\"/products/{id}/\"
|
||||||
|
-D API_GET_PRODUCT_STOCK_URL=\"/products/{id}/stock/\"
|
||||||
|
-D API_LIST_WAREHOUSE_URL=\"/warehouses/\"
|
||||||
|
-D API_LIST_STOCKS_MOVEMENTS_URL=\"/stockmovements/?sortfield=t.rowid\"
|
||||||
|
-D API_CREATE_STOCKS_MOVEMENTS_URL=\"/stockmovements/\"
|
||||||
|
-D API_MAX_JSON_SIZE=4096
|
27
docker-compose.yml
Normal file
27
docker-compose.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
mariadb:
|
||||||
|
image: mariadb:latest
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${DB_PASS}
|
||||||
|
MYSQL_DATABASE: ${DB_NAME}
|
||||||
|
volumes:
|
||||||
|
- database:/var/lib/mysql
|
||||||
|
restart: always
|
||||||
|
web:
|
||||||
|
image: tuxgasy/dolibarr
|
||||||
|
environment:
|
||||||
|
DOLI_DB_HOST: mariadb
|
||||||
|
DOLI_DB_USER: root
|
||||||
|
DOLI_DB_PASSWORD: ${DB_PASS}
|
||||||
|
DOLI_DB_NAME: ${DB_NAME}
|
||||||
|
DOLI_URL_ROOT: ${DOLI_URL}
|
||||||
|
PHP_INI_DATE_TIMEZONE: ${TIME_ZONE}
|
||||||
|
restart: always
|
||||||
|
# ports:
|
||||||
|
# - "80:80"
|
||||||
|
depends_on:
|
||||||
|
- mariadb
|
||||||
|
volumes:
|
||||||
|
database:
|
@ -2,6 +2,8 @@
|
|||||||
#define PROGRAM_H
|
#define PROGRAM_H
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
Nicolas marked this conversation as resolved
Outdated
Clement
commented
deja inclue dans les config deja inclue dans les config
|
|||||||
|
#include "DolibarrClient.h"
|
||||||
|
#include <M5Stack.h>
|
||||||
|
|
||||||
class Program {
|
class Program {
|
||||||
public:
|
public:
|
||||||
@ -11,9 +13,11 @@ public:
|
|||||||
Program();
|
Program();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program main loop
|
* Program WarehouseGUI loop
|
||||||
*/
|
*/
|
||||||
void loop();
|
void loop();
|
||||||
|
private:
|
||||||
|
DolibarrClient *client;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
151
lib/DolibarrClient/src/DolibarrClient.cpp
Normal file
151
lib/DolibarrClient/src/DolibarrClient.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include "DolibarrClient.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
DolibarrClient::DolibarrClient(struct DolibarrConfig dolibarr_config) : dolibarr(dolibarr_config) {
|
||||||
Nicolas marked this conversation as resolved
Outdated
Clement
commented
mettre en config mettre en config
|
|||||||
|
#if defined(DEBUG)
|
||||||
|
Serial.println(" --- Dolibarr configuration --- ");
|
||||||
|
Serial.println((std::string("Base URL: ") + std::string(dolibarr_config.url)).c_str());
|
||||||
|
Serial.println((std::string("Token: ") + std::string(dolibarr_config.api_key)).c_str());
|
||||||
|
#endif
|
||||||
|
this->initialize_http_client();
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPClient *DolibarrClient::build_url(const String& url) const {
|
||||||
|
auto *client = new HTTPClient();
|
||||||
|
String clientUrl = this->dolibarr.url + url;
|
||||||
|
client->begin(clientUrl);
|
||||||
|
client->addHeader("Content-Type", "application/json");
|
||||||
|
client->addHeader("DOLAPIKEY", this->dolibarr.api_key);
|
||||||
|
#if defined(DEBUG)
|
||||||
|
Serial.println("URL Request: " + clientUrl);
|
||||||
|
#endif
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DolibarrClient::login() const {
|
||||||
|
HTTPClient *client = this->build_url(API_LOGIN_URL);
|
||||||
|
int httpResponseCode = client->GET();
|
||||||
|
if (httpResponseCode > 0) {
|
||||||
|
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
|
||||||
|
DeserializationError error = deserializeJson(doc, client->getString().c_str());
|
||||||
|
if (error) {
|
||||||
|
delete client;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
delete client;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
delete client;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
String replace_id(const char *str, const char *id) {
|
||||||
|
String url(str);
|
||||||
|
url.replace("{id}", id);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<models::Product> *DolibarrClient::list_products() const {
|
||||||
Nicolas marked this conversation as resolved
Clement
commented
utiliser les string d'Arduino utiliser les string d'Arduino
|
|||||||
|
HTTPClient *client = this->build_url(API_LIST_PRODUCT_URL);
|
||||||
|
if (client->GET() == HTTP_CODE_OK) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
models::Product *DolibarrClient::get_product_by_id(const char* id_product) const {
|
||||||
|
HTTPClient *client = this->build_url(replace_id(API_GET_PRODUCT_URL, id_product).c_str());
|
||||||
|
if (client->GET() == HTTP_CODE_OK) {
|
||||||
|
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
|
||||||
|
DeserializationError error = deserializeJson(doc, client->getString().c_str());
|
||||||
|
if (error) {
|
||||||
|
Serial.println("ERROR: ");
|
||||||
|
Serial.println(error.c_str());
|
||||||
|
delete client;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto *product = new models::Product();
|
||||||
|
product->date_creation = doc["date_creation"];
|
||||||
|
product->id = doc["id"];
|
||||||
|
product->entity = doc["entity"];
|
||||||
|
product->stock_reel = doc["stock_reel"];
|
||||||
|
product->label = doc["label"];
|
||||||
|
delete client;
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
delete client;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<models::Warehouse> *DolibarrClient::list_warehouse() const {
|
||||||
|
HTTPClient *client = this->build_url(API_LIST_WAREHOUSE_URL);
|
||||||
|
if (client->GET() == HTTP_CODE_OK) {
|
||||||
|
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
|
||||||
|
DeserializationError error = deserializeJson(doc, client->getString().c_str());
|
||||||
|
if (error) {
|
||||||
|
Serial.println("ERROR: ");
|
||||||
|
Serial.println(error.c_str());
|
||||||
|
delete client;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto *warehouses = new std::vector<models::Warehouse>();
|
||||||
|
for (auto obj : doc.as<JsonArray>()) {
|
||||||
|
models::Warehouse warehouse = {};
|
||||||
|
warehouse.id = obj["id"];
|
||||||
|
warehouses->push_back(warehouse);
|
||||||
|
}
|
||||||
|
delete client;
|
||||||
|
return warehouses;
|
||||||
|
}
|
||||||
|
delete client;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DolibarrClient::create_movement(models::CreateProductStock &stock) const {
|
||||||
|
HTTPClient *client = this->build_url("API_CREATE_STOCKS_MOVEMENTS_URL");
|
||||||
|
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
|
||||||
|
std::string result;
|
||||||
|
doc["product_id"] = stock.product_id;
|
||||||
|
doc["warehouse_id"] = stock.warehouse_id;
|
||||||
|
doc["qty"] = stock.qty;
|
||||||
|
serializeJson(doc, result);
|
||||||
|
Serial.println(result.c_str());
|
||||||
|
if (client->POST(result.c_str()) == HTTP_CODE_OK) {
|
||||||
|
delete client;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DolibarrClient::initialize_http_client() {
|
||||||
|
this->httpClient = new HTTPClient();
|
||||||
|
if (this->login() == 0) {
|
||||||
|
auto* product = this->get_product_by_id("1");
|
||||||
|
if (product == nullptr) {
|
||||||
|
Serial.println("Product is nullptr !");
|
||||||
|
return -1;
|
||||||
Nicolas marked this conversation as resolved
Clement
commented
faut pas faire sa dans le prog principal ? faut pas faire sa dans le prog principal ?
|
|||||||
|
}
|
||||||
|
Serial.println("Product label: ");
|
||||||
|
Serial.println(product->label);
|
||||||
|
auto* warehouses = this->list_warehouse();
|
||||||
|
if (warehouses == nullptr) {
|
||||||
|
delete product;
|
||||||
|
Serial.println("Warehouse is nullptr !");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Serial.println("Warehouses: ");
|
||||||
|
models::CreateProductStock product_stock = {product->id, warehouses->at(0).id, "1"};
|
||||||
|
this->create_movement(product_stock);
|
||||||
|
for (auto warehouse : *warehouses) {
|
||||||
|
Serial.println(warehouse.id);
|
||||||
|
}
|
||||||
|
delete product;
|
||||||
|
delete warehouses;
|
||||||
|
} else {
|
||||||
|
Serial.println("An Error has occurred while trying to login");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
35
lib/DolibarrClient/src/DolibarrClient.h
Normal file
35
lib/DolibarrClient/src/DolibarrClient.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef DOLIBARR_CLIENT_H
|
||||||
|
#define DOLIBARR_CLIENT_H
|
||||||
|
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "DolibarrModels.h"
|
||||||
|
|
||||||
|
struct WifiConfig {
|
||||||
|
const char* ssid;
|
||||||
|
const char* password;
|
||||||
|
};
|
||||||
|
|
||||||
Nicolas marked this conversation as resolved
Clement
commented
tout les constexpr les mettre dans les fichiers ini (env et config) tout les constexpr les mettre dans les fichiers ini (env et config)
|
|||||||
|
struct DolibarrConfig {
|
||||||
|
const char* url;
|
||||||
|
const char* api_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DolibarrClient {
|
||||||
|
public:
|
||||||
|
DolibarrClient(DolibarrConfig dolibarr_config);
|
||||||
|
~DolibarrClient() = default;
|
||||||
|
int login() const;
|
||||||
|
std::vector<models::Warehouse> *list_warehouse() const;
|
||||||
|
std::vector<models::Product> *list_products() const;
|
||||||
|
models::Product *get_product_by_id(const char* id_product) const;
|
||||||
|
int create_movement(models::CreateProductStock &stock) const;
|
||||||
|
private:
|
||||||
|
HTTPClient* httpClient{};
|
||||||
|
struct DolibarrConfig dolibarr;
|
||||||
|
int initialize_http_client();
|
||||||
|
HTTPClient *build_url(const String& url) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //DOLIBARR_CLIENT_H
|
40
lib/DolibarrClient/src/DolibarrModels.h
Normal file
40
lib/DolibarrClient/src/DolibarrModels.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef T_IOT_901_CONVOYOR_DOLIBARRMODELS_H
|
||||||
|
#define T_IOT_901_CONVOYOR_DOLIBARRMODELS_H
|
||||||
|
|
||||||
|
namespace models {
|
||||||
Nicolas marked this conversation as resolved
Clement
commented
je suis chaud que tu m'explique les namesapce j'ai jamais utiliser ;) je suis chaud que tu m'explique les namesapce j'ai jamais utiliser ;)
|
|||||||
|
|
||||||
|
struct Product {
|
||||||
|
const char* id;
|
||||||
|
const char* entity;
|
||||||
|
const char* ref;
|
||||||
|
const char* status;
|
||||||
|
const char* date_creation;
|
||||||
|
const char* date_modification;
|
||||||
|
const char* label;
|
||||||
|
const char* description;
|
||||||
|
const char* type;
|
||||||
|
const char* price;
|
||||||
|
const char* stock_reel;
|
||||||
|
const char* seuil_stock_alerte;
|
||||||
|
const char* desiredstock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProductStock {
|
||||||
|
const char* id;
|
||||||
|
const char* product_id;
|
||||||
|
const char* quantity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CreateProductStock {
|
||||||
|
const char* product_id;
|
||||||
|
const char* warehouse_id;
|
||||||
|
const char* qty;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Warehouse {
|
||||||
|
const char* id;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //T_IOT_901_CONVOYOR_DOLIBARRMODELS_H
|
@ -17,13 +17,14 @@ extra_configs =
|
|||||||
secrets.ini
|
secrets.ini
|
||||||
config.ini
|
config.ini
|
||||||
envs.ini
|
envs.ini
|
||||||
|
config_api.ini
|
||||||
|
|
||||||
; Cache folder
|
; Cache folder
|
||||||
build_cache_dir = ./.pio/cache
|
build_cache_dir = ./.pio/cache
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
; build Envs
|
; build Envs
|
||||||
build_flags = ${config.build_flags} ${secrets.build_flags}
|
build_flags = ${config.build_flags} ${secrets.build_flags} ${config_api.build_flags}
|
||||||
|
|
||||||
; Add scripts for more functionnalities
|
; Add scripts for more functionnalities
|
||||||
; see individual scripts for more informations
|
; see individual scripts for more informations
|
||||||
@ -50,6 +51,9 @@ upload_speed = 921600
|
|||||||
|
|
||||||
; librairies (make sure to fix versions where possible!)
|
; librairies (make sure to fix versions where possible!)
|
||||||
lib_deps =
|
lib_deps =
|
||||||
Nicolas marked this conversation as resolved
Outdated
Clement
commented
mettre un commentaire sur chaque ligne pour dire l'utilité de la lib mettre un commentaire sur chaque ligne pour dire l'utilité de la lib
|
|||||||
|
bblanchon/ArduinoJson@^6.21.3 ; JSON serializer et deserializer
|
||||||
|
m5stack/M5Stack@^0.4.5 ; M5 Lib
|
||||||
|
m5stack/M5GFX@^0.1.9 ; M5 Lib pour le LCD
|
||||||
; example:
|
; example:
|
||||||
; erropix/ESP32 AnalogWrite@0.2
|
; erropix/ESP32 AnalogWrite@0.2
|
||||||
|
|
||||||
|
@ -4,3 +4,8 @@
|
|||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-D WIFI_SSID=\"test\"
|
||||||
|
-D WIFI_PASSWORD=\"abcd1234\"
|
||||||
|
-D DOLIBARR_API_TOKEN=\"monapitokendedolibarr\"
|
||||||
|
-D DOLIBARR_URL=\"http://0.0.0.0/api/index.php\"
|
||||||
|
-D DEBUG=true
|
@ -1,10 +1,29 @@
|
|||||||
#include "Program.h"
|
#include "Program.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DolibarrClient.h"
|
||||||
|
|
||||||
|
int initialize_wifi(WifiConfig wifi) {
|
||||||
|
WiFiClass::mode(WIFI_STA); //Optional
|
||||||
|
WiFi.setSleep(false);
|
||||||
|
WiFi.begin(wifi.ssid, wifi.password);
|
||||||
|
Serial.print("Connecting ");
|
||||||
|
while(WiFiClass::status() != WL_CONNECTED){
|
||||||
|
delay(WAITING_WIFI_DELAY);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.println("Connected to the WiFi network");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Program::Program() {
|
Program::Program() {
|
||||||
// Startup
|
|
||||||
Serial.begin(MONITOR_SPEED);
|
Serial.begin(MONITOR_SPEED);
|
||||||
Nicolas marked this conversation as resolved
Outdated
Clement
commented
remettre le serial print comme c'était remettre le serial print comme c'était
|
|||||||
|
struct WifiConfig wifi_c = {WIFI_SSID, WIFI_PASSWORD};
|
||||||
|
struct DolibarrConfig dolibarr = {DOLIBARR_URL, DOLIBARR_API_TOKEN};
|
||||||
|
initialize_wifi(wifi_c);
|
||||||
|
this->client = new DolibarrClient(dolibarr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Program::loop() {
|
void Program::loop() {
|
||||||
// Loop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "Program.h"
|
#include "Program.h"
|
||||||
|
|
||||||
Program* program;
|
Program* program;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
10
test/dolibarr.cpp
Normal file
10
test/dolibarr.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <unity.h>
|
||||||
|
#include "DolibarrClient.h"
|
||||||
|
|
||||||
|
void test_construct_dolibarr_client() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_destroy_basic_state() {
|
||||||
|
return;
|
||||||
|
}
|
36
test/test.cpp
Normal file
36
test/test.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <M5Stack.h>
|
||||||
|
#include <unity.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
// set stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
// clean stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
int runUnityTests(void) {
|
||||||
|
UNITY_BEGIN();
|
||||||
|
RUN_TEST(test_construct_dolibarr_client);
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
return runUnityTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Arduino framework
|
||||||
|
void setup() {
|
||||||
|
// Wait ~2 seconds before the Unity test runner
|
||||||
|
// establishes connection with a board Serial interface
|
||||||
|
runUnityTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Arduino framework
|
||||||
|
void loop() {}
|
||||||
|
|
||||||
|
// For ESP-IDF framework
|
||||||
|
void app_main() {
|
||||||
|
runUnityTests();
|
||||||
|
}
|
6
test/test.h
Normal file
6
test/test.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef T_IOT_901_CONVOYOR_TEST_H
|
||||||
|
#define T_IOT_901_CONVOYOR_TEST_H
|
||||||
|
|
||||||
|
void test_construct_dolibarr_client();
|
||||||
|
|
||||||
|
#endif //T_IOT_901_CONVOYOR_TEST_H
|
Loading…
x
Reference in New Issue
Block a user
vraiment utile @Nicolas ?