Compare commits

...

24 commits

Author SHA1 Message Date
nicolas.schmauch 98b0130911 Actualiser src/main.cpp 2024-06-26 11:25:15 +02:00
nicolas.schmauch 2f6da4ea09 Actualiser mqtt-python.py 2024-06-25 14:16:39 +02:00
Nicolas Schmauch 37ef459625 LocalSave + clearOldData + SendLocalData 2024-06-25 13:54:06 +02:00
Nicolas Schmauch 97346c1b06 Add LocalSave and SendLocalData 2024-06-21 10:38:52 +02:00
Nicolas Schmauch e9d30f5f30 comm 2024-06-21 10:38:19 +02:00
Nicolas Schmauch f164212c74 Add LocalSave and SendLocalData 2024-06-21 10:24:50 +02:00
Nicolas Schmauch cce2fb3629 améliration du code 2024-06-14 17:07:29 +02:00
noah cazeaudumec 0b04918e65 ajustement valeur batterie + save des données en local 2024-06-14 14:46:44 +02:00
nicolas.schmauch 3215912edd Actualiser mqtt-python.py 2024-06-12 10:19:21 +02:00
nicolas.schmauch 8c9f015b08 Actualiser mqtt-python.py 2024-06-11 16:27:28 +02:00
noah cazeaudumec 42f7f3331d amelioration+debug+com 2024-06-07 14:27:50 +02:00
margot.dubuisson aa83fc58d6 Actualiser include/secret.h
change password
2024-06-06 15:39:34 +02:00
nicolas.schmauch f1b23c54a6 Actualiser platformio.ini 2024-05-31 18:24:06 +02:00
Nicolas Schmauch 2d622688e6 new mqtt-python 2024-05-30 17:19:25 +02:00
Aurélien Gauthier c463b39c56 fixxx with epoch time we pray to it work 2022-06-13 17:51:51 +02:00
Aurélien Gauthier 367baf5f9a try test ntp fix 2022-06-13 16:55:18 +02:00
Aurélien Gauthier 80dac772f5 try fix restart bad work, condition fonction removed 2022-06-07 14:04:09 +02:00
Aurélien Gauthier efa325b044 try fix restart wrong fonctionnement, old condition fonction nor rm 2022-06-07 14:02:42 +02:00
Aurélien Gauthier 44872fc71e add persistant solution for restart and comment 2022-06-02 15:49:34 +02:00
Aurélien Gauthier d886bce090 restart each day to try bug fix, add delay for lost connexion wifi and mqtt 2022-06-02 00:21:41 +02:00
Aurélien Gauthier f0a0ccc395 timestamp fix 2022-05-24 16:50:46 +02:00
Aurélien Gauthier a21f0104d8 vscode extension 2022-05-24 10:05:31 +02:00
Aurélien Gauthier e21137c10d test unix timestamp fix 2022-05-24 10:03:16 +02:00
auel 6105de9f97 Temp captor:fixed, Battery measurement:work, solder on esp32, not final version 2022-05-20 17:01:50 +02:00
31 changed files with 1695 additions and 389 deletions

10
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

57
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,57 @@
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
}
}

View file

@ -15,37 +15,58 @@
#include <Pangodream_18650_CL.h>
#include <secret.h>
#define TOPIC "test1"
#define MQTT_ADDRESS "192.168.0.242"
#define TOPIC "test"
#define MQTT_ADDRESS "185.233.103.24"
#define MQTT_PORT 1883
#define ESPNAME "esp32-bastien"
#define CLUSTER "grappe1"
#define ESPNAME "esp32-fablab"
#define CLUSTER "grappe3"
#define SENSORS_NUMBER 5
#define DHT22 22
#define TIME_TO_SLEEP 598
// comment for the test part this is the good frequency
#define TIME_TO_SLEEP 596
// #define TIME_TO_SLEEP 28
#define US_TO_S_FACTOR 1000000
#define R2 100
#define R3 10
#define VOLTAGE_OUT(Vin) (((Vin)*R3) / (R2 + R3))
#define VOLTAGE_OUT(Vin) (((Vin) * R3) / (R2 + R3))
#define VOLTAGE_MAX 4200
#define VOLTAGE_MIN 3300
#define ADC_REFERENCE 1100
#define VOLTAGE_TO_ADC(in) ((ADC_REFERENCE * (in)) / 4096)
#define BATTERY_MAX_ADC VOLTAGE_TO_ADC(VOLTAGE_OUT(VOLTAGE_MAX))
#define BATTERY_MIN_ADC VOLTAGE_TO_ADC(VOLTAGE_OUT(VOLTAGE_MIN))
#define ADC_PIN 34
#define CONV_FACTOR 2.92
// Solder apply on all riders behind the ESP32 for the battery voltage captor
#define ADC_PIN 35
#define CONV_FACTOR 1.78
#define READS 20
const long gmtOffset_sec = 3600;
int getAverageChargeLevel();
void setupMQTT(const char *address, int port);
void setupWIFI(const char *wifi_name, const char *password);
void reconnect(void);
void initSensors(DHT *sensors, int number);
void readSensors(DHT sensors[], float temp[], float hum[], int number);
void sleep();
void clearOldData(int index);
void LocalSave();
void SendLocalData();
std::tuple<int, int, int> getDate();
/**
* @brief hgfhdjskl
*
* @param txt testetest
* @param temp dqsdzfs
* @param hum
* @param number vdsvsvsvs
*/
void writeMsg(char *txt, float *temp, float *hum, int number);
//timeClient.getEpochTime().toCharArray(date, 50); = convertir un string en char
// timeClient.getEpochTime().toCharArray(date, 50); = convertir un string en char
/*
For test the esp32 signal emission without server Working/fixed/updated :
mosquitto_sub -h cohabit-capteurs.aquilenet.fr -u capteurs -P Fablab -t test-alex
*/
#endif

View file

@ -1,5 +1,4 @@
#define MQTT_USER "NomUtilisateurMQTT"
#define MQTT_MDP "MotDePasseMQTT"
#define SSID "NomDuWifi"
#define PWD "MotDePasseWifi"
#define MQTT_USER "capteurs"
#define MQTT_MDP "Fablab"
#define SSID "coh@bit"
#define PWD "lewifidecohabit"

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Pangodream
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
# 18650CL
Library to calculate 18650 charge in Arduino environment

View file

@ -0,0 +1,28 @@
#include <Pangodream_18650_CL.h>
//#define ADC_PIN 34
//#define CONV_FACTOR 1.7
//#define READS 20
Pangodream_18650_CL BL;
/**
* If you need to change default values you can use it as
* Pangodream_18650_CL BL(ADC_PIN, CONV_FACTOR, READS);
*/
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.print("Value from pin: ");
Serial.println(analogRead(34));
Serial.print("Average value from pin: ");
Serial.println(BL.pinRead());
Serial.print("Volts: ");
Serial.println(BL.getBatteryVolts());
Serial.print("Charge level: ");
Serial.println(BL.getBatteryChargeLevel());
Serial.println("");
delay(1000);
}

View file

@ -0,0 +1,18 @@
#######################################
# Syntax Coloring Map BH1750FVI
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Pangodream_18650_CL KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
getBatteryChargeLevel KEYWORD2
getBatteryVolts KEYWORD2
getAnalogPin KEYWORD2
pinRead KEYWORD2
getConvFactor KEYWORD2

View file

@ -0,0 +1,9 @@
name=Pangodream_18650_CL
version=1.0.1
author=Pangodream
maintainer=Pangodream
sentence=Pangodream Library to calculate 18650 charge
paragraph=Pangodream Library to calculate 18650 Ion-Li battery charge
category=Uncategorized
url=https://github.com/pangodream/18650CL
architectures=esp32

View file

