V2.0
440
CG_scale.ino
@ -4,11 +4,16 @@
|
|||||||
(c) 2019 by M. Lehmann
|
(c) 2019 by M. Lehmann
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#define CGSCALE_VERSION "1.2.1"
|
#define CGSCALE_VERSION "2.0"
|
||||||
/*
|
/*
|
||||||
|
|
||||||
******************************************************************
|
******************************************************************
|
||||||
history:
|
history:
|
||||||
|
V2.0 26.01.20 Webpage rewritten, no bootstrap framework needed
|
||||||
|
add translation to webpage (en, de)
|
||||||
|
optimized for measuring with landinggears
|
||||||
|
updated to ArduinoJson V6
|
||||||
|
firmware update over web interface
|
||||||
V1.2.1 31.03.19 small bug fixed
|
V1.2.1 31.03.19 small bug fixed
|
||||||
values in model database are rounded
|
values in model database are rounded
|
||||||
mDNS and OTA did not work in AP mode
|
mDNS and OTA did not work in AP mode
|
||||||
@ -24,7 +29,7 @@
|
|||||||
|
|
||||||
Software License Agreement (BSD License)
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
Copyright (c) 2019, Michael Lehmann
|
Copyright (c) 2019-2020, Michael Lehmann
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -64,9 +69,12 @@
|
|||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESP8266WebServer.h>
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
#include <ESP8266HTTPClient.h>
|
||||||
#include <ESP8266mDNS.h>
|
#include <ESP8266mDNS.h>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
|
#include <ESP8266HTTPUpdateServer.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -84,14 +92,27 @@ HX711_ADC LoadCell[]{HX711_ADC(PIN_LOADCELL1_DOUT, PIN_LOADCELL1_PD_SCK),HX711_A
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
ESP8266WebServer server(80);
|
ESP8266WebServer server(80);
|
||||||
IPAddress apIP(ip[0], ip[1], ip[2], ip[3]);
|
IPAddress apIP(ip[0], ip[1], ip[2], ip[3]);
|
||||||
|
ESP8266HTTPUpdateServer httpUpdater;
|
||||||
|
WiFiClientSecure httpsClient;
|
||||||
File fsUploadFile; // a File object to temporarily store the received file
|
File fsUploadFile; // a File object to temporarily store the received file
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
char name[MAX_MODELNAME_LENGHT + 1] = "";
|
||||||
|
float distance[3] = {DISTANCE_X1, DISTANCE_X2, DISTANCE_X3};
|
||||||
|
#if defined(ESP8266)
|
||||||
|
float targetCGmin = 0;
|
||||||
|
float targetCGmax = 0;
|
||||||
|
uint8_t mechanicsType = 0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
Model model;
|
||||||
|
|
||||||
// load default values
|
// load default values
|
||||||
uint8_t nLoadcells = NUMBER_LOADCELLS;
|
uint8_t nLoadcells = NUMBER_LOADCELLS;
|
||||||
float distance[] = {DISTANCE_X1, DISTANCE_X2, DISTANCE_X3};
|
|
||||||
float calFactorLoadcell[] = {LOADCELL1_CALIBRATION_FACTOR, LOADCELL2_CALIBRATION_FACTOR, LOADCELL3_CALIBRATION_FACTOR};
|
float calFactorLoadcell[] = {LOADCELL1_CALIBRATION_FACTOR, LOADCELL2_CALIBRATION_FACTOR, LOADCELL3_CALIBRATION_FACTOR};
|
||||||
float resistor[] = {RESISTOR_R1, RESISTOR_R2};
|
float resistor[] = {RESISTOR_R1, RESISTOR_R2};
|
||||||
uint8_t batType = BAT_TYPE;
|
uint8_t batType = BAT_TYPE;
|
||||||
@ -103,6 +124,8 @@ char ssid_STA[MAX_SSID_PW_LENGHT + 1] = SSID_STA;
|
|||||||
char password_STA[MAX_SSID_PW_LENGHT + 1] = PASSWORD_STA;
|
char password_STA[MAX_SSID_PW_LENGHT + 1] = PASSWORD_STA;
|
||||||
char ssid_AP[MAX_SSID_PW_LENGHT + 1] = SSID_AP;
|
char ssid_AP[MAX_SSID_PW_LENGHT + 1] = SSID_AP;
|
||||||
char password_AP[MAX_SSID_PW_LENGHT + 1] = PASSWORD_AP;
|
char password_AP[MAX_SSID_PW_LENGHT + 1] = PASSWORD_AP;
|
||||||
|
bool enableUpdate = ENABLE_UPDATE;
|
||||||
|
bool enableOTA = ENABLE_OTA;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// declare variables
|
// declare variables
|
||||||
@ -116,13 +139,12 @@ unsigned long lastTimeMenu = 0;
|
|||||||
unsigned long lastTimeLoadcell = 0;
|
unsigned long lastTimeLoadcell = 0;
|
||||||
bool updateMenu = true;
|
bool updateMenu = true;
|
||||||
int menuPage = 0;
|
int menuPage = 0;
|
||||||
String errMsg[5] = "";
|
String errMsg[5];
|
||||||
int errMsgCnt = 0;
|
int errMsgCnt = 0;
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
String wifiMsg = "";
|
|
||||||
String updateMsg = "";
|
String updateMsg = "";
|
||||||
bool wifiSTAmode = true;
|
bool wifiSTAmode = true;
|
||||||
char curModelName[MAX_MODELNAME_LENGHT + 1] = "";
|
float gitVersion = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -176,7 +198,7 @@ bool runAutoCalibrate() {
|
|||||||
}
|
}
|
||||||
// calculate weight
|
// calculate weight
|
||||||
float toWeightLoadCell[] = {0, 0, 0};
|
float toWeightLoadCell[] = {0, 0, 0};
|
||||||
toWeightLoadCell[LC2] = ((refCG - distance[X1]) * refWeight) / distance[X2];
|
toWeightLoadCell[LC2] = ((refCG - model.distance[X1]) * refWeight) / model.distance[X2];
|
||||||
toWeightLoadCell[LC1] = refWeight - toWeightLoadCell[LC2];
|
toWeightLoadCell[LC1] = refWeight - toWeightLoadCell[LC2];
|
||||||
if (nLoadcells == 3) {
|
if (nLoadcells == 3) {
|
||||||
toWeightLoadCell[LC1] = toWeightLoadCell[LC1] / 2;
|
toWeightLoadCell[LC1] = toWeightLoadCell[LC1] / 2;
|
||||||
@ -200,9 +222,11 @@ bool getLoadcellError() {
|
|||||||
for (int i = LC1; i <= LC3; i++) {
|
for (int i = LC1; i <= LC3; i++) {
|
||||||
if (i < nLoadcells) {
|
if (i < nLoadcells) {
|
||||||
if (LoadCell[i].getTareTimeoutFlag()) {
|
if (LoadCell[i].getTareTimeoutFlag()) {
|
||||||
errMsg[++errMsgCnt] = "ERROR: Timeout TARE Lc";
|
String msg = "ERROR: Timeout TARE Lc" + String(i + 1);
|
||||||
errMsg[errMsgCnt] += (i + 1) ;
|
errMsg[++errMsgCnt] = msg + "\n";
|
||||||
errMsg[errMsgCnt] += "\n";
|
#if defined(ESP8266)
|
||||||
|
printConsole(T_ERROR, msg);
|
||||||
|
#endif
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,11 +279,15 @@ void setup() {
|
|||||||
|
|
||||||
// init serial
|
// init serial
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
|
printConsole(T_BOOT, "startup CG scale V" + String(CGSCALE_VERSION));
|
||||||
|
|
||||||
// init filesystem
|
// init filesystem
|
||||||
SPIFFS.begin();
|
SPIFFS.begin();
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
printConsole(T_BOOT, "init filesystem");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// read settings from eeprom
|
// read settings from eeprom
|
||||||
@ -269,7 +297,7 @@ void setup() {
|
|||||||
|
|
||||||
for (int i = LC1; i <= LC3; i++) {
|
for (int i = LC1; i <= LC3; i++) {
|
||||||
if (EEPROM.read(P_DISTANCE_X1 + (i * sizeof(float))) != 0xFF) {
|
if (EEPROM.read(P_DISTANCE_X1 + (i * sizeof(float))) != 0xFF) {
|
||||||
EEPROM.get(P_DISTANCE_X1 + (i * sizeof(float)), distance[i]);
|
EEPROM.get(P_DISTANCE_X1 + (i * sizeof(float)), model.distance[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EEPROM.read(P_LOADCELL1_CALIBRATION_FACTOR + (i * sizeof(float))) != 0xFF) {
|
if (EEPROM.read(P_LOADCELL1_CALIBRATION_FACTOR + (i * sizeof(float))) != 0xFF) {
|
||||||
@ -317,17 +345,30 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (EEPROM.read(P_MODELNAME) != 0xFF) {
|
if (EEPROM.read(P_MODELNAME) != 0xFF) {
|
||||||
EEPROM.get(P_MODELNAME, curModelName);
|
EEPROM.get(P_MODELNAME, model.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EEPROM.read(P_ENABLE_UPDATE) != 0xFF) {
|
||||||
|
EEPROM.get(P_ENABLE_UPDATE, enableUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EEPROM.read(P_ENABLE_OTA) != 0xFF) {
|
||||||
|
EEPROM.get(P_ENABLE_OTA, enableOTA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load current model
|
// load current model
|
||||||
if (!openModelJson(curModelName)) {
|
printConsole(T_BOOT, "open last model");
|
||||||
curModelName[0] = '\0';
|
if (!openModelJson(model.name)) {
|
||||||
|
saveModelJson(DEFAULT_NAME);
|
||||||
|
openModelJson(DEFAULT_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// init OLED display
|
// init OLED display
|
||||||
|
#if defined(ESP8266)
|
||||||
|
printConsole(T_BOOT, "init OLED display");
|
||||||
|
#endif
|
||||||
oledDisplay.begin();
|
oledDisplay.begin();
|
||||||
oledDisplay.firstPage();
|
oledDisplay.firstPage();
|
||||||
do {
|
do {
|
||||||
@ -349,6 +390,9 @@ void setup() {
|
|||||||
if (i < nLoadcells) {
|
if (i < nLoadcells) {
|
||||||
LoadCell[i].begin();
|
LoadCell[i].begin();
|
||||||
LoadCell[i].setCalFactor(calFactorLoadcell[i]);
|
LoadCell[i].setCalFactor(calFactorLoadcell[i]);
|
||||||
|
#if defined(ESP8266)
|
||||||
|
printConsole(T_BOOT, "init Loadcell " + String(i+1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,6 +407,41 @@ void setup() {
|
|||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
|
|
||||||
|
// Start by connecting to a WiFi network
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid_STA, password_STA);
|
||||||
|
|
||||||
|
printConsole(T_BOOT, "Wifi: STA mode - connect with: " + String(ssid_STA));
|
||||||
|
|
||||||
|
long timeoutWiFi = millis();
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
if (WiFi.status() == WL_NO_SSID_AVAIL) {
|
||||||
|
printConsole(T_ERROR, "Wifi: No SSID available");
|
||||||
|
break;
|
||||||
|
} else if (WiFi.status() == WL_CONNECT_FAILED) {
|
||||||
|
printConsole(T_ERROR, "Wifi: Connection failed");
|
||||||
|
break;
|
||||||
|
} else if ((millis() - timeoutWiFi) > TIMEOUT_CONNECT) {
|
||||||
|
printConsole(T_ERROR, "Wifi: Timeout");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
|
// if WiFi not connected, switch to access point mode
|
||||||
|
wifiSTAmode = false;
|
||||||
|
printConsole(T_BOOT, "Wifi: AP mode - create access point: " + String(ssid_AP));
|
||||||
|
WiFi.mode(WIFI_AP);
|
||||||
|
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
||||||
|
WiFi.softAP(ssid_AP, password_AP);
|
||||||
|
printConsole(T_RUN, "Wifi: Connected, IP: " + String(WiFi.softAPIP().toString()));
|
||||||
|
} else {
|
||||||
|
printConsole(T_RUN, "Wifi: Connected, IP: " + String(WiFi.localIP().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set Hostname
|
// Set Hostname
|
||||||
String hostname = "disabled";
|
String hostname = "disabled";
|
||||||
#if ENABLE_MDNS
|
#if ENABLE_MDNS
|
||||||
@ -371,63 +450,14 @@ void setup() {
|
|||||||
hostname.toLowerCase();
|
hostname.toLowerCase();
|
||||||
if (!MDNS.begin(hostname, WiFi.localIP())) {
|
if (!MDNS.begin(hostname, WiFi.localIP())) {
|
||||||
hostname = "mDNS failed";
|
hostname = "mDNS failed";
|
||||||
|
printConsole(T_ERROR, "Wifi: " + hostname);
|
||||||
}else{
|
}else{
|
||||||
hostname += ".local";
|
hostname += ".local";
|
||||||
|
printConsole(T_RUN, "Wifi: " + hostname);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " Hostname: ";
|
|
||||||
wifiMsg += hostname;
|
|
||||||
wifiMsg += "\n";
|
|
||||||
|
|
||||||
|
|
||||||
// Start by connecting to a WiFi network
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
WiFi.begin(ssid_STA, password_STA);
|
|
||||||
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " STA mode - connect with wifi: ";
|
|
||||||
wifiMsg += ssid_STA;
|
|
||||||
wifiMsg += "\n";
|
|
||||||
|
|
||||||
long timeoutWiFi = millis();
|
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
|
||||||
delay(500);
|
|
||||||
if (WiFi.status() == WL_NO_SSID_AVAIL) {
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " No SSID available\n";
|
|
||||||
break;
|
|
||||||
} else if (WiFi.status() == WL_CONNECT_FAILED) {
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " Connection failed\n";
|
|
||||||
break;
|
|
||||||
} else if ((millis() - timeoutWiFi) > TIMEOUT_CONNECT) {
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " Timeout\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
|
||||||
// if WiFi not connected, switch to access point mode
|
|
||||||
wifiSTAmode = false;
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " AP mode - create access point: ";
|
|
||||||
wifiMsg += ssid_AP;
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
|
||||||
WiFi.softAP(ssid_AP, password_AP);
|
|
||||||
wifiMsg += "\n";
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " IP: ";
|
|
||||||
wifiMsg += WiFi.softAPIP().toString();
|
|
||||||
} else {
|
|
||||||
wifiMsg += TimeToString(millis());
|
|
||||||
wifiMsg += " Connected, IP: ";
|
|
||||||
wifiMsg += WiFi.localIP().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// print wifi status
|
// print wifi status
|
||||||
oledDisplay.firstPage();
|
oledDisplay.firstPage();
|
||||||
do {
|
do {
|
||||||
@ -471,20 +501,25 @@ void setup() {
|
|||||||
server.on("/deleteModel", deleteModel);
|
server.on("/deleteModel", deleteModel);
|
||||||
|
|
||||||
// When the client upload file
|
// When the client upload file
|
||||||
server.on("/models.html", HTTP_POST, []() {
|
server.on("/settings.html", HTTP_POST, []() {
|
||||||
server.send(200, "text/plain", "");
|
server.send(200, "text/plain", "");
|
||||||
}, handleFileUpload);
|
}, handleFileUpload);
|
||||||
|
|
||||||
// If the client requests any URI
|
// If the client requests any URI
|
||||||
server.onNotFound([]() {
|
server.onNotFound([]() {
|
||||||
if (!handleFileRead(server.uri()))
|
if (!handleFileRead(server.uri()))
|
||||||
server.send(404, "text/plain", "404: Not Found");
|
server.send(404, "text/plain", "CGscale Error: 404\n File or URL not Found !");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// init http updater
|
||||||
|
httpUpdater.setup(&server);
|
||||||
|
|
||||||
// init webserver
|
// init webserver
|
||||||
server.begin();
|
server.begin();
|
||||||
|
printConsole(T_RUN, "Webserver is up and running");
|
||||||
|
|
||||||
// init OTA (over the air update)
|
// init OTA (over the air update)
|
||||||
|
if(enableOTA){
|
||||||
ArduinoOTA.setHostname(ssid_AP);
|
ArduinoOTA.setHostname(ssid_AP);
|
||||||
ArduinoOTA.setPassword(password_AP);
|
ArduinoOTA.setPassword(password_AP);
|
||||||
|
|
||||||
@ -493,11 +528,11 @@ void setup() {
|
|||||||
if (ArduinoOTA.getCommand() == U_FLASH) {
|
if (ArduinoOTA.getCommand() == U_FLASH) {
|
||||||
type = "firmware";
|
type = "firmware";
|
||||||
} else { // U_SPIFFS
|
} else { // U_SPIFFS
|
||||||
//SPIFFS.end();
|
|
||||||
type = "SPIFFS";
|
type = "SPIFFS";
|
||||||
}
|
}
|
||||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||||
updateMsg = "Updating " + type;
|
updateMsg = "Updating " + type;
|
||||||
|
printConsole(T_UPDATE, type);
|
||||||
});
|
});
|
||||||
|
|
||||||
ArduinoOTA.onEnd([]() {
|
ArduinoOTA.onEnd([]() {
|
||||||
@ -525,6 +560,15 @@ void setup() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
|
printConsole(T_RUN, "OTA is up and running");
|
||||||
|
}
|
||||||
|
|
||||||
|
// https update
|
||||||
|
httpsClient.setInsecure();
|
||||||
|
if(enableUpdate){
|
||||||
|
// check for update
|
||||||
|
httpsUpdate(PROBE_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -539,7 +583,9 @@ void loop() {
|
|||||||
MDNS.update();
|
MDNS.update();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(enableOTA){
|
||||||
ArduinoOTA.handle();
|
ArduinoOTA.handle();
|
||||||
|
}
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -573,12 +619,21 @@ void loop() {
|
|||||||
|
|
||||||
if (weightTotal > MINIMAL_CG_WEIGHT) {
|
if (weightTotal > MINIMAL_CG_WEIGHT) {
|
||||||
// CG longitudinal axis
|
// CG longitudinal axis
|
||||||
CG_length = ((weightLoadCell[LC2] * distance[X2]) / weightTotal) + distance[X1];
|
CG_length = ((weightLoadCell[LC2] * model.distance[X2]) / weightTotal) + model.distance[X1];
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
if(model.mechanicsType == 2){
|
||||||
|
CG_length = ((weightLoadCell[LC2] * model.distance[X2]) / weightTotal) - model.distance[X1];
|
||||||
|
}else if(model.mechanicsType == 3){
|
||||||
|
CG_length = ((weightLoadCell[LC2] * model.distance[X2]) / weightTotal) * -1 + model.distance[X1];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// CG transverse axis
|
// CG transverse axis
|
||||||
if (nLoadcells == 3) {
|
if (nLoadcells == 3) {
|
||||||
CG_trans = (distance[X3] / 2) - (((weightLoadCell[LC1] + weightLoadCell[LC2] / 2) * distance[X3]) / weightTotal);
|
CG_trans = (model.distance[X3] / 2) - (((weightLoadCell[LC1] + weightLoadCell[LC2] / 2) * model.distance[X3]) / weightTotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
CG_length = 0;
|
CG_length = 0;
|
||||||
CG_trans = 0;
|
CG_trans = 0;
|
||||||
@ -682,8 +737,8 @@ void loop() {
|
|||||||
updateMenu = true;
|
updateMenu = true;
|
||||||
break;
|
break;
|
||||||
case MENU_DISTANCE_X1 ... MENU_DISTANCE_X3:
|
case MENU_DISTANCE_X1 ... MENU_DISTANCE_X3:
|
||||||
distance[menuPage - MENU_DISTANCE_X1] = Serial.parseFloat();
|
model.distance[menuPage - MENU_DISTANCE_X1] = Serial.parseFloat();
|
||||||
EEPROM.put(P_DISTANCE_X1 + ((menuPage - MENU_DISTANCE_X1) * sizeof(float)), distance[menuPage - MENU_DISTANCE_X1]);
|
EEPROM.put(P_DISTANCE_X1 + ((menuPage - MENU_DISTANCE_X1) * sizeof(float)), model.distance[menuPage - MENU_DISTANCE_X1]);
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
#endif
|
#endif
|
||||||
@ -797,7 +852,7 @@ void loop() {
|
|||||||
Serial.print(F(" - Set distance X"));
|
Serial.print(F(" - Set distance X"));
|
||||||
Serial.print(i+1);
|
Serial.print(i+1);
|
||||||
Serial.print(F(" ("));
|
Serial.print(F(" ("));
|
||||||
Serial.print(distance[i]);
|
Serial.print(model.distance[i]);
|
||||||
Serial.print(F("mm)\n"));
|
Serial.print(F("mm)\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,7 +929,7 @@ void loop() {
|
|||||||
Serial.print("\n\nDistance X");
|
Serial.print("\n\nDistance X");
|
||||||
Serial.print(menuPage - MENU_DISTANCE_X1 + 1);
|
Serial.print(menuPage - MENU_DISTANCE_X1 + 1);
|
||||||
Serial.print(F(": "));
|
Serial.print(F(": "));
|
||||||
Serial.print(distance[menuPage - MENU_DISTANCE_X1]);
|
Serial.print(model.distance[menuPage - MENU_DISTANCE_X1]);
|
||||||
Serial.print(F("mm\n"));
|
Serial.print(F("mm\n"));
|
||||||
printNewValueText();
|
printNewValueText();
|
||||||
updateMenu = false;
|
updateMenu = false;
|
||||||
@ -965,9 +1020,6 @@ void loop() {
|
|||||||
case MENU_WIFI_INFO:
|
case MENU_WIFI_INFO:
|
||||||
{
|
{
|
||||||
Serial.println("\n\n********************************************\nWiFi network information\n");
|
Serial.println("\n\n********************************************\nWiFi network information\n");
|
||||||
Serial.println("# Startup log:");
|
|
||||||
Serial.println(wifiMsg);
|
|
||||||
Serial.println("# end of log\n");
|
|
||||||
|
|
||||||
Serial.println("# Current WiFi status:");
|
Serial.println("# Current WiFi status:");
|
||||||
WiFi.printDiag(Serial);
|
WiFi.printDiag(Serial);
|
||||||
@ -1035,6 +1087,8 @@ void getHead() {
|
|||||||
}
|
}
|
||||||
response += "&";
|
response += "&";
|
||||||
response += CGSCALE_VERSION;
|
response += CGSCALE_VERSION;
|
||||||
|
response += "&";
|
||||||
|
response += gitVersion;
|
||||||
server.send(200, "text/html", response);
|
server.send(200, "text/html", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,7 +1131,16 @@ void getRawValue() {
|
|||||||
response += "g&";
|
response += "g&";
|
||||||
dtostrf(weightLoadCell[LC3], 5, 1, buff);
|
dtostrf(weightLoadCell[LC3], 5, 1, buff);
|
||||||
response += buff;
|
response += buff;
|
||||||
response += "g";
|
response += "g&";
|
||||||
|
if (batType == B_VOLT) {
|
||||||
|
dtostrf(batVolt, 5, 2, buff);
|
||||||
|
response += buff;
|
||||||
|
response += "V";
|
||||||
|
} else {
|
||||||
|
dtostrf(batVolt, 5, 0, buff);
|
||||||
|
response += buff;
|
||||||
|
response += "%";
|
||||||
|
}
|
||||||
server.send(200, "text/html", response);
|
server.send(200, "text/html", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1089,21 +1152,24 @@ void getParameter() {
|
|||||||
float weightTotal_saved = 0;
|
float weightTotal_saved = 0;
|
||||||
float CG_length_saved = 0;
|
float CG_length_saved = 0;
|
||||||
float CG_trans_saved = 0;
|
float CG_trans_saved = 0;
|
||||||
|
model.targetCGmin = 0;
|
||||||
|
model.targetCGmax = 0;
|
||||||
|
|
||||||
StaticJsonBuffer<JSONBUFFER_SIZE> jsonBuffer;
|
StaticJsonDocument<JSONDOC_SIZE> jsonDoc;
|
||||||
//DynamicJsonBuffer jsonBuffer(JSONBUFFER_SIZE);
|
|
||||||
|
|
||||||
if (SPIFFS.exists(MODEL_FILE)) {
|
if (SPIFFS.exists(MODEL_FILE)) {
|
||||||
// read json file
|
// read json file
|
||||||
File f = SPIFFS.open(MODEL_FILE, "r");
|
File f = SPIFFS.open(MODEL_FILE, "r");
|
||||||
JsonObject& root = jsonBuffer.parseObject(f);
|
auto error = deserializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
// check if model exists
|
// check if model exists
|
||||||
if (root.success() && root.containsKey(curModelName)) {
|
if (!error && jsonDoc.containsKey(model.name)) {
|
||||||
JsonObject& object = root[curModelName];
|
weightTotal_saved = jsonDoc[model.name]["wt"];
|
||||||
weightTotal_saved = object["wt"];
|
CG_length_saved = jsonDoc[model.name]["cg"];
|
||||||
CG_length_saved = object["cg"];
|
CG_trans_saved = jsonDoc[model.name]["cglr"];
|
||||||
CG_trans_saved = object["cglr"];
|
model.targetCGmin = jsonDoc[model.name]["cgmin"];
|
||||||
|
model.targetCGmax = jsonDoc[model.name]["cgmax"];
|
||||||
|
model.mechanicsType = jsonDoc[model.name]["mType"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1111,7 +1177,7 @@ void getParameter() {
|
|||||||
response += nLoadcells;
|
response += nLoadcells;
|
||||||
response += "&";
|
response += "&";
|
||||||
for (int i = X1; i <= X3; i++) {
|
for (int i = X1; i <= X3; i++) {
|
||||||
response += distance[i];
|
response += model.distance[i];
|
||||||
response += "&";
|
response += "&";
|
||||||
}
|
}
|
||||||
response += refWeight;
|
response += refWeight;
|
||||||
@ -1138,7 +1204,7 @@ void getParameter() {
|
|||||||
response += "&";
|
response += "&";
|
||||||
response += password_AP;
|
response += password_AP;
|
||||||
response += "&";
|
response += "&";
|
||||||
response += curModelName;
|
response += model.name;
|
||||||
response += "&";
|
response += "&";
|
||||||
dtostrf(weightTotal_saved, 5, 1, buff);
|
dtostrf(weightTotal_saved, 5, 1, buff);
|
||||||
response += buff;
|
response += buff;
|
||||||
@ -1148,7 +1214,16 @@ void getParameter() {
|
|||||||
response += "mm&";
|
response += "mm&";
|
||||||
dtostrf(CG_trans_saved, 5, 1, buff);
|
dtostrf(CG_trans_saved, 5, 1, buff);
|
||||||
response += buff;
|
response += buff;
|
||||||
response += "mm";
|
response += "mm&";
|
||||||
|
response += model.targetCGmin;
|
||||||
|
response += "&";
|
||||||
|
response += model.targetCGmax;
|
||||||
|
response += "&";
|
||||||
|
response += model.mechanicsType;
|
||||||
|
response += "&";
|
||||||
|
response += enableUpdate;
|
||||||
|
response += "&";
|
||||||
|
response += enableOTA;
|
||||||
server.send(200, "text/html", response);
|
server.send(200, "text/html", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,9 +1252,9 @@ void getWiFiNetworks() {
|
|||||||
// save parameters
|
// save parameters
|
||||||
void saveParameter() {
|
void saveParameter() {
|
||||||
if (server.hasArg("nLoadcells")) nLoadcells = server.arg("nLoadcells").toInt();
|
if (server.hasArg("nLoadcells")) nLoadcells = server.arg("nLoadcells").toInt();
|
||||||
if (server.hasArg("distanceX1")) distance[X1] = server.arg("distanceX1").toFloat();
|
if (server.hasArg("distanceX1")) model.distance[X1] = server.arg("distanceX1").toFloat();
|
||||||
if (server.hasArg("distanceX2")) distance[X2] = server.arg("distanceX2").toFloat();
|
if (server.hasArg("distanceX2")) model.distance[X2] = server.arg("distanceX2").toFloat();
|
||||||
if (server.hasArg("distanceX3")) distance[X3] = server.arg("distanceX3").toFloat();
|
if (server.hasArg("distanceX3")) model.distance[X3] = server.arg("distanceX3").toFloat();
|
||||||
if (server.hasArg("refWeight")) refWeight = server.arg("refWeight").toFloat();
|
if (server.hasArg("refWeight")) refWeight = server.arg("refWeight").toFloat();
|
||||||
if (server.hasArg("refCG")) refCG = server.arg("refCG").toFloat();
|
if (server.hasArg("refCG")) refCG = server.arg("refCG").toFloat();
|
||||||
if (server.hasArg("calFactorLoadcell1")) calFactorLoadcell[LC1] = server.arg("calFactorLoadcell1").toFloat();
|
if (server.hasArg("calFactorLoadcell1")) calFactorLoadcell[LC1] = server.arg("calFactorLoadcell1").toFloat();
|
||||||
@ -1193,10 +1268,13 @@ void saveParameter() {
|
|||||||
if (server.hasArg("password_STA")) server.arg("password_STA").toCharArray(password_STA, MAX_SSID_PW_LENGHT + 1);
|
if (server.hasArg("password_STA")) server.arg("password_STA").toCharArray(password_STA, MAX_SSID_PW_LENGHT + 1);
|
||||||
if (server.hasArg("ssid_AP")) server.arg("ssid_AP").toCharArray(ssid_AP, MAX_SSID_PW_LENGHT + 1);
|
if (server.hasArg("ssid_AP")) server.arg("ssid_AP").toCharArray(ssid_AP, MAX_SSID_PW_LENGHT + 1);
|
||||||
if (server.hasArg("password_AP")) server.arg("password_AP").toCharArray(password_AP, MAX_SSID_PW_LENGHT + 1);
|
if (server.hasArg("password_AP")) server.arg("password_AP").toCharArray(password_AP, MAX_SSID_PW_LENGHT + 1);
|
||||||
|
if (server.hasArg("mechanicsType")) model.mechanicsType = server.arg("mechanicsType").toInt();
|
||||||
|
if (server.hasArg("enableUpdate")) enableUpdate = server.arg("enableUpdate").toInt();
|
||||||
|
if (server.hasArg("enableOTA")) enableOTA = server.arg("enableOTA").toInt();
|
||||||
|
|
||||||
EEPROM.put(P_NUMBER_LOADCELLS, nLoadcells);
|
EEPROM.put(P_NUMBER_LOADCELLS, nLoadcells);
|
||||||
for (int i = LC1; i <= LC3; i++) {
|
for (int i = LC1; i <= LC3; i++) {
|
||||||
EEPROM.put(P_DISTANCE_X1 + (i * sizeof(float)), distance[i]);
|
EEPROM.put(P_DISTANCE_X1 + (i * sizeof(float)), model.distance[i]);
|
||||||
saveCalFactor(i);
|
saveCalFactor(i);
|
||||||
}
|
}
|
||||||
EEPROM.put(P_REF_WEIGHT, refWeight);
|
EEPROM.put(P_REF_WEIGHT, refWeight);
|
||||||
@ -1210,8 +1288,14 @@ void saveParameter() {
|
|||||||
EEPROM.put(P_PASSWORD_STA, password_STA);
|
EEPROM.put(P_PASSWORD_STA, password_STA);
|
||||||
EEPROM.put(P_SSID_AP, ssid_AP);
|
EEPROM.put(P_SSID_AP, ssid_AP);
|
||||||
EEPROM.put(P_PASSWORD_AP, password_AP);
|
EEPROM.put(P_PASSWORD_AP, password_AP);
|
||||||
|
EEPROM.put(P_ENABLE_UPDATE, enableUpdate);
|
||||||
|
EEPROM.put(P_ENABLE_OTA, enableOTA);
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
|
|
||||||
|
if(model.name != ""){
|
||||||
|
saveModelJson(model.name);
|
||||||
|
}
|
||||||
|
|
||||||
server.send(200, "text/plain", "saved");
|
server.send(200, "text/plain", "saved");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1219,7 +1303,7 @@ void saveParameter() {
|
|||||||
// calibrate cg scale
|
// calibrate cg scale
|
||||||
void autoCalibrate() {
|
void autoCalibrate() {
|
||||||
while (!runAutoCalibrate());
|
while (!runAutoCalibrate());
|
||||||
server.send(200, "text/plain", "parameters saved");
|
server.send(200, "text/plain", "Calibration successful");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1227,16 +1311,22 @@ void autoCalibrate() {
|
|||||||
void runTare() {
|
void runTare() {
|
||||||
tareLoadcells();
|
tareLoadcells();
|
||||||
if (!getLoadcellError()) {
|
if (!getLoadcellError()) {
|
||||||
server.send(200, "text/plain", "tare completed");
|
server.send(200, "text/plain", "Tare completed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
server.send(404, "text/plain", "404: tare failed !");
|
server.send(404, "text/plain", "404: Tare failed !");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// save model
|
// save model
|
||||||
void saveModel() {
|
void saveModel() {
|
||||||
if (server.hasArg("modelname")) {
|
if (server.hasArg("modelname")) {
|
||||||
|
if (server.hasArg("targetCGmin")) model.targetCGmin = server.arg("targetCGmin").toFloat();
|
||||||
|
if (server.hasArg("targetCGmax")) model.targetCGmax = server.arg("targetCGmax").toFloat();
|
||||||
|
if (server.hasArg("distanceX1")) model.distance[X1] = server.arg("distanceX1").toFloat();
|
||||||
|
if (server.hasArg("distanceX2")) model.distance[X2] = server.arg("distanceX2").toFloat();
|
||||||
|
if (server.hasArg("distanceX3")) model.distance[X3] = server.arg("distanceX3").toFloat();
|
||||||
|
if (server.hasArg("mechanicsType")) model.mechanicsType = server.arg("mechanicsType").toInt();
|
||||||
if (saveModelJson(server.arg("modelname"))) {
|
if (saveModelJson(server.arg("modelname"))) {
|
||||||
server.send(200, "text/plain", "saved");
|
server.send(200, "text/plain", "saved");
|
||||||
return;
|
return;
|
||||||
@ -1285,7 +1375,6 @@ String getContentType(String filename) {
|
|||||||
|
|
||||||
// send file to the client (if it exists)
|
// send file to the client (if it exists)
|
||||||
bool handleFileRead(String path) {
|
bool handleFileRead(String path) {
|
||||||
|
|
||||||
// If a folder is requested, send the index file
|
// If a folder is requested, send the index file
|
||||||
if (path.endsWith("/")) path += "index.html";
|
if (path.endsWith("/")) path += "index.html";
|
||||||
String contentType = getContentType(path);
|
String contentType = getContentType(path);
|
||||||
@ -1325,7 +1414,7 @@ void handleFileUpload() {
|
|||||||
if (fsUploadFile) {
|
if (fsUploadFile) {
|
||||||
fsUploadFile.close();
|
fsUploadFile.close();
|
||||||
// Redirect the client to the success page
|
// Redirect the client to the success page
|
||||||
server.sendHeader("Location", "/models.html");
|
server.sendHeader("Location", "/settings.html");
|
||||||
server.send(303);
|
server.send(303);
|
||||||
} else {
|
} else {
|
||||||
server.send(500, "text/plain", "500: couldn't create file");
|
server.send(500, "text/plain", "500: couldn't create file");
|
||||||
@ -1342,40 +1431,38 @@ bool saveModelJson(String modelName) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticJsonBuffer<JSONBUFFER_SIZE> jsonBuffer;
|
StaticJsonDocument<JSONDOC_SIZE> jsonDoc;
|
||||||
//DynamicJsonBuffer jsonBuffer(JSONBUFFER_SIZE);
|
|
||||||
|
|
||||||
if (SPIFFS.exists(MODEL_FILE)) {
|
if (SPIFFS.exists(MODEL_FILE)) {
|
||||||
// read json file
|
// read json file
|
||||||
File f = SPIFFS.open(MODEL_FILE, "r");
|
File f = SPIFFS.open(MODEL_FILE, "r");
|
||||||
JsonObject& root = jsonBuffer.parseObject(f);
|
auto error = deserializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
if (!root.success()) {
|
if (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// check if model exists
|
// check if model exists
|
||||||
if (root.containsKey(modelName)) {
|
if (jsonDoc.containsKey(modelName)) {
|
||||||
writeModelData(root[modelName]);
|
writeModelData(jsonDoc[modelName]);
|
||||||
} else {
|
} else {
|
||||||
// otherwise create new
|
// otherwise create new
|
||||||
writeModelData(root.createNestedObject(modelName));
|
writeModelData(jsonDoc.createNestedObject(modelName));
|
||||||
}
|
}
|
||||||
// write to file
|
// write to file
|
||||||
if (root.success()) {
|
if (!error) {
|
||||||
f = SPIFFS.open(MODEL_FILE, "w");
|
f = SPIFFS.open(MODEL_FILE, "w");
|
||||||
root.printTo(f);
|
serializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// creat new json
|
// creat new json
|
||||||
JsonObject& root = jsonBuffer.createObject();
|
writeModelData(jsonDoc.createNestedObject(modelName));
|
||||||
writeModelData(root.createNestedObject(modelName));
|
|
||||||
// write to file
|
// write to file
|
||||||
if (root.success()) {
|
if (!jsonDoc.isNull()) {
|
||||||
File f = SPIFFS.open(MODEL_FILE, "w");
|
File f = SPIFFS.open(MODEL_FILE, "w");
|
||||||
root.printTo(f);
|
serializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -1389,31 +1476,32 @@ bool saveModelJson(String modelName) {
|
|||||||
// read model data from json file
|
// read model data from json file
|
||||||
bool openModelJson(String modelName) {
|
bool openModelJson(String modelName) {
|
||||||
|
|
||||||
StaticJsonBuffer<JSONBUFFER_SIZE> jsonBuffer;
|
StaticJsonDocument<JSONDOC_SIZE> jsonDoc;
|
||||||
//DynamicJsonBuffer jsonBuffer(JSONBUFFER_SIZE);
|
|
||||||
|
|
||||||
if (SPIFFS.exists(MODEL_FILE)) {
|
if (SPIFFS.exists(MODEL_FILE)) {
|
||||||
// read json file
|
// read json file
|
||||||
File f = SPIFFS.open(MODEL_FILE, "r");
|
File f = SPIFFS.open(MODEL_FILE, "r");
|
||||||
JsonObject& root = jsonBuffer.parseObject(f);
|
auto error = deserializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
if (!root.success()) {
|
if (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// check if model exists
|
// check if model exists
|
||||||
if (root.containsKey(modelName)) {
|
if (jsonDoc.containsKey(modelName)) {
|
||||||
JsonObject& object = root[modelName];
|
|
||||||
// load parameters from model
|
// load parameters from model
|
||||||
distance[X1] = object["x1"];
|
model.distance[X1] = jsonDoc[modelName]["x1"];
|
||||||
distance[X2] = object["x2"];
|
model.distance[X2] = jsonDoc[modelName]["x2"];
|
||||||
distance[X3] = object["x3"];
|
model.distance[X3] = jsonDoc[modelName]["x3"];
|
||||||
|
model.targetCGmin = jsonDoc[modelName]["cgmin"];
|
||||||
|
model.targetCGmax = jsonDoc[modelName]["cgmax"];
|
||||||
|
model.mechanicsType = jsonDoc[modelName]["mType"];
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save current model name to eeprom
|
// save current model name to eeprom
|
||||||
modelName.toCharArray(curModelName, MAX_MODELNAME_LENGHT + 1);
|
modelName.toCharArray(model.name, MAX_MODELNAME_LENGHT + 1);
|
||||||
EEPROM.put(P_MODELNAME, curModelName);
|
EEPROM.put(P_MODELNAME, model.name);
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1426,31 +1514,30 @@ bool openModelJson(String modelName) {
|
|||||||
// delete model from json file
|
// delete model from json file
|
||||||
bool deleteModelJson(String modelName) {
|
bool deleteModelJson(String modelName) {
|
||||||
|
|
||||||
StaticJsonBuffer<JSONBUFFER_SIZE> jsonBuffer;
|
StaticJsonDocument<JSONDOC_SIZE> jsonDoc;
|
||||||
//DynamicJsonBuffer jsonBuffer(JSONBUFFER_SIZE);
|
|
||||||
|
|
||||||
if (SPIFFS.exists(MODEL_FILE)) {
|
if (SPIFFS.exists(MODEL_FILE)) {
|
||||||
// read json file
|
// read json file
|
||||||
File f = SPIFFS.open(MODEL_FILE, "r");
|
File f = SPIFFS.open(MODEL_FILE, "r");
|
||||||
JsonObject& root = jsonBuffer.parseObject(f);
|
auto error = deserializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
if (!root.success()) {
|
if (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// check if model exists
|
// check if model exists
|
||||||
if (root.containsKey(modelName)) {
|
if (jsonDoc.containsKey(modelName)) {
|
||||||
root.remove(modelName);
|
jsonDoc.remove(modelName);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// if no models in json, kill it
|
// if no models in json, kill it
|
||||||
if (root.size() == 0) {
|
if (jsonDoc.size() == 0) {
|
||||||
SPIFFS.remove(MODEL_FILE);
|
SPIFFS.remove(MODEL_FILE);
|
||||||
} else {
|
} else {
|
||||||
// write to file
|
// write to file
|
||||||
if (root.success()) {
|
if (!jsonDoc.isNull()) {
|
||||||
File f = SPIFFS.open(MODEL_FILE, "w");
|
File f = SPIFFS.open(MODEL_FILE, "w");
|
||||||
root.printTo(f);
|
serializeJson(jsonDoc, f);
|
||||||
f.close();
|
f.close();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -1463,7 +1550,7 @@ bool deleteModelJson(String modelName) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeModelData(JsonObject& object) {
|
void writeModelData(JsonObject object) {
|
||||||
char buff[8];
|
char buff[8];
|
||||||
String stringBuff;
|
String stringBuff;
|
||||||
|
|
||||||
@ -1479,14 +1566,19 @@ void writeModelData(JsonObject& object) {
|
|||||||
stringBuff = buff;
|
stringBuff = buff;
|
||||||
stringBuff.trim();
|
stringBuff.trim();
|
||||||
object["cglr"] = stringBuff;
|
object["cglr"] = stringBuff;
|
||||||
object["x1"] = distance[X1];
|
object["x1"] = model.distance[X1];
|
||||||
object["x2"] = distance[X2];
|
object["x2"] = model.distance[X2];
|
||||||
object["x3"] = distance[X3];
|
object["x3"] = model.distance[X3];
|
||||||
|
object["cgmin"] = model.targetCGmin;
|
||||||
|
object["cgmax"] = model.targetCGmax;
|
||||||
|
object["mType"] = model.mechanicsType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// print update progress screen
|
// print update progress screen
|
||||||
void printUpdateProgress(unsigned int progress, unsigned int total) {
|
void printUpdateProgress(unsigned int progress, unsigned int total) {
|
||||||
|
printConsole(T_UPDATE, updateMsg);
|
||||||
|
|
||||||
oledDisplay.firstPage();
|
oledDisplay.firstPage();
|
||||||
do {
|
do {
|
||||||
oledDisplay.setFont(u8g2_font_helvR08_tr);
|
oledDisplay.setFont(u8g2_font_helvR08_tr);
|
||||||
@ -1518,4 +1610,82 @@ char * TimeToString(unsigned long t)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printConsole(int t, String msg){
|
||||||
|
Serial.print(TimeToString(millis()));
|
||||||
|
Serial.print(" [");
|
||||||
|
switch(t) {
|
||||||
|
case T_BOOT:
|
||||||
|
Serial.print("BOOT");
|
||||||
|
break;
|
||||||
|
case T_RUN:
|
||||||
|
Serial.print("RUN");
|
||||||
|
break;
|
||||||
|
case T_ERROR:
|
||||||
|
Serial.print("ERROR");
|
||||||
|
break;
|
||||||
|
case T_WIFI:
|
||||||
|
Serial.print("WIFI");
|
||||||
|
break;
|
||||||
|
case T_UPDATE:
|
||||||
|
Serial.print("UPDATE");
|
||||||
|
break;
|
||||||
|
case T_HTTPS:
|
||||||
|
Serial.print("HTTPS");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Serial.print("] ");
|
||||||
|
Serial.println(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https update
|
||||||
|
bool httpsUpdate(uint8_t command){
|
||||||
|
if (!httpsClient.connect(HOST, HTTPS_PORT)) {
|
||||||
|
printConsole(T_ERROR, "Wifi: connection to GIT failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * headerKeys[] = {"Location"} ;
|
||||||
|
const size_t numberOfHeaders = 1;
|
||||||
|
|
||||||
|
HTTPClient https;
|
||||||
|
https.setUserAgent("cgscale");
|
||||||
|
https.setRedirectLimit(0);
|
||||||
|
https.setFollowRedirects(true);
|
||||||
|
|
||||||
|
String url = "https://" + String(HOST) + String(URL);
|
||||||
|
if (https.begin(httpsClient, url)) {
|
||||||
|
https.collectHeaders(headerKeys, numberOfHeaders);
|
||||||
|
|
||||||
|
printConsole(T_HTTPS, "GET: " + url);
|
||||||
|
int httpCode = https.GET();
|
||||||
|
if (httpCode > 0) {
|
||||||
|
// response
|
||||||
|
if (httpCode == HTTP_CODE_FOUND) {
|
||||||
|
String newUrl = https.header("Location");
|
||||||
|
gitVersion = newUrl.substring(newUrl.lastIndexOf('/')+2).toFloat();
|
||||||
|
if(gitVersion > String(CGSCALE_VERSION).toFloat()){
|
||||||
|
printConsole(T_UPDATE, "Firmware update available: V" + String(gitVersion));
|
||||||
|
}else{
|
||||||
|
printConsole(T_UPDATE, "Firmware version found on GitHub: V" + String(gitVersion) + " - current firmware is up to date");
|
||||||
|
}
|
||||||
|
}else if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
|
||||||
|
Serial.println(https.getString());
|
||||||
|
}else{
|
||||||
|
printConsole(T_ERROR, "HTTPS: GET... failed, " + https.errorToString(httpCode));
|
||||||
|
https.end();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
https.end();
|
||||||
|
}else {
|
||||||
|
printConsole(T_ERROR, "Wifi: Unable to connect");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
BIN
Doc/img/cgscale_V2_homeconfig2.png
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
Doc/img/cgscale_V2_homeconfig3.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
Doc/img/cgscale_V2_homeext.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
Doc/img/json_lib_V2.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
Doc/img/nodeMCUpyFlasher.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
Doc/img/webupdate.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
data/CG_scale_mechanics.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
data/Resistor.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
data/battery.png
Before Width: | Height: | Size: 814 B |
BIN
data/fw190.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
data/home.png
Before Width: | Height: | Size: 1.9 KiB |
BIN
data/pc6.png
Normal file
After Width: | Height: | Size: 234 KiB |
BIN
data/pc7.png
Normal file
After Width: | Height: | Size: 70 KiB |
25
defaults.h
@ -51,6 +51,27 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
// https update
|
||||||
|
enum {
|
||||||
|
PROBE_UPDATE,
|
||||||
|
UPDATE_FIRMWARE,
|
||||||
|
UPDATE_SPIFFS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// console msg type
|
||||||
|
enum {
|
||||||
|
T_BOOT,
|
||||||
|
T_RUN,
|
||||||
|
T_ERROR,
|
||||||
|
T_WIFI,
|
||||||
|
T_UPDATE,
|
||||||
|
T_HTTPS
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// EEprom parameter addresses
|
// EEprom parameter addresses
|
||||||
enum {
|
enum {
|
||||||
P_NUMBER_LOADCELLS = 1,
|
P_NUMBER_LOADCELLS = 1,
|
||||||
@ -74,7 +95,9 @@ enum {
|
|||||||
P_SSID_AP = P_PASSWORD_STA + MAX_SSID_PW_LENGHT + 1,
|
P_SSID_AP = P_PASSWORD_STA + MAX_SSID_PW_LENGHT + 1,
|
||||||
P_PASSWORD_AP = P_SSID_AP + MAX_SSID_PW_LENGHT + 1,
|
P_PASSWORD_AP = P_SSID_AP + MAX_SSID_PW_LENGHT + 1,
|
||||||
P_MODELNAME = P_PASSWORD_AP + MAX_SSID_PW_LENGHT + 1,
|
P_MODELNAME = P_PASSWORD_AP + MAX_SSID_PW_LENGHT + 1,
|
||||||
EEPROM_SIZE = P_MODELNAME + MAX_MODELNAME_LENGHT + 1
|
P_ENABLE_UPDATE = P_MODELNAME + MAX_MODELNAME_LENGHT + 1,
|
||||||
|
P_ENABLE_OTA = P_ENABLE_UPDATE + 1,
|
||||||
|
EEPROM_SIZE = P_ENABLE_OTA + 1
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
img/measuring.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@ -142,11 +142,22 @@ U8G2_SH1106_128X64_NONAME_1_HW_I2C oledDisplay(U8G2_R0, /* reset=*/ U8X8_PIN_NON
|
|||||||
const char ip[4] = {1,2,3,4}; // default IP address
|
const char ip[4] = {1,2,3,4}; // default IP address
|
||||||
|
|
||||||
#define ENABLE_MDNS true // enable mDNS to reach the webpage with hostname.local
|
#define ENABLE_MDNS true // enable mDNS to reach the webpage with hostname.local
|
||||||
|
#define ENABLE_OTA true // enable over the air update
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// **** https update settings ****
|
||||||
|
|
||||||
|
#define ENABLE_UPDATE true
|
||||||
|
#define HTTPS_PORT 443
|
||||||
|
#define HOST "github.com"
|
||||||
|
#define URL "/nightflyer88/CG_scale/releases/latest"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// **** Model memory settings ****
|
// **** Model memory settings ****
|
||||||
|
|
||||||
#define MAX_MODELNAME_LENGHT 32 // max chars
|
#define MAX_MODELNAME_LENGHT 32 // max chars
|
||||||
|
#define DEFAULT_NAME "Model" // default model name
|
||||||
#define MODEL_FILE "/models.json" // file to store models
|
#define MODEL_FILE "/models.json" // file to store models
|
||||||
#define JSONBUFFER_SIZE 20000 // max file size in bytes
|
#define JSONDOC_SIZE 20000 // max file size in bytes
|
||||||
|