Création du module DolibarrClient avec ses différentes routes & création du module WarehouseGUI pour le LCD M5Stack (#7)
Co-authored-by: Nicolas SANS <nicolas.sansd@gmail.com> Co-authored-by: Clement <c.boesmier@aptatio.com> Co-authored-by: Clement <clement@jo85.com> Reviewed-on: #7 Co-authored-by: Nicolas <nicolas.sansd@gmail.com> Co-committed-by: Nicolas <nicolas.sansd@gmail.com>
This commit is contained in:
parent
e4f009b63e
commit
88077f284e
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
|
||||||
-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"
|
||||||
|
#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) {
|
||||||
|
#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 {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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 =
|
||||||
|
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);
|
||||||
|
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