@ -0,0 +1,177 @@
/*
MIT License
Copyright (c) 2019 Pangodream
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "Arduino.h"
#include "Pangodream_18650_CL.h"
Pangodream_18650_CL::Pangodream_18650_CL(int addressPin, double convFactor, int reads)
{
_reads = reads;
_convFactor = convFactor;
_addressPin = addressPin;
_initVoltsArray();
}
Pangodream_18650_CL::Pangodream_18650_CL(int addressPin, double convFactor)
{
_reads = DEF_READS;
_convFactor = convFactor;
_addressPin = addressPin;
_initVoltsArray();
}
Pangodream_18650_CL::Pangodream_18650_CL(int addressPin)
{
_reads = DEF_READS;
_convFactor = DEF_CONV_FACTOR;
_addressPin = addressPin;
_initVoltsArray();
}
Pangodream_18650_CL::Pangodream_18650_CL()
{
_reads = DEF_READS;
_convFactor = DEF_CONV_FACTOR;
_addressPin = DEF_PIN;
_initVoltsArray();
}
int Pangodream_18650_CL::getAnalogPin()
{
return _addressPin;
}
double Pangodream_18650_CL::getConvFactor()
{
return _convFactor;
}
/**
* Loads each voltage value in its matching charge element (index)
*/
// void Pangodream_18650_CL::_initVoltsArray(){
// _vs[0] = 3.200;
// _vs[1] = 3.250; _vs[2] = 3.300; _vs[3] = 3.350; _vs[4] = 3.400; _vs[5] = 3.450;
// _vs[6] = 3.500; _vs[7] = 3.550; _vs[8] = 3.600; _vs[9] = 3.650; _vs[10] = 3.700;
// _vs[11] = 3.703; _vs[12] = 3.706; _vs[13] = 3.710; _vs[14] = 3.713; _vs[15] = 3.716;
// _vs[16] = 3.719; _vs[17] = 3.723; _vs[18] = 3.726; _vs[19] = 3.729; _vs[20] = 3.732;
// _vs[21] = 3.735; _vs[22] = 3.739; _vs[23] = 3.742; _vs[24] = 3.745; _vs[25] = 3.748;
// _vs[26] = 3.752; _vs[27] = 3.755; _vs[28] = 3.758; _vs[29] = 3.761; _vs[30] = 3.765;
// _vs[31] = 3.768; _vs[32] = 3.771; _vs[33] = 3.774; _vs[34] = 3.777; _vs[35] = 3.781;
// _vs[36] = 3.784; _vs[37] = 3.787; _vs[38] = 3.790; _vs[39] = 3.794; _vs[40] = 3.797;
// _vs[41] = 3.800; _vs[42] = 3.805; _vs[43] = 3.811; _vs[44] = 3.816; _vs[45] = 3.821;
// _vs[46] = 3.826; _vs[47] = 3.832; _vs[48] = 3.837; _vs[49] = 3.842; _vs[50] = 3.847;
// _vs[51] = 3.853; _vs[52] = 3.858; _vs[53] = 3.863; _vs[54] = 3.868; _vs[55] = 3.874;
// _vs[56] = 3.879; _vs[57] = 3.884; _vs[58] = 3.889; _vs[59] = 3.895; _vs[60] = 3.900;
// _vs[61] = 3.906; _vs[62] = 3.911; _vs[63] = 3.917; _vs[64] = 3.922; _vs[65] = 3.928;
// _vs[66] = 3.933; _vs[67] = 3.939; _vs[68] = 3.944; _vs[69] = 3.950; _vs[70] = 3.956;
// _vs[71] = 3.961; _vs[72] = 3.967; _vs[73] = 3.972; _vs[74] = 3.978; _vs[75] = 3.983;
// _vs[76] = 3.989; _vs[77] = 3.994; _vs[78] = 4.000; _vs[79] = 4.008; _vs[80] = 4.015;
// _vs[81] = 4.023; _vs[82] = 4.031; _vs[83] = 4.038; _vs[84] = 4.046; _vs[85] = 4.054;
// _vs[86] = 4.062; _vs[87] = 4.069; _vs[88] = 4.077; _vs[89] = 4.085; _vs[90] = 4.092;
// _vs[91] = 4.100; _vs[92] = 4.111; _vs[93] = 4.122; _vs[94] = 4.133; _vs[95] = 4.144;
// _vs[96] = 4.156; _vs[97] = 4.167; _vs[98] = 4.178; _vs[99] = 4.189; _vs[100] = 4.200;
// }
void Pangodream_18650_CL::_initVoltsArray(){
_vs[0] = 3.300;
_vs[1] = 3.309; _vs[2] = 3.318; _vs[3] = 3.327; _vs[4] = 3.336; _vs[5] = 3.345;
_vs[6] = 3.354; _vs[7] = 3.363; _vs[8] = 3.372; _vs[9] = 3.381; _vs[10] = 3.390;
_vs[11] = 3.399; _vs[12] = 3.408; _vs[13] = 3.417; _vs[14] = 3.426; _vs[15] = 3.435;
_vs[16] = 3.444; _vs[17] = 3.453; _vs[18] = 3.462; _vs[19] = 3.471; _vs[20] = 3.480;
_vs[21] = 3.489; _vs[22] = 3.498; _vs[23] = 3.507; _vs[24] = 3.516; _vs[25] = 3.525;
_vs[26] = 3.534; _vs[27] = 3.543; _vs[28] = 3.552; _vs[29] = 3.561; _vs[30] = 3.570;
_vs[31] = 3.579; _vs[32] = 3.588; _vs[33] = 3.597; _vs[34] = 3.606; _vs[35] = 3.615;
_vs[36] = 3.624; _vs[37] = 3.633; _vs[38] = 3.642; _vs[39] = 3.651; _vs[40] = 3.660;
_vs[41] = 3.669; _vs[42] = 3.678; _vs[43] = 3.687; _vs[44] = 3.696; _vs[45] = 3.705;
_vs[46] = 3.714; _vs[47] = 3.723; _vs[48] = 3.732; _vs[49] = 3.741; _vs[50] = 3.750;
_vs[51] = 3.759; _vs[52] = 3.768; _vs[53] = 3.777; _vs[54] = 3.786; _vs[55] = 3.795;
_vs[56] = 3.804; _vs[57] = 3.813; _vs[58] = 3.822; _vs[59] = 3.831; _vs[60] = 3.840;
_vs[61] = 3.849; _vs[62] = 3.858; _vs[63] = 3.867; _vs[64] = 3.876; _vs[65] = 3.885;
_vs[66] = 3.894; _vs[67] = 3.903; _vs[68] = 3.912; _vs[69] = 3.921; _vs[70] = 3.930;
_vs[71] = 3.939; _vs[72] = 3.948; _vs[73] = 3.957; _vs[74] = 3.966; _vs[75] = 3.975;
_vs[76] = 3.984; _vs[77] = 3.993; _vs[78] = 4.002; _vs[79] = 4.011; _vs[80] = 4.020;
_vs[81] = 4.029; _vs[82] = 4.038; _vs[83] = 4.047; _vs[84] = 4.056; _vs[85] = 4.065;
_vs[86] = 4.074; _vs[87] = 4.083; _vs[88] = 4.092; _vs[89] = 4.101; _vs[90] = 4.110;
_vs[91] = 4.119; _vs[92] = 4.128; _vs[93] = 4.137; _vs[94] = 4.146; _vs[95] = 4.155;
_vs[96] = 4.164; _vs[97] = 4.173; _vs[98] = 4.182; _vs[99] = 4.191; _vs[100] = 4.200;
}
int Pangodream_18650_CL::getBatteryChargeLevel()
{
int readValue = _analogRead(_addressPin);
double volts = _analogReadToVolts(readValue);
int chargeLevel = _getChargeLevel(volts);
return chargeLevel;
}
int Pangodream_18650_CL::pinRead(){
return _analogRead(_addressPin);
}
int Pangodream_18650_CL::_analogRead(int pinNumber){
int totalValue = 0;
int averageValue = 0;
for(int i = 0; i < _reads; i++){
totalValue += analogRead(pinNumber);
}
averageValue = totalValue / _reads;
return averageValue;
}
/**
* Performs a binary search to find the index corresponding to a voltage.
* The index of the array is the charge %
*/
int Pangodream_18650_CL::_getChargeLevel(double volts){
int idx = 50;
int prev = 0;
int half = 0;
if (volts >= 4.2){
return 100;
}
if (volts <= 3.2){
return 0;
}
while(true){
half = abs(idx - prev) / 2;
prev = idx;
if(volts >= _vs[idx]){
idx = idx + half;
}else{
idx = idx - half;
}
if (prev == idx){
break;
}
}
return idx;
}
double Pangodream_18650_CL::_analogReadToVolts(int readValue){
double volts;
volts = readValue * _convFactor / 1000;
return volts;
}
double Pangodream_18650_CL::getBatteryVolts(){
int readValue = analogRead(_addressPin);
return _analogReadToVolts(readValue);
}

View file

