8 char* copystr(const char* s) {
10 char* res = new char[len+1];
15 char* copystr(const __FlashStringHelper* s) {
16 int len = strlen_P((PGM_P)s);
17 char* res = new char[len+1];
18 strcpy_P(res, (PGM_P)s);
22 ConfigParameter::ConfigParameter(const char *id, const char* value) {
27 ConfigParameter::ConfigParameter(const char *id, int value) {
32 ConfigParameter::ConfigParameter(const char *id, double value) {
37 ConfigParameter::ConfigParameter(const char *id, bool value) {
42 ConfigParameter::ConfigParameter(const __FlashStringHelper *id, const char* value) {
47 ConfigParameter::ConfigParameter(const __FlashStringHelper *id, int value) {
52 ConfigParameter::ConfigParameter(const __FlashStringHelper *id, double value) {
57 ConfigParameter::ConfigParameter(const __FlashStringHelper *id, bool value) {
62 ConfigParameter::~ConfigParameter() {
64 if (_type=='S' && _value.charValue) {
65 delete[] _value.charValue;
69 const char *ConfigParameter::getID() const {
73 char ConfigParameter::getType() const {
77 const bool ConfigParameter::getBoolValue() const {
78 return (_type=='B')?_value.boolValue:false;
81 const int ConfigParameter::getIntValue() const {
82 return (_type=='I')?_value.intValue:0;
85 const double ConfigParameter::getFloatValue() const {
86 return (_type=='F')?_value.floatValue:0.0;
89 const char *ConfigParameter::getCharValue() const {
90 return (_type=='S')?_value.charValue:"";
93 void ConfigParameter::setValue(const bool value) {
95 _value.boolValue = value;
99 void ConfigParameter::setValue(const int value) {
101 _value.intValue = value;
105 void ConfigParameter::setValue(const double value) {
107 _value.floatValue = value;
111 void ConfigParameter::setValue(const char *value) {
113 int length = strlen(value);
114 if (!_value.charValue) {
115 _value.charValue = new char[length + 1];
116 } else if (strlen(_value.charValue) != length) {
117 delete[] _value.charValue;
118 _value.charValue = new char[length + 1];
120 strcpy(_value.charValue,value);
124 void ConfigParameter::init(const char *id, char type) {
127 _value.charValue = nullptr;
130 void ConfigParameter::init(const __FlashStringHelper *id, char type) {
133 _value.charValue = nullptr;
136 size_t ConfigParameter::printTo(Print& p) const {
138 n += p.print(_id); n += p.print(":"); n += p.print(_type); n += p.print(":");
141 if (_value.boolValue) { n += p.print("true"); }
142 else { n += p.print("false"); }
145 n += p.print(_value.intValue);
148 n += p.print(_value.floatValue);
151 n += p.print(_value.charValue);
161 void Config::init() {
163 _max_params = MAX_PARAMS;
169 if (_params != NULL) {
170 for (int i = 0; i < _paramsCount; i++) {
172 _params[i] = nullptr;
179 ConfigParameter* Config::getParameter(int i) {
183 int Config::getParametersCount() const {
187 ConfigParameter* Config::getParam(const char *id) const {
188 for (int j = 0; j < _paramsCount; j++) {
189 if (strcmp(id, _params[j]->getID()) == 0) {
196 ConfigParameter* Config::getParam(const __FlashStringHelper *id) const {
197 for (int j = 0; j < _paramsCount; j++) {
198 if (strcmp_P(_params[j]->getID(),(PGM_P)id) == 0) {
205 void Config::addParameter(ConfigParameter* p) {
206 if (_params == NULL) {
207 _params = (ConfigParameter**)malloc(_max_params * sizeof(ConfigParameter*));
209 if (_paramsCount == _max_params) {
210 _max_params += MAX_PARAMS;
211 ConfigParameter** new_params = (ConfigParameter**)realloc(_params, _max_params * sizeof(ConfigParameter*));
212 if (new_params != NULL) {
213 _params = new_params;
215 Serial.println(F("Не удалось расширить массив параметров"));
219 _params[_paramsCount] = p;
224 void Config::setValue(const char *id, const char *value) {
225 ConfigParameter* p = getParam(id);
229 addParameter(new ConfigParameter(id,value));
234 void Config::setValue(const __FlashStringHelper *id, const char *value) {
235 ConfigParameter* p = getParam(id);
239 addParameter(new ConfigParameter(copystr(id),value));
244 void Config::setValue(const char *id, int value) {
245 ConfigParameter* p = getParam(id);
249 addParameter(new ConfigParameter(id,value));
254 void Config::setValue(const __FlashStringHelper *id, int value) {
255 ConfigParameter* p = getParam(id);
259 addParameter(new ConfigParameter(copystr(id),value));
264 void Config::setValue(const char *id, const double value) {
265 ConfigParameter* p = getParam(id);
269 addParameter(new ConfigParameter(id,value));
274 void Config::setValue(const __FlashStringHelper *id, const double value) {
275 ConfigParameter* p = getParam(id);
279 addParameter(new ConfigParameter(copystr(id),value));
284 void Config::setValue(const char *id, const bool value) {
285 ConfigParameter* p = getParam(id);
289 addParameter(new ConfigParameter(id,value));
294 void Config::setValue(const __FlashStringHelper *id, const bool value) {
295 ConfigParameter* p = getParam(id);
299 addParameter(new ConfigParameter(copystr(id),value));
304 size_t Config::printTo(Print& p) const {
306 for (int i=0; i<_paramsCount; i++) {
307 ConfigParameter* param = _params[i];
309 n += p.print(*param); n+= p.println();
315 int Config::getIntValue(const char *id) const {
316 ConfigParameter* p = getParam(id);
318 return p->getIntValue();
324 int Config::getIntValue(const __FlashStringHelper *id) const {
325 ConfigParameter* p = getParam(id);
327 return p->getIntValue();
333 double Config::getFloatValue(const char *id) const {
334 ConfigParameter* p = getParam(id);
336 return p->getFloatValue();
342 double Config::getFloatValue(const __FlashStringHelper *id) const {
343 ConfigParameter* p = getParam(id);
345 return p->getFloatValue();
351 bool Config::getBoolValue(const char *id) const {
352 ConfigParameter* p = getParam(id);
354 return p->getBoolValue();
360 bool Config::getBoolValue(const __FlashStringHelper *id) const {
361 ConfigParameter* p = getParam(id);
363 return p->getBoolValue();
369 const char* Config::getCharValue(const char *id) const {
370 ConfigParameter* p = getParam(id);
372 return p->getCharValue();
378 const char* Config::getCharValue(const __FlashStringHelper *id) const {
379 ConfigParameter* p = getParam(id);
381 return p->getCharValue();
387 void Config::readFrom(Stream& s) {
388 char buf[256]; // name + type + value + separators
389 while (s.available()) {
390 int x = s.readBytesUntil('\n',buf,255);
393 char* origName = strtok(buf,":\r\n");
394 char* origType = strtok(NULL,":\r\n");
395 char* origValue = strtok(NULL,"\r\n");
396 if (origType && origName && origName[0]) {
397 if (origType[0]=='B') {
399 setValue(copystr(origName),(strcmp(origValue,"true")==0));
401 setValue(copystr(origName),false);
403 } else if (origType[0]=='I') {
405 setValue(copystr(origName),atoi(origValue));
407 setValue(copystr(origName),0);
409 } else if (origType[0]=='F') {
411 setValue(copystr(origName),atof(origValue));
413 setValue(copystr(origName),0.0);
415 } else if (origType[0]=='S') {
417 setValue(copystr(origName),origValue);
419 setValue(copystr(origName),"");
427 void Config::clear() {
428 if (_params != NULL) {
429 for (int i = 0; i < _paramsCount; i++) {
431 _params[i] = nullptr;
438 void Config::dumpJson(Stream& s) const {
440 for (int i=0; i<_paramsCount; i++) {
441 ConfigParameter* param = _params[i];
444 s.print(param->getID());
446 switch (param->getType()) {
448 s.print(param->getBoolValue()?"true":"false");
451 s.print(param->getIntValue());
454 s.print(param->getFloatValue());
458 s.print(param->getCharValue());
466 unsigned long Config::getTimestamp() {
470 void Config::resetTimestamp() {
475 if (LittleFS.begin()) {
476 if (File f = LittleFS.open(F("/config.txt"),"r")) {
477 Serial.println('Открываю файл конфигурации');
480 cfg.resetTimestamp();
483 Serial.println(F("Конфигурация не найдена"));
487 void saveConfig(bool force) {
488 if (cfg.getTimestamp() || force) {
489 if (File f = LittleFS.open(F("/config.txt"),"w")) {
492 Serial.println(F("Конфигурация сохранена"));
493 cfg.resetTimestamp();
501 messageModal(F("Перезагружаюсь"));
505 char* distConfig PROGMEM =
509 "ap_ssid:S:WiFi_Clock\n"
510 "ap_psk:S:1234-5678\n"
511 "ntp_server:S:ru.pool.ntp.org\n"
515 "i2c_speed:I:400000\n"
516 "enable_rtc:B:true\n"
517 "flash_dots:B:true\n"
524 "panel_brightness_day:I:1\n"
525 "panel_brightness_night:I:0\n"
526 "panel_zero:B:true\n"
527 "panel_seconds:B:false\n"
528 "enable_button:B:true\n"
530 "enable_buzzer:B:true\n"
532 "buzzer_passive:B:true\n"
535 "enable_hourly:B:true\n"
536 "hourly_night:B:false\n"
538 "hourly_tone:I:800\n"
539 "hourly_beep_ms:I:100\n"
540 "hourly_silent_ms:I:100\n"
541 "enable_alarm:B:false\n"
543 "alarm_minute:I:12\n"
544 "alarm_days:S:1111111\n"
545 "alarm_tone:I:1500\n"
546 "alarm_length:I:60\n"
547 "alarm_beep_ms:I:300\n"
548 "alarm_silent_ms:I:200\n"
549 "enable_weather:B:false\n"
550 "weather_url:S:http://api.openweathermap.org/data/2.5/weather?lat=5{LATITUDE}&lon={LONGITUDE}&appid={API_KEY}&lang=ru&units=metric\n"
551 "weather_template:S:Сегодня %weather.[0].description%, температура %main.temp% (%main.feels_like%)°C, влажность %main.humidity%%%, ветер %wind.speed% м/с\n"
558 messageModal(F("Сбрасываю настройки"));
559 if (File f = LittleFS.open(F("/config.txt"),"w")) {