@ -0,0 +1,94 @@
/*
MIT License
Copyright (c) 2019 Pangodream
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
* 18650 Ion-Li battery charge
*/
#ifndef Pangodream_18650_CL_h
#define Pangodream_18650_CL_h
#include "Arduino.h"
#define DEF_PIN 34
#define DEF_CONV_FACTOR 1.7
#define DEF_READS 20
/*
* 18650 Ion-Li battery charge
* Calculates charge level of an 18650 Ion-Li battery
*/
class Pangodream_18650_CL {
public:
/*
* Constructor
* @param addressPin, ADC pin number where the voltage divider is connected to
*/
Pangodream_18650_CL(int addressPin);
/*
* Constructor
* @param addressPin, ADC pin number where the voltage divider is connected to
* @param convFactor, Convertion factor for analog read units to volts
*/
Pangodream_18650_CL(int addressPin, double convFactor);
/*
* Constructor
* @param addressPin, ADC pin number where the voltage divider is connected to
* @param convFactor, Convertion factor for analog read units to volts
* @param reads, Number of reads of analog pin to calculate an average value
*/
Pangodream_18650_CL(int addressPin, double convFactor, int reads);
/*
* Constructor
*/
Pangodream_18650_CL();
/*
* Get the battery charge level (0-100)
* @return The calculated battery charge level
*/
int getBatteryChargeLevel();
double getBatteryVolts();
int getAnalogPin();
int pinRead();
double getConvFactor();
private:
int _addressPin; //!< ADC pin used, default is GPIO34 - ADC1_6
int _reads; //Number of reads of ADC pin to calculate an average value
double _convFactor; //!< Convertion factor to translate analog units to volts
double _vs[101]; //Array with voltage - charge definitions
void _initVoltsArray();
int _getChargeLevel(double volts);
int _analogRead(int pinNumber);
double _analogReadToVolts(int readValue);
};
#endif

View file

@ -0,0 +1,7 @@
# See: https://github.com/codespell-project/codespell#using-a-config-file
[codespell]
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
ignore-words-list = ,
check-filenames =
check-hidden =
skip = ./.git

View file

@ -0,0 +1,10 @@
# See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file
version: 2
updates:
# Configure check for outdated GitHub Actions actions in workflows.
# See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot
- package-ecosystem: github-actions
directory: / # Check the repository's workflows under /.github/workflows/
schedule:
interval: daily

View file

@ -0,0 +1,28 @@
name: Check Arduino
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
pull_request:
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint.
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Arduino Lint
uses: arduino/arduino-lint-action@v1
with:
compliance: specification
library-manager: update
# Always use this setting for official repositories. Remove for 3rd party projects.
official: true
project-type: library

View file

@ -0,0 +1,70 @@
name: Compile Examples
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/compile-examples.yml"
- "examples/**"
- "**.c"
- "**.cpp"
- "**.h"
- "*.S"
pull_request:
paths:
- ".github/workflows/compile-examples.yml"
- "examples/**"
- "**.c"
- "**.cpp"
- "**.h"
- "*.S"
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
build:
name: ${{ matrix.board.fqbn }}
runs-on: ubuntu-latest
env:
SKETCHES_REPORTS_PATH: sketches-reports
strategy:
fail-fast: false
matrix:
board:
- fqbn: esp8266:esp8266:huzzah
platforms: |
- name: esp8266:esp8266
source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Compile examples
uses: arduino/compile-sketches@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fqbn: ${{ matrix.board.fqbn }}
platforms: ${{ matrix.board.platforms }}
libraries: |
# Install the library from the local path.
- source-path: ./
# Additional library dependencies can be listed here.
# See: https://github.com/arduino/compile-sketches#libraries
sketch-paths: |
- examples
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
- name: Save sketches report as workflow artifact
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
path: ${{ env.SKETCHES_REPORTS_PATH }}
name: ${{ env.SKETCHES_REPORTS_PATH }}

View file

@ -0,0 +1,24 @@
name: Report Size Deltas
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/report-size-deltas.yml"
schedule:
# Run at the minimum interval allowed by GitHub Actions.
# Note: GitHub Actions periodically has outages which result in workflow failures.
# In this event, the workflows will start passing again once the service recovers.
- cron: "*/5 * * * *"
workflow_dispatch:
repository_dispatch:
jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Comment size deltas reports to PRs
uses: arduino/report-size-deltas@v1
with:
# The name of the workflow artifact created by the sketch compilation workflow
sketches-reports-source: sketches-reports

View file

@ -0,0 +1,22 @@
name: Spell Check
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
pull_request:
schedule:
# Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates.
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Spell check
uses: codespell-project/actions-codespell@master

View file

@ -0,0 +1,138 @@
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md
name: Sync Labels
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/sync-labels.ya?ml"
- ".github/label-configuration-files/*.ya?ml"
pull_request:
paths:
- ".github/workflows/sync-labels.ya?ml"
- ".github/label-configuration-files/*.ya?ml"
schedule:
# Run daily at 8 AM UTC to sync with changes to shared label configurations.
- cron: "0 8 * * *"
workflow_dispatch:
repository_dispatch:
env:
CONFIGURATIONS_FOLDER: .github/label-configuration-files
CONFIGURATIONS_ARTIFACT: label-configuration-files
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Download JSON schema for labels configuration file
id: download-schema
uses: carlosperate/download-file-action@v1
with:
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
location: ${{ runner.temp }}/label-configuration-schema
- name: Install JSON schema validator
run: |
sudo npm install \
--global \
ajv-cli \
ajv-formats
- name: Validate local labels configuration
run: |
# See: https://github.com/ajv-validator/ajv-cli#readme
ajv validate \
--all-errors \
-c ajv-formats \
-s "${{ steps.download-schema.outputs.file-path }}" \
-d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}"
download:
needs: check
runs-on: ubuntu-latest
strategy:
matrix:
filename:
# Filenames of the shared configurations to apply to the repository in addition to the local configuration.
# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels
- universal.yml
steps:
- name: Download
uses: carlosperate/download-file-action@v1
with:
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
- name: Pass configuration files to next job via workflow artifact
uses: actions/upload-artifact@v3
with:
path: |
*.yaml
*.yml
if-no-files-found: error
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
sync:
needs: download
runs-on: ubuntu-latest
steps:
- name: Set environment variables
run: |
# See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV"
- name: Determine whether to dry run
id: dry-run
if: >
github.event_name == 'pull_request' ||
(
(
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch'
) &&
github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
)
run: |
# Use of this flag in the github-label-sync command will cause it to only check the validity of the
# configuration.
echo "::set-output name=flag::--dry-run"
- name: Checkout repository
uses: actions/checkout@v3
- name: Download configuration files artifact
uses: actions/download-artifact@v3
with:
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
path: ${{ env.CONFIGURATIONS_FOLDER }}
- name: Remove unneeded artifact
uses: geekyeggo/delete-artifact@v1
with:
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
- name: Merge label configuration files
run: |
# Merge all configuration files
shopt -s extglob
cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}"
- name: Install github-label-sync
run: sudo npm install --global github-label-sync
- name: Sync labels
env:
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# See: https://github.com/Financial-Times/github-label-sync
github-label-sync \
--labels "${{ env.MERGED_CONFIGURATION_PATH }}" \
${{ steps.dry-run.outputs.flag }} \
${{ github.repository }}

View file

@ -1,10 +0,0 @@
language: c
sudo: false
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
script:
- build_platform esp8266
notifications:
email:
on_success: change
on_failure: change

140
lib/NTPClient-master/NTPClient.cpp Normal file → Executable file
View file

@ -25,7 +25,7 @@ NTPClient::NTPClient(UDP& udp) {
this->_udp = &udp;
}
NTPClient::NTPClient(UDP& udp, int timeOffset) {
NTPClient::NTPClient(UDP& udp, long timeOffset) {
this->_udp = &udp;
this->_timeOffset = timeOffset;
}
@ -35,24 +35,45 @@ NTPClient::NTPClient(UDP& udp, const char* poolServerName) {
this->_poolServerName = poolServerName;
}
NTPClient::NTPClient(UDP& udp, const char* poolServerName, int timeOffset) {
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP) {
this->_udp = &udp;
this->_poolServerIP = poolServerIP;
this->_poolServerName = NULL;
}
NTPClient::NTPClient(UDP& udp, const char* poolServerName, long timeOffset) {
this->_udp = &udp;
this->_timeOffset = timeOffset;
this->_poolServerName = poolServerName;
}
NTPClient::NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval) {
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset){
this->_udp = &udp;
this->_timeOffset = timeOffset;
this->_poolServerIP = poolServerIP;
this->_poolServerName = NULL;
}
NTPClient::NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval) {
this->_udp = &udp;
this->_timeOffset = timeOffset;
this->_poolServerName = poolServerName;
this->_updateInterval = updateInterval;
}
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval) {
this->_udp = &udp;
this->_timeOffset = timeOffset;
this->_poolServerIP = poolServerIP;
this->_poolServerName = NULL;
this->_updateInterval = updateInterval;
}
void NTPClient::begin() {
this->begin(NTP_DEFAULT_LOCAL_PORT);
}
void NTPClient::begin(int port) {
void NTPClient::begin(unsigned int port) {
this->_port = port;
this->_udp->begin(this->_port);
@ -60,37 +81,15 @@ void NTPClient::begin(int port) {
this->_udpSetup = true;
}
bool NTPClient::isValid(byte * ntpPacket)
{
//Perform a few validity checks on the packet
if((ntpPacket[0] & 0b11000000) == 0b11000000) //Check for LI=UNSYNC
return false;
if((ntpPacket[0] & 0b00111000) >> 3 < 0b100) //Check for Version >= 4
return false;
if((ntpPacket[0] & 0b00000111) != 0b100) //Check for Mode == Server
return false;
if((ntpPacket[1] < 1) || (ntpPacket[1] > 15)) //Check for valid Stratum
return false;
if( ntpPacket[16] == 0 && ntpPacket[17] == 0 &&
ntpPacket[18] == 0 && ntpPacket[19] == 0 &&
ntpPacket[20] == 0 && ntpPacket[21] == 0 &&
ntpPacket[22] == 0 && ntpPacket[22] == 0) //Check for ReferenceTimestamp != 0
return false;
return true;
}
bool NTPClient::forceUpdate() {
#ifdef DEBUG_NTPClient
Serial.println("Update from NTP Server");
#endif
// flush any existing packets
while(this->_udp->parsePacket() != 0)
this->_udp->flush();
this->sendNTPPacket();
// Wait till data is there or timeout...
@ -99,20 +98,14 @@ bool NTPClient::forceUpdate() {
do {
delay ( 10 );
cb = this->_udp->parsePacket();
if(cb > 0)
{
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
if(!this->isValid(this->_packetBuffer))
cb = 0;
}
if (timeout > 100) return false; // timeout after 1000 ms
timeout++;
} while (cb == 0);
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
// combine the four bytes (two words) into a long integer
@ -121,39 +114,43 @@ bool NTPClient::forceUpdate() {
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
return true;
return true; // return true after successful update
}
bool NTPClient::update() {
if ((millis() - this->_lastUpdate >= this->_updateInterval) // Update after _updateInterval
|| this->_lastUpdate == 0) { // Update if there was no update yet.
if (!this->_udpSetup) this->begin(); // setup the UDP client if needed
if (!this->_udpSetup || this->_port != NTP_DEFAULT_LOCAL_PORT) this->begin(this->_port); // setup the UDP client if needed
return this->forceUpdate();
}
return true;
return false; // return false if update does not occur
}
unsigned long NTPClient::getEpochTime() {
bool NTPClient::isTimeSet() const {
return (this->_lastUpdate != 0); // returns true if the time has been set, else false
}
unsigned long NTPClient::getEpochTime() const {
return this->_timeOffset + // User offset
this->_currentEpoc + // Epoc returned by the NTP server
this->_currentEpoc + // Epoch returned by the NTP server
((millis() - this->_lastUpdate) / 1000); // Time since last update
}
int NTPClient::getDay() {
int NTPClient::getDay() const {
return (((this->getEpochTime() / 86400L) + 4 ) % 7); //0 is Sunday
}
int NTPClient::getHours() {
int NTPClient::getHours() const {
return ((this->getEpochTime() % 86400L) / 3600);
}
int NTPClient::getMinutes() {
int NTPClient::getMinutes() const {
return ((this->getEpochTime() % 3600) / 60);
}
int NTPClient::getSeconds() {
int NTPClient::getSeconds() const {
return (this->getEpochTime() % 60);
}
String NTPClient::getFormattedTime(unsigned long secs) {
unsigned long rawTime = secs ? secs : this->getEpochTime();
String NTPClient::getFormattedTime() const {
unsigned long rawTime = this->getEpochTime();
unsigned long hours = (rawTime % 86400L) / 3600;
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);
@ -166,33 +163,6 @@ String NTPClient::getFormattedTime(unsigned long secs) {
return hoursStr + ":" + minuteStr + ":" + secondStr;
}
// Based on https://github.com/PaulStoffregen/Time/blob/master/Time.cpp
// currently assumes UTC timezone, instead of using this->_timeOffset
String NTPClient::getFormattedDate(unsigned long secs) {
unsigned long rawTime = (secs ? secs : this->getEpochTime()) / 86400L; // in days
unsigned long days = 0, year = 1970;
uint8_t month;
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31};
while((days += (LEAP_YEAR(year) ? 366 : 365)) <= rawTime)
year++;
rawTime -= days - (LEAP_YEAR(year) ? 366 : 365); // now it is days in this year, starting at 0
days=0;
for (month=0; month<12; month++) {
uint8_t monthLength;
if (month==1) { // february
monthLength = LEAP_YEAR(year) ? 29 : 28;
} else {
monthLength = monthDays[month];
}
if (rawTime < monthLength) break;
rawTime -= monthLength;
}
String monthStr = ++month < 10 ? "0" + String(month) : String(month); // jan is month 1
String dayStr = ++rawTime < 10 ? "0" + String(rawTime) : String(rawTime); // day of month
return String(year) + "-" + monthStr + "-" + dayStr + "T" + this->getFormattedTime(secs ? secs : 0) + "Z";
}
void NTPClient::end() {
this->_udp->stop();
@ -207,28 +177,36 @@ void NTPClient::setUpdateInterval(unsigned long updateInterval) {
this->_updateInterval = updateInterval;
}
void NTPClient::setPoolServerName(const char* poolServerName) {
this->_poolServerName = poolServerName;
}
void NTPClient::sendNTPPacket() {
// set all bytes in the buffer to 0
memset(this->_packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode
this->_packetBuffer[1] = 0; // Stratum, or type of clock
this->_packetBuffer[2] = 6; // Polling Interval
this->_packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
this->_packetBuffer[12] = 0x49;
this->_packetBuffer[12] = 49;
this->_packetBuffer[13] = 0x4E;
this->_packetBuffer[14] = 0x49;
this->_packetBuffer[15] = 0x52;
this->_packetBuffer[14] = 49;
this->_packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
this->_udp->beginPacket(this->_poolServerName, 123); //NTP requests are to port 123
if (this->_poolServerName) {
this->_udp->beginPacket(this->_poolServerName, 123);
} else {
this->_udp->beginPacket(this->_poolServerIP, 123);
}
this->_udp->write(this->_packetBuffer, NTP_PACKET_SIZE);
this->_udp->endPacket();
}
void NTPClient::setEpochTime(unsigned long secs) {
this->_currentEpoc = secs;
void NTPClient::setRandomPort(unsigned int minValue, unsigned int maxValue) {
randomSeed(analogRead(0));
this->_port = random(minValue, maxValue);
}

65
lib/NTPClient-master/NTPClient.h Normal file → Executable file
View file

@ -7,8 +7,6 @@
#define SEVENZYYEARS 2208988800UL
#define NTP_PACKET_SIZE 48
#define NTP_DEFAULT_LOCAL_PORT 1337
#define LEAP_YEAR(Y) ( (Y>0) && !(Y%4) && ( (Y%100) || !(Y%400) ) )
class NTPClient {
private:
@ -16,8 +14,9 @@ class NTPClient {
bool _udpSetup = false;
const char* _poolServerName = "pool.ntp.org"; // Default time server
int _port = NTP_DEFAULT_LOCAL_PORT;
int _timeOffset = 0;
IPAddress _poolServerIP;
unsigned int _port = NTP_DEFAULT_LOCAL_PORT;
long _timeOffset = 0;
unsigned long _updateInterval = 60000; // In ms
@ -27,14 +26,28 @@ class NTPClient {
byte _packetBuffer[NTP_PACKET_SIZE];
void sendNTPPacket();
bool isValid(byte * ntpPacket);
public:
NTPClient(UDP& udp);
NTPClient(UDP& udp, int timeOffset);
NTPClient(UDP& udp, long timeOffset);
NTPClient(UDP& udp, const char* poolServerName);
NTPClient(UDP& udp, const char* poolServerName, int timeOffset);
NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval);
NTPClient(UDP& udp, const char* poolServerName, long timeOffset);
NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval);
NTPClient(UDP& udp, IPAddress poolServerIP);
NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset);
NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval);
/**
* Set time server name
*
* @param poolServerName
*/
void setPoolServerName(const char* poolServerName);
/**
* Set random local port
*/
void setRandomPort(unsigned int minValue = 49152, unsigned int maxValue = 65535);
/**
* Starts the underlying UDP client with the default local port
@ -44,7 +57,7 @@ class NTPClient {
/**
* Starts the underlying UDP client with the specified local port
*/
void begin(int port);
void begin(unsigned int port);
/**
* This should be called in the main loop of your application. By default an update from the NTP Server is only
@ -61,10 +74,17 @@ class NTPClient {
*/
bool forceUpdate();
int getDay();
int getHours();
int getMinutes();
int getSeconds();
/**
* This allows to check if the NTPClient successfully received a NTP packet and set the time.
*
* @return true if time has been set, else false
*/
bool isTimeSet() const;
int getDay() const;
int getHours() const;
int getMinutes() const;
int getSeconds() const;
/**
* Changes the time offset. Useful for changing timezones dynamically
@ -78,28 +98,17 @@ class NTPClient {
void setUpdateInterval(unsigned long updateInterval);
/**
* @return secs argument (or 0 for current time) formatted like `hh:mm:ss`
*/
String getFormattedTime(unsigned long secs = 0);
* @return time formatted like `hh:mm:ss`
*/
String getFormattedTime() const;
/**
* @return time in seconds since Jan. 1, 1970
*/
unsigned long getEpochTime();
/**
* @return secs argument (or 0 for current date) formatted to ISO 8601
* like `2004-02-12T15:19:21+00:00`
*/
String getFormattedDate(unsigned long secs = 0);
unsigned long getEpochTime() const;
/**
* Stops the underlying UDP client
*/
void end();
/**
* Replace the NTP-fetched time with seconds since Jan. 1, 1970
*/
void setEpochTime(unsigned long secs);
};

View file

@ -1,6 +1,8 @@
# NTPClient
[![Build Status](https://travis-ci.org/arduino-libraries/NTPClient.svg?branch=master)](https://travis-ci.org/arduino-libraries/NTPClient)
[![Check Arduino status](https://github.com/arduino-libraries/NTPClient/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/NTPClient/actions/workflows/check-arduino.yml)
[![Compile Examples status](https://github.com/arduino-libraries/NTPClient/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/NTPClient/actions/workflows/compile-examples.yml)
[![Spell Check status](https://github.com/arduino-libraries/NTPClient/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/NTPClient/actions/workflows/spell-check.yml)
Connect to a NTP server, here is how:
@ -22,7 +24,7 @@ WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// You can specify the time server pool and the offset, (in seconds)
// additionaly you can specify the update interval (in milliseconds).
// additionally you can specify the update interval (in milliseconds).
// NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
void setup(){
@ -45,3 +47,6 @@ void loop() {
delay(1000);
}
```
## Function documentation
`getEpochTime` returns the Unix epoch, which are the seconds elapsed since 00:00:00 UTC on 1 January 1970 (leap seconds are ignored, every day is treated as having 86400 seconds). **Attention**: If you have set a time offset this time offset will be added to your epoch timestamp.

View file

@ -11,7 +11,7 @@ const char *password = "<PASSWORD>";
WiFiUDP ntpUDP;
// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// changed later with setTimeOffset() ). Additionally you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

View file

@ -0,0 +1,53 @@
#include <NTPClient.h>
// change next line to use with another board/shield
#include <ESP8266WiFi.h>
//#include <WiFi.h> // for WiFi shield
//#include <WiFi101.h> // for WiFi 101 shield or MKR1000
#include <WiFiUdp.h>
const char *ssid = "<SSID>";
const char *password = "<PASSWORD>";
WiFiUDP ntpUDP;
// initialized to a time offset of 10 hours
NTPClient timeClient(ntpUDP,"pool.ntp.org", 36000, 60000);
// HH:MM:SS
// timeClient initializes to 10:00:00 if it does not receive an NTP packet
// before the 100ms timeout.
// without isTimeSet() the LED would be switched on, although the time
// was not yet set correctly.
// blue LED on ESP-12F
const int led = 2;
const int hour = 10;
const int minute = 0;
void setup(){
Serial.begin(115200);
pinMode(led, OUTPUT);
// led is off when pin is high
digitalWrite(led, 1);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay (500);
Serial.print (".");
}
timeClient.begin();
}
void loop() {
timeClient.update();
Serial.println(timeClient.getFormattedTime());
if(timeClient.isTimeSet()) {
if (hour == timeClient.getHours() && minute == timeClient.getMinutes()) {
digitalWrite(led, 0);
}
}
delay(1000);
}

View file

@ -12,9 +12,13 @@ begin KEYWORD2
end KEYWORD2
update KEYWORD2
forceUpdate KEYWORD2
isTimeSet KEYWORD2
getDay KEYWORD2
getHours KEYWORD2
getMinutes KEYWORD2
getSeconds KEYWORD2
getFormattedTime KEYWORD2
getEpochTime KEYWORD2
setTimeOffset KEYWORD2
setUpdateInterval KEYWORD2
setPoolServerName KEYWORD2

View file

@ -1,24 +0,0 @@
{
"name": "NTPClient",
"keywords": "ntp, client, time",
"description": "A NTPClient to connect to a time server",
"authors":
[
{
"name": "Fabrice Weinberg",
"email": "fabrice@weinberg.me"
},
{
"name": "Sandeep Mistry",
"email": "s.mistry@arduino.cc"
}
],
"repository":
{
"type": "git",
"url": "https://github.com/arduino-libraries/NTPClient.git"
},
"version": "3.1.0",
"frameworks": "arduino",
"platforms": "espressif"
}

View file

@ -1,5 +1,5 @@
name=NTPClient
version=3.1.0
version=3.2.1
author=Fabrice Weinberg
maintainer=Fabrice Weinberg <fabrice@weinberg.me>
sentence=An NTPClient to connect to a time server

View file

@ -1,55 +0,0 @@
import paho.mqtt.client as mqttClient
from influxdb import InfluxDBClient
import time
TOPIC = "test1"
broker_address= "localhost"
port = 1883
database = "thermo-bibli"
nom_client = "capteurs1"
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe(TOPIC, 2)
def addData(database, time, numero_grappe, numero_capteur, temp, hum, batterie): # ajoute donnée à base de donnée influxDB
client = InfluxDBClient(host='localhost', port=8086)
client.create_database(database)
client.switch_database(database)
data = [
{
"measurement": numero_grappe,
"tags": {"numero_capteur": numero_capteur},
"time": time,
"fields": {"temperature": temp, "humidite": hum, "batterie": batterie}
}
]
client.write_points(data)
def on_message(client, userdata, message):
message = (message.payload).decode("utf-8") # convertit type bytes en string
print("Message reçu")
tab = message.split("|")
temp = tab[2].split()
hum = tab[3].split()
batterie = tab[4]
L = len(temp)
for i in range(L):
addData(database, tab[0], tab[1], "capteur" + str(i+1), temp[i], hum[i], batterie)
client = mqttClient.Client(nom_client, False)
client.username_pw_set(username="capteurs",password="Fablab")
client.on_connect= on_connect #callback
client.on_message= on_message #callback
client.connect(broker_address, port, 65535)
client.loop_start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
print ("exiting")
client.disconnect()
client.loop_stop()

100
mqtt-python.py Normal file
View file

@ -0,0 +1,100 @@
#!/usr/bin/python3
#lib pour faire le timestamp
#from datetime import datetime
#lib pour ecoute mqtt
import paho.mqtt.client as mqttClient
import time
import sys
#http request lib
import requests
from aiohttp import ClientSession
##################################################################################################
#var mqtt
TOPIC = "test"
broker_address= "localhost"
port = 1883
nom_client = "serveur-test"
#var influx
influx_bucket = "Fablab" #database
influx_token = "QRzx929_X67sunqmY6xpS65fM7ff7Gy_Fz4ZD2qAT7eaR8Jps-9CZtEkot5Z01CQ-q1tq87IRyahXGebsSEzxV==" #token
influx_org="Fablab"
influx_url=f"http://localhost:8086/api/v2/write?org={influx_org}&bucket={influx_bucket}&precision=s"
#########################################################################################################
#http
async def get(session: object, url: object) -> object:
async with session.get(url) as response:
return await response.text()
#enregistre dans un fichier pour debug
def log(time):
f = open("/var/log/mqtt-influxdb/date.txt", "a")
f.write(time + "\n")
f.close()
def dump_log(text):
f = open("/var/log/mqtt-influxdb/dumped_message_thermo-fablab", "a")
f.write(text + "\n")
f.close()
#envois les donnees a influx via l'apiv2
def addData(time, numero_grappe, numero_capteur, temp, hum, batterie): # ajoute donnée à base de donnée influxDB
Headers = {"Authorization": f"Token {influx_token}"}
#data envoye a l'api
int_time = int(time)
#if (int_time > 1817589156):
# time = str(int_time - 368384901)
Data=f"{numero_grappe},numero_capteur={numero_capteur} temperature={temp},humidite={hum},batterie={batterie} {time}"
print(Data)
response = requests.post(influx_url, headers=Headers, data=Data)
print(response.status_code)
#debug api, fonctionne correctement malgres le code retour 204, quand il y a un code 204 le json response fait une erreur
#print("Status Code", response.status_code)
#print("JSON Response ", response.json())
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe(TOPIC, 2)
def on_message(client, userdata, message):
message = (message.payload).decode("utf-8") # convertit type bytes en string
print("\nMessage reçu")
tab = message.split("|")
temp = tab[2].split()
hum = tab[3].split()
batterie = tab[4]
L = len(temp)
time=tab[0]
#envois la valeur temps reçu pour le debug
#log(time + " reçu")
for i in range(L):
addData(time, tab[1], "capteur" + str(i+1), temp[i], hum[i], batterie)
#log("---------")
#envois la valeur message pour le debug
#dump_log(message)
client = mqttClient.Client(nom_client, False)
client.username_pw_set(username="capteurs",password="Fablab")
client.on_connect= on_connect #callback
client.on_message= on_message #callback
client.connect(broker_address, port, 65535)
client.loop_start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
print ("exiting")
client.disconnect()
client.loop_stop()

View file

@ -4,13 +4,14 @@
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
[env:esp32_olimex_devKit_Lipo]
platform = espressif32
board = esp32dev
board = esp32-devkitlipo
framework = arduino
lib_deps =
adafruit/DHT sensor library@^1.4.2
@ -18,4 +19,4 @@ lib_deps =
knolleary/PubSubClient@^2.8
ottowinter/ESPAsyncWebServer-esphome@^1.2.7
ottowinter/AsyncTCP-esphome@^1.2.1
arduino-libraries/NTPClient@^3.1.0
arduino-libraries/NTPClient@^3.1.0

View file

@ -1,171 +1,681 @@
#include "main.h"
using namespace std;
DHT sensors[SENSORS_NUMBER] = {DHT(23, DHT22), DHT(22, DHT22), DHT(21, DHT22), DHT(17, DHT22), DHT(2, DHT22)};
float temp[SENSORS_NUMBER];
float hum[SENSORS_NUMBER];
WiFiClient WifiClient;
PubSubClient MqttClient(WifiClient);
WiFiUDP NtpUDP;
NTPClient TimeClient(NtpUDP, "europe.pool.ntp.org", 0, 60000);
Pangodream_18650_CL Battery(ADC_PIN, CONV_FACTOR, READS);
//-------------------- FONCTIONS --------------------//
//-------------- Connexion MQTT --------------//
void setupMQTT(const char *address, int port)
{
MqttClient.setServer(address, port);
}
void setupWIFI(const char *wifi_name, const char *password)
{
Serial.println('\n');
WiFi.begin(wifi_name, password);
Serial.print("Connecting to ");
Serial.print(wifi_name);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print('.');
}
Serial.println('\n');
Serial.println("Connection established!");
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
}
void reconnect(void)
{
Serial.println("Connecting to MQTT Broker...");
while (!MqttClient.connected())
{
Serial.print(".");
if (MqttClient.connect(ESPNAME, MQTT_USER, MQTT_PWD))
{
Serial.println("Connected.");
}
}
}
//-------------- Initialisation et lecture des capteurs --------------//
void initSensors(DHT *sensors, int number)
{
int i;
for (i = 0; i < number; i++)
{
sensors[i].begin();
}
}
void readSensors(DHT sensors[], float temp[], float hum[], int number)
{
int i;
for (i = 0; i < number; i++)
{
*(temp + i) = sensors[i].readTemperature();
*(hum + i) = sensors[i].readHumidity();
}
}
//-------------------- Sleep de l'ESP --------------------//
void sleep()
{
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * US_TO_S_FACTOR);
esp_deep_sleep_start();
}
//exemple d'une triple utilisation de valeur pour une fonction utilise pour la date
std::tuple<int, int, int> getDate()
{
time_t rawtime = TimeClient.getEpochTime();
struct tm *ti;
ti = localtime(&rawtime);
int year = ti->tm_year + 1900;
int month = (ti->tm_mon + 1) < 10 ? 0 + (ti->tm_mon + 1) : (ti->tm_mon + 1);
int day = (ti->tm_mday) < 10 ? 0 + (ti->tm_mday) : (ti->tm_mday);
return std::make_tuple(year, month, day);
}
//-------------------- Création de trames --------------------//
void writeMessage(char *txt, float *temp, float *hum, int number)
{
int chargelvl = Battery.getBatteryChargeLevel();
switch (number)
{
case 1:
sprintf(txt, "|%s|%0.2f|%0.2f", CLUSTER, temp[0], hum[0]);
break;
case 2:
sprintf(txt, "|%s|%0.2f %0.2f|%0.2f %0.2f", CLUSTER, temp[0], temp[1], hum[0], hum[1]);
break;
case 3:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], hum[0], hum[1], hum[2]);
break;
case 4:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], hum[0], hum[1], hum[2], hum[3]);
break;
case 5:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f|%d", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], hum[0], hum[1], hum[2], hum[3], hum[4], chargelvl);
break;
case 6:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], hum[0], hum[1], hum[2], hum[3], hum[4], hum[5]);
break;
default:
Serial.println("Erreur, temp et hum sont trop longs : trop de capteurs");
break;
}
}
//-------------------- Initialisation --------------------//
void setup()
{
Serial.begin(9600);
setupWIFI(SSID, PWD);
setupMQTT(MQTT_ADDRESS, MQTT_PORT);
initSensors(sensors, SENSORS_NUMBER);
TimeClient.begin();
}
//-------------------- Boucle pricipale --------------------//
void loop()
{
int year, month, day;
int lenght;
char time[30];
char date[30];
char msg[70];
MqttClient.loop();
if (!MqttClient.connected())
{
reconnect();
}
readSensors(sensors, temp, hum, SENSORS_NUMBER);
writeMessage(msg, temp, hum, SENSORS_NUMBER);
TimeClient.update();
TimeClient.getFormattedTime().toCharArray(time, 30);
tie(year, month, day) = getDate();
lenght = sprintf(date, "%d-%d-%d ", year, month, day);
sprintf(date + lenght, time);
sprintf(date + strlen(date), msg);
MqttClient.publish(TOPIC, date);
delay(2000);
sleep();
#include "main.h"
#include "NTPClient.h"
#include <sys/time.h>
#include <nvs_flash.h>
#include <ctime>
#include <iostream>
#include <chrono>
#include "Preferences.h"
#define STORAGE_NAMESPACE "storage"
#define _OPEN_SYS_ITOA_EXT
#define RESTART 1
#define REFRESHMEMBOOT 0
#define RESTARTTIMES 2
#define REFRESHTIMES 4
using namespace std;
Preferences preferences;
// Array of DHT sensors with their respective pins and types
DHT sensors[SENSORS_NUMBER] = {DHT(04, DHT22), DHT(18, DHT22), DHT(05, DHT22), DHT(17, DHT22), DHT(16, DHT22)};
// Arrays to store temperature and humidity readings
float temp[SENSORS_NUMBER];
float hum[SENSORS_NUMBER];
// Pangodream_18650_CL battery object with ADC pin, conversion factor, and number of reads
Pangodream_18650_CL Battery(ADC_PIN, CONV_FACTOR, READS);
// WiFi client object
WiFiClient WifiClient;
// PubSubClient object for MQTT communication
PubSubClient MqttClient(WifiClient);
// UDP object for NTP communication
WiFiUDP NtpUDP;
// NTP client object with UDP and NTP server address
NTPClient TimeClient(NtpUDP, "192.168.23.254"); /*si vous utilisez le Wifi du fablab*/
// NTPClient TimeClient(NtpUDP, "europe.pool.ntp.org"); /*si vous utilisez un réseau 4g ou autre */
//-------------------- CONDITION --------------------//
/**
* @brief Test if the time is good for restart or refresh memory
*
* @param hours
* @param minutes
* @param restart bool to choose which the restart time bool or the refresh time bool will be returned
* @return true It's time to refresh or restart
* @return false It's not the time to refresh or restart
*/
bool testTime(int hours, int minutes, bool restart)
{
// debug parts
// Serial.println('\n');
// Serial.println((REFRESHTIMES * TIME_TO_SLEEP) / 3600,DEC);
// Serial.println(((REFRESHTIMES * TIME_TO_SLEEP) % 3600) / 60,DEC);
// Serial.println('\n');
if (restart)
{ // restart parts
if (hours < (RESTARTTIMES * TIME_TO_SLEEP) / 3600)
return true;
else
{
if ((hours = (RESTARTTIMES * TIME_TO_SLEEP) / 3600) && (minutes <= ((RESTARTTIMES * TIME_TO_SLEEP) % 3600) / 60))
return true;
return false;
}
}
else
{ // refresh parts
if (hours >= (RESTARTTIMES * TIME_TO_SLEEP) / 3600)
{
if (hours < (REFRESHTIMES * TIME_TO_SLEEP) / 3600)
return true;
else
{
if ((hours = (REFRESHTIMES * TIME_TO_SLEEP) / 3600) && (minutes <= ((REFRESHTIMES * TIME_TO_SLEEP) % 3600) / 60))
return true;
else
{
return false;
}
}
}
}
// Not needed but carefully habits
return false;
}
//-------------------- FONCTIONS --------------------//
//-------------- Connexion MQTT --------------//
/**
* @brief Set up MQTT server with address and port
*
* @param address MQTT server address
* @param port MQTT server port
*/
void setupMQTT(const char *address, int port)
{
MqttClient.setServer(address, port);
}
/**
* @brief Set up WiFi connection with SSID and password
*
* @param wifi_name WiFi SSID
* @param password WiFi password
*/
void setupWIFI(const char *wifi_name, const char *password)
{
Serial.println('\n');
WiFi.begin(wifi_name, password);
Serial.print("Connecting to ");
Serial.print(wifi_name);
int cpttry = 10;
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print('.');
/* stop trying wifi connexion */
cpttry--;
if (cpttry == 0)
{
Serial.print("wifi: 10 try go to sleep");
sleep();
}
}
Serial.println('\n');
Serial.println("Connection established!");
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
}
void reconnect(void)
{
Serial.println("\n Connecting to MQTT Broker...");
int cpttry = 10;
while (!MqttClient.connected())
{
/* stop trying mqtt connexion */
cpttry--;
if (cpttry == 0)
{
Serial.print("Mqtt: 10 try go to sleep");
LocalSave();
sleep();
}
Serial.print(".");
if (MqttClient.connect(ESPNAME, MQTT_USER, MQTT_MDP)) // MQTT_MDP (mot de passe)
{
Serial.println("Connected.");
}
}
}
//-------------- Initialisation et lecture des capteurs --------------//
/**
* @brief Initialize DHT sensors
*
* @param sensors array of DHT sensors
* @param number number of sensors
*/
void initSensors(DHT *sensors, int number)
{
int i;
for (i = 0; i < number; i++)
{
sensors[i].begin();
}
}
/**
* @brief Read temperature and humidity from DHT sensors
*
* @param sensors array of DHT sensors
* @param temp array to store temperature readings
* @param hum array to store humidity readings
* @param number number of sensors
*/
void readSensors(DHT sensors[], float temp[], float hum[], int number)
{
int i;
for (i = 0; i < number; i++)
{
*(temp + i) = sensors[i].readTemperature();
*(hum + i) = sensors[i].readHumidity();
}
}
//-------------------- Sleep de l'ESP --------------------//
/**
* @brief Put ESP into deep sleep mode
*/
void sleep()
{
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * US_TO_S_FACTOR);
esp_deep_sleep_start();
}
// exemple d'une triple utilisation de valeur pour une fonction utilise pour la date
std::tuple<int, int, int> getDate()
{
struct timeval synctime;
TimeClient.forceUpdate();
time_t rawtime = TimeClient.getEpochTime();
synctime.tv_sec = rawtime;
synctime.tv_usec = 0;
if (settimeofday(&synctime, NULL) != 0)
std::cout << "error\n";
// set timezone to France
setenv("TZ", "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", 2); // set at 2 or 3 (Third parameter)
tzset();
struct tm *ti;
ti = localtime(&rawtime);
int year = ti->tm_year + 1900;
int month = (ti->tm_mon + 1) < 10 ? 0 + (ti->tm_mon + 1) : (ti->tm_mon + 1);
int day = (ti->tm_mday) < 10 ? 0 + (ti->tm_mday) : (ti->tm_mday);
return std::make_tuple(year, month, day);
}
// Function that gets current epoch time
unsigned long getTime()
{
time_t now = TimeClient.getEpochTime();
struct timeval synctime;
struct tm timeinfo;
synctime.tv_sec = now;
synctime.tv_usec = 0;
if (settimeofday(&synctime, NULL) != 0)
std::cout << "error\n";
// TimeClient.forceUpdate(); //cette ligne crée un bug avec l'heure quand on est connecté au réseau du fablab
vTaskDelay(1000);
if (!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain time");
return (0);
}
time(&now);
Serial.println(now);
return now;
}
int getAverageChargeLevel()
{
const int moyenne = 10;
int charge[moyenne];
int total = 0;
for (int i = 0; i < moyenne; i++)
{
charge[i] = Battery.getBatteryChargeLevel(); // Assurez-vous que Battery.getBatteryChargeLevel() est défini
total += charge[i];
}
int chargelvl = total / moyenne;
return chargelvl;
}
//-------------------- Création de trames --------------------//
/**
* @brief Create message frame with temperature and humidity readings
*
* @param txt message buffer
* @param temp array of temperature readings
* @param hum array of humidity readings
* @param number number of sensors
*/
void writeMessage(char *txt, float *temp, float *hum, int number)
{
int chargelvl = getAverageChargeLevel();
delay(2000);
switch (number)
{
case 1:
sprintf(txt, "|%s|%0.2f|%0.2f", CLUSTER, temp[0], hum[0]);
break;
case 2:
sprintf(txt, "|%s|%0.2f %0.2f|%0.2f %0.2f", CLUSTER, temp[0], temp[1], hum[0], hum[1]);
break;
case 3:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], hum[0], hum[1], hum[2]);
break;
case 4:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], hum[0], hum[1], hum[2], hum[3]);
break;
case 5:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f|%d", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], hum[0], hum[1], hum[2], hum[3], hum[4], chargelvl);
break;
case 6:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], hum[0], hum[1], hum[2], hum[3], hum[4], hum[5]);
break;
default:
Serial.println("Erreur, temp et hum sont trop longs : trop de capteurs");
break;
}
}
//-------------------- read, refresh and return the day boot state --------------------//
/**
* @brief Read, refresh and return the day boot state
*
* @return bool at true if the esp was restarted or false if error or not restarted
* @inspired of https://github.com/espressif/esp-idf/blob/master/examples/storage/nvs_rw_blob/main/nvs_blob_example_main.c
*/
bool TestBoot(bool resOrRfsh)
{
nvs_handle_t my_handle;
esp_err_t err;
bool booted = false;
// Serial.println("Test");
// Open
err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);
if (err != ESP_OK)
{
Serial.println("Erreur open nvs persistant storage");
return false;
}
/******** Refresh part ********/
if (resOrRfsh == REFRESHMEMBOOT)
{
int32_t restart = REFRESHMEMBOOT;
err = nvs_set_i32(my_handle, "restart", restart);
if (err != ESP_OK)
{
Serial.println("Erreur write nvs persistant storage");
return false;
}
// Commit written value.
// After setting any values, nvs_commit() must be called to ensure changes are written
// to flash storage. Implementations may write to storage at other times,
// but this is not guaranteed.
err = nvs_commit(my_handle);
if (err != ESP_OK)
return err;
// Close
nvs_close(my_handle);
Serial.println("Refresh memory restart state ");
return false;
}
// Read
int32_t restart = 0; // value will default to 0, if not set yet in NVS
err = nvs_get_i32(my_handle, "restart", &restart);
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
{
Serial.println("Erreur read nvs persistant storage");
return false;
}
if (!restart)
{
// Write
restart = 1;
err = nvs_set_i32(my_handle, "restart", restart);
if (err != ESP_OK)
{
Serial.println("Erreur write nvs persistant storage");
return false;
}
// Commit written value.
// After setting any values, nvs_commit() must be called to ensure changes are written
// to flash storage. Implementations may write to storage at other times,
// but this is not guaranteed.
err = nvs_commit(my_handle);
if (err != ESP_OK)
return err;
// Close
nvs_close(my_handle);
Serial.println("Flag restart = 0 (not restarted");
return true;
}
else
{
// Close
nvs_close(my_handle);
Serial.println("Flag restart = 1 (already restart)");
return false;
}
/* Not needed but finish properly the function */
// Close
Serial.println("Maybe issue: last return");
nvs_close(my_handle);
return false;
}
//-------------------- Initialisation --------------------//
/**
* @brief Setup function for the ESP
*/
void setup()
{
Serial.begin(9600);
Serial.println("\n-----------------Start---------------------");
setupWIFI(SSID, PWD);
setupMQTT(MQTT_ADDRESS, MQTT_PORT);
initSensors(sensors, SENSORS_NUMBER);
TimeClient.begin();
TimeClient.update();
// int rawtime = (TimeClient.getEpochTime()) % 86400; // 86400 = 60sec*60minutes*24heures
unsigned long rawtime = getTime();
int hours = rawtime / 3600, minutes = (rawtime % 3600) / 60, secondes = rawtime % 60;
if (nvs_flash_init() != ESP_OK)
{
Serial.println("Erreur flash init");
}
/**
* @brief restart the ESP if there is the time restart
*
*/
if (testTime(hours, minutes, RESTART) && TestBoot(RESTART))
{
Serial.println("-----------------RESSSSTTTAAAART---------------------");
ESP.restart();
delay(1000);
}
else if (testTime(hours, minutes, REFRESHMEMBOOT))
{
TestBoot(REFRESHMEMBOOT);
}
// // ######### test time part #########
// Serial.println('\n');
// Serial.println(hours,DEC);
// Serial.println(':');
// Serial.println(minutes,DEC);
// Serial.println(':');
// Serial.println(secondes,DEC);
// Serial.println('\n');
}
// Définir la capacité maximale de stockage
const int maxDataSets = 11;
// Fonction pour sauvegarder les données localement
void LocalSave()
{
// Ouvre les préférences sous le nom "capteurs" en mode lecture/écriture
preferences.begin("capteurs", false);
// Lit l'indice de la prochaine sauvegarde, ou initialise à 0 s'il n'existe pas
int saveCounter = preferences.getInt("saveCounter", 0);
// Efface les anciennes données si nécessaire
if (saveCounter >= maxDataSets)
{
saveCounter = 0; // Réinitialise le compteur si la limite est atteinte
}
// Appelle la fonction pour effacer les données anciennes à l'index actuel
clearOldData(saveCounter);
// Calcule l'heure actuelle en secondes depuis l'époque Unix
int chargelvl = getAverageChargeLevel(); // Obtient le niveau moyen de la batterie
time_t rawtime = TimeClient.getEpochTime(); // Obtient l'heure actuelle
Serial.print("\n-----------------Save---------------------\n");
// Boucle pour sauvegarder les données de température et d'humidité
for (int i = 0; i < 5; i++)
{
char tempKey[16];
char humiKey[16];
// Génère des clés uniques pour chaque valeur de température et d'humidité
snprintf(tempKey, sizeof(tempKey), "temp%d_%d", saveCounter, i);
snprintf(humiKey, sizeof(humiKey), "hum%d_%d", saveCounter, i);
// Sauvegarde les valeurs de température et d'humidité dans les préférences
preferences.putFloat(tempKey, temp[i]);
preferences.putFloat(humiKey, hum[i]);
// Affiche les valeurs de température et d'humidité pour vérification
Serial.printf("temp[%d]: %0.2f\n", i, temp[i]);
Serial.printf("hum[%d]: %0.2f\n", i, hum[i]);
}
// Sauvegarde le temps et le niveau de charge
char timeKey[16];
char chargeKey[16];
snprintf(timeKey, sizeof(timeKey), "time%d", saveCounter);
snprintf(chargeKey, sizeof(chargeKey), "chargelvl%d", saveCounter);
// Sauvegarde les valeurs de temps et de niveau de charge dans les préférences
preferences.putInt(timeKey, rawtime);
preferences.putInt(chargeKey, chargelvl);
// Affiche les valeurs de temps et de niveau de charge pour vérification
Serial.printf("time: %d \n", rawtime);
Serial.printf("chargelvl: %d\n", chargelvl);
// Incrémente le compteur de sauvegardes et le sauvegarde
saveCounter++;
preferences.putInt("saveCounter", saveCounter);
// Termine l'accès aux préférences
preferences.end();
}
// Fonction pour effacer les anciennes données si l'espace est insuffisant
void clearOldData(int index)
{
// Variables pour stocker les noms de clé formatés
char timeKey[16];
char chargeKey[16];
// Formate les noms de clé pour le temps et le niveau de charge en fonction de l'index donné
snprintf(timeKey, sizeof(timeKey), "time%d", index);
snprintf(chargeKey, sizeof(chargeKey), "chargelvl%d", index);
// Supprime les entrées correspondantes au temps et au niveau de charge
preferences.remove(timeKey);
preferences.remove(chargeKey);
// Boucle pour supprimer les entrées de température et d'humidité associées
for (int i = 0; i < 5; i++)
{
// Variables pour stocker les noms de clé formatés pour la température et l'humidité
char tempKey[16];
char humiKey[16];
// Formate les noms de clé pour la température et l'humidité en fonction de l'index et du sous-index
snprintf(tempKey, sizeof(tempKey), "temp%d_%d", index, i);
snprintf(humiKey, sizeof(humiKey), "hum%d_%d", index, i);
// Supprime les entrées correspondantes à la température et à l'humidité
preferences.remove(tempKey);
preferences.remove(humiKey);
}
}
// Fonction pour envoyer les données locales
void SendLocalData()
{
// Ouvre les préférences sous le nom "capteurs" en mode lecture seule
preferences.begin("capteurs", true);
// Lit le compteur de sauvegardes, ou initialise à 0 s'il n'existe pas
int saveCounter = preferences.getInt("saveCounter", 0);
// Boucle pour envoyer les données sauvegardées
for (int counter = 0; counter < saveCounter; counter++)
{
char timeKey[16];
char chargeKey[16];
// Génère des clés uniques pour le temps et le niveau de charge
snprintf(timeKey, sizeof(timeKey), "time%d", counter);
snprintf(chargeKey, sizeof(chargeKey), "chargelvl%d", counter);
// Lit les valeurs de temps et de niveau de charge depuis les préférences
time_t rawtime = preferences.getInt(timeKey, 0);
int chargelvl = preferences.getInt(chargeKey, 0);
// Boucle pour lire les données de température et d'humidité
for (int i = 0; i < 5; i++)
{
char tempKey[16];
char humiKey[16];
// Génère des clés uniques pour chaque valeur de température et d'humidité
snprintf(tempKey, sizeof(tempKey), "temp%d_%d", counter, i);
snprintf(humiKey, sizeof(humiKey), "hum%d_%d", counter, i);
// Lit les valeurs de température et d'humidité depuis les préférences
temp[i] = preferences.getFloat(tempKey, 0);
hum[i] = preferences.getFloat(humiKey, 0);
}
// Prépare le message à envoyer
char msgsld[200];
sprintf(msgsld, "%lu|%s|%0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f|%d", rawtime, CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], hum[0], hum[1], hum[2], hum[3], hum[4], chargelvl);
// Envoie le message via MQTT
MqttClient.publish(TOPIC, msgsld);
Serial.println(msgsld);
// Supprime les clés après envoi
clearOldData(counter);
}
// Réinitialise le compteur de sauvegardes
preferences.putInt("saveCounter", 0);
// Termine l'accès aux préférences
preferences.end();
}
//-------------------- Boucle principale --------------------//
/**
* @brief Main loop function for the ESP
*/
void loop()
{
int year, month, day;
int lenght;
unsigned long now;
char time[30];
char date[30];
char msg[70];
bool horoIssue = false;
readSensors(sensors, temp, hum, SENSORS_NUMBER);
writeMessage(msg, temp, hum, SENSORS_NUMBER);
MqttClient.loop();
if (!MqttClient.connected())
{
reconnect();
}
// MqttClient.publish(TOPIC, msg, date);
// TimeClient.update();
// TimeClient.getFormattedTime().toCharArray(time, 30);
// tie(year, month, day) = getDate();
// /* debug print*/
// Serial.println('\n');
// Serial.println(year,DEC);
// Serial.println(':');
// Serial.println(month,DEC);
// Serial.println(':');
// Serial.println(day,DEC);
// Serial.println('\n');
now = getTime();
lenght = sprintf(date, "%s", ultoa(now, date, 10) /* "|%d-%d-%d ", year, month, day */);
sprintf(date + lenght, time);
// Serial.println("msg1 : "); //debug print
// Serial.println(msg); //debug print
sprintf(date + strlen(date), msg);
// Serial.println("msg2 : "); //debug print
// Serial.println(msg); //debug print
// Serial.println("date : "); //debug print
// Serial.println(date); //debug print
Serial.println("\n");
Serial.println("-----------------Local---------------------");
SendLocalData();
nvs_flash_erase(); // Supprime les données en local.
MqttClient.publish(TOPIC, date);
Serial.println("-----------------Brut---------------------");
Serial.println(date);
Serial.println("-----------------DeepSleep---------------------");
delay(2000);
sleep();
delay(1000);
}