добавил сценарии и класс сенсора

This commit is contained in:
Dmitry Borisenko
2022-01-14 21:48:43 +01:00
parent a18552c4f4
commit e6e3497c40
20 changed files with 857 additions and 33 deletions

7
include/Buffers.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include "Global.h"
#include "MqttClient.h"
void eventGen2(String eventName, String eventValue);
extern void spaceCmdExecute(String &cmdStr);
extern String getValueJson(String &key);

View File

@@ -7,6 +7,7 @@
#include <ArduinoJson.h>
#include <TickerScheduler.h>
#include <PubSubClient.h>
#include <StringCommand.h>
#ifdef ESP32
#include "WiFi.h"
@@ -46,6 +47,7 @@
#include "Utils/FileUtils.h"
#include "Utils/JsonUtils.h"
#include "Utils/SerialPrint.h"
#include "Utils/StringUtils.h"
/*********************************************************************************************************************
*****************************************глобальные объекты классов***************************************************
@@ -54,6 +56,7 @@
extern TickerScheduler ts;
extern WiFiClient espClient;
extern PubSubClient mqtt;
extern StringCommand sCmd;
#ifdef ASYNC_WEB_SERVER
extern AsyncWebServer server;
#endif
@@ -79,6 +82,10 @@ extern String settingsFlashJson;
extern String paramsFlashJson;
extern String paramsHeapJson;
// buf
extern String orderBuf;
extern String eventBuf;
// Mqtt
extern String mqttServer;
extern int mqttPort;

View File

@@ -2,7 +2,6 @@
//
#include "EspFileSystem.h"
#include "Global.h"
#include "Utils/Pretty.h"
#include "Utils/WiFiUtils.h"
#include "AsyncWebServer.h"
#include "StandWebServer.h"

View File

@@ -0,0 +1,26 @@
#pragma once
#include <WString.h>
class IoTSensor {
public:
IoTSensor();
~IoTSensor();
void loop();
virtual void doByInterval();
void init(String key, String id, unsigned long interval);
void regEvent(String value, String consoleInfo);
String getKey();
String getID();
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long difference;
protected:
String _key;
String _id;
unsigned long _interval;
};

View File

@@ -0,0 +1,255 @@
#pragma once
#include "Global.h"
#include "MqttClient.h"
#include "Buffers.h"
class Scenario {
public:
void loop2() {
if (!jsonReadBool(settingsFlashJson, "scen")) {
return;
}
String allBlocks = scenario;
allBlocks += "\n";
String incommingEvent = selectToMarker(eventBuf, ",");
String incommingEventKey = selectToMarker(incommingEvent, " ");
String incommingEventValue = selectToMarkerLast(incommingEvent, " ");
while (allBlocks.length()) {
String oneBlock = selectToMarker(allBlocks, "end\n");
String condition = selectToMarker(oneBlock, "\n");
//логическое и
if (condition.indexOf("&&") != -1) {
condition = condition += " && ";
//посчитаем количество условий
int conditionCnt = itemsCount2(condition, "&&") - 1;
//создадим и заполним динамический массив
bool *arr = new bool[conditionCnt];
for (int i = 0; i < conditionCnt; i++) {
arr[i] = false;
}
//есть ли входящее событие хотя бы в одном из условий и удавлетварено ли оно?
int evenInConditionNum = -1;
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " && ", i);
if (isScenarioNeedToDo(buf, incommingEventKey, incommingEventValue, 1)) {
arr[i] = true;
evenInConditionNum = i;
}
}
//если да то проверяем остальные условия по json
if (evenInConditionNum >= 0) {
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " && ", i);
if (i != evenInConditionNum) {
if (isScenarioNeedToDoJson(buf)) {
arr[i] = true;
}
}
}
}
//все элементы массива должны быть true
bool result = true;
for (int i = 0; i < conditionCnt; i++) {
if (!arr[i]) {
result = false;
}
}
delete[] arr;
if (result) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("I", "Event done", incommingEvent);
SerialPrint("I", F("Scenario"), F("All conditions are matched"));
spaceCmdExecute(oneBlock);
}
//логическое или
} else if (condition.indexOf("||") != -1) {
condition = condition += " || ";
//посчитаем количество условий
int conditionCnt = itemsCount2(condition, "||") - 1;
//создадим и заполним динамический массив
bool *arr = new bool[conditionCnt];
for (int i = 0; i < conditionCnt; i++) {
arr[i] = false;
}
//есть ли входящее событие хотя бы в одном из условий и удавлетварено ли оно?
int evenInConditionNum = -1;
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " || ", i);
if (isScenarioNeedToDo(buf, incommingEventKey, incommingEventValue, 1)) {
arr[i] = true;
evenInConditionNum = i;
}
}
//если да то проверяем остальные условия по json
if (evenInConditionNum >= 0) {
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " || ", i);
if (i != evenInConditionNum) {
if (isScenarioNeedToDoJson(buf)) {
arr[i] = true;
}
}
}
}
//хотя бы один элемент массива должн быть true
bool result = false;
for (int i = 0; i < conditionCnt; i++) {
if (arr[i]) {
result = true;
}
}
delete[] arr;
if (result) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("I", "Event done", incommingEvent);
SerialPrint("I", F("Scenario"), F("One of all condition are matched"));
spaceCmdExecute(oneBlock);
}
//если гистерезис
} else if (condition.indexOf("+-") != -1) {
if (isScenarioNeedToDo(condition, incommingEventKey, incommingEventValue, 2)) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("I", "Event done", incommingEvent);
SerialPrint("I", F("Scenario"), "Condition are matched: " + condition);
spaceCmdExecute(oneBlock);
}
//остальные случаи
} else {
if (isScenarioNeedToDo(condition, incommingEventKey, incommingEventValue, 1)) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("I", "Event done", incommingEvent);
SerialPrint("I", F("Scenario"), "Condition are matched: " + condition);
spaceCmdExecute(oneBlock);
}
}
allBlocks = deleteBeforeDelimiter(allBlocks, "end\n");
}
eventBuf = deleteBeforeDelimiter(eventBuf, ",");
}
private:
bool isScenarioNeedToDo(String &condition, String &incommingEventKey, String &incommingEventValue, int type) {
bool res = false;
String setEventKey = selectFromMarkerToMarker(condition, " ", 0);
if (isEventExist(incommingEventKey, setEventKey)) {
String setEventSign;
String setEventValue;
if (type == 1) preCalculation(condition, setEventSign, setEventValue);
if (type == 2) preCalculationGisteresis(condition, setEventSign, setEventValue);
if (isConditionMatch(setEventSign, incommingEventValue, setEventValue)) {
res = true;
}
}
return res;
}
bool isScenarioNeedToDoJson(String &condition) {
bool res = false;
String setEventKey = selectFromMarkerToMarker(condition, " ", 0);
String setEventSign;
String setEventValue;
preCalculation(condition, setEventSign, setEventValue);
String jsonValue = getValueJson(setEventKey);
if (isConditionMatch(setEventSign, jsonValue, setEventValue)) {
res = true;
}
return res;
}
// bool isScenarioNeedToDoJson2(String &condition, String &incommingEventKey, String &incommingEventValue) {
// bool res = false;
// String setEventKey = selectFromMarkerToMarker(condition, " ", 0);
// if (isEventExist(incommingEventKey, setEventKey)) {
// String setEventSign;
// String setEventValue;
// preCalculation(condition, setEventSign, setEventValue);
// if (isConditionMatch(setEventSign, incommingEventValue, setEventValue)) {
// res = true;
// }
// }
// return res;
// }
void preCalculation(String &condition, String &setEventSign, String &setEventValue) {
setEventSign = selectFromMarkerToMarker(condition, " ", 1);
setEventValue = selectFromMarkerToMarker(condition, " ", 2);
if (!isDigitDotCommaStr(setEventValue)) {
setEventValue = getValueJson(setEventValue);
}
}
void preCalculationGisteresis(String &condition, String &setEventSign, String &setEventValue) {
setEventSign = selectFromMarkerToMarker(condition, " ", 1);
setEventValue = selectFromMarkerToMarker(condition, " ", 2);
if (!isDigitDotCommaStr(setEventValue)) {
String setEventValueName = selectToMarker(setEventValue, "+-");
String gisteresisValue = selectToMarkerLast(setEventValue, "+-");
gisteresisValue.replace("+-", "");
String value = getValueJson(setEventValueName);
String upValue = String(value.toFloat() + gisteresisValue.toFloat());
String lowValue = String(value.toFloat() - gisteresisValue.toFloat());
if (setEventSign == ">") {
setEventValue = upValue;
} else if (setEventSign == "<") {
setEventValue = lowValue;
}
}
}
bool isEventExist(String &incommingEventKey, String &setEventKey) {
bool res = false;
if (incommingEventKey == setEventKey) {
res = true;
}
return res;
}
bool isConditionMatch(String &setEventSign, String &incommingEventValue, String &setEventValue) {
boolean flag = false;
if (setEventSign == "=") {
flag = incommingEventValue == setEventValue;
} else if (setEventSign == "!=") {
flag = incommingEventValue != setEventValue;
} else if (setEventSign == "<") {
flag = incommingEventValue.toFloat() < setEventValue.toFloat();
} else if (setEventSign == ">") {
flag = incommingEventValue.toFloat() > setEventValue.toFloat();
} else if (setEventSign == ">=") {
flag = incommingEventValue.toFloat() >= setEventValue.toFloat();
} else if (setEventSign == "<=") {
flag = incommingEventValue.toFloat() <= setEventValue.toFloat();
}
return flag;
}
};
extern Scenario *myScenario;

View File

@@ -1,4 +0,0 @@
#pragma once
#include "Global.h"
String prettyBytes(size_t size);

View File

@@ -0,0 +1,39 @@
#pragma once
#include "Global.h"
void hex2string(byte array[], unsigned int len, char buffer[]);
int string2hex(const char* str, unsigned char* bytes);
uint8_t hexStringToUint8(String hex);
uint16_t hexStringToUint16(String hex);
String selectToMarkerLast(String str, String found);
String selectToMarker(String str, String found);
String extractInner(String str);
String deleteAfterDelimiter(String str, String found);
String deleteBeforeDelimiter(String str, String found);
String deleteBeforeDelimiterTo(String str, String found);
String deleteToMarkerLast(String str, String found);
String selectFromMarkerToMarker(String str, String found, int number);
size_t itemsCount2(String str, const String& separator);
char* stringToChar(String& str);
size_t itemsCount(String& str, const char* delim);
boolean isDigitStr(const String& str);
boolean isDigitDotCommaStr(const String& str);
String prettyBytes(size_t size);

View File

@@ -0,0 +1,137 @@
/**
* SerialCommand - A Wiring/Arduino library to tokenize and parse commands
* received over a serial port.
*
* Copyright (C) 2012 Stefan Rado
* Copyright (C) 2011 Steven Cogswell <steven.cogswell@gmail.com>
* http://husks.wordpress.com
*
* Version 20120522
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StringCommand.h"
/**
* Constructor makes sure some things are set.
*/
StringCommand::StringCommand()
: commandList(NULL),
commandCount(0),
defaultHandler(NULL),
term('\n'), // default terminator for commands, newline character
last(NULL),
main(NULL)
{
strcpy(delim, " "); // strtok_r needs a null-terminated string
clearBuffer();
}
/**
* Adds a "command" and a handler function to the list of available commands.
* This is used for matching a found token in the buffer, and gives the pointer
* to the handler function to deal with it.
*/
void StringCommand::addCommand(const char *command, void (*function)()) {
#ifdef SERIALCOMMAND_DEBUG
Serial.print("Adding command (");
Serial.print(commandCount);
Serial.print("): ");
Serial.println(command);
#endif
commandList = (StringCommandCallback *) realloc(commandList, (commandCount + 1) * sizeof(StringCommandCallback));
strncpy(commandList[commandCount].command, command, SERIALCOMMAND_MAXCOMMANDLENGTH);
commandList[commandCount].function = function;
commandCount++;
}
/**
* This sets up a handler to be called in the event that the receveived command string
* isn't in the list of commands.
*/
void StringCommand::setDefaultHandler(void (*function)(const char *)) {
defaultHandler = function;
}
/**
* This checks the Serial stream for characters, and assembles them into a buffer.
* When the terminator character (default '\n') is seen, it starts parsing the
* buffer for a prefix command, and calls handlers setup by addCommand() member
*/
void StringCommand::readStr(String sBuffer ) {
sBuffer.toCharArray(buffer, SERIALCOMMAND_BUFFER);
#ifdef SERIALCOMMAND_DEBUG
Serial.print("Received: ");
Serial.println(buffer);
#endif
char *command = strtok_r(buffer, delim, &last); // Search for command at start of buffer
if (command != NULL) {
boolean matched = false;
for (int i = 0; i < commandCount; i++) {
#ifdef SERIALCOMMAND_DEBUG
Serial.print("Comparing [");
Serial.print(command);
Serial.print("] to [");
Serial.print(commandList[i].command);
Serial.println("]");
#endif
// Compare the found command against the list of known commands for a match
if (strncmp(command, commandList[i].command, SERIALCOMMAND_MAXCOMMANDLENGTH) == 0) {
#ifdef SERIALCOMMAND_DEBUG
Serial.print("Matched Command: ");
Serial.println(command);
#endif
// Execute the stored handler function for the command
(*commandList[i].function)();
matched = true;
break;
}
}
if (!matched && (defaultHandler != NULL)) {
(*defaultHandler)(command);
}
clearBuffer();
}
}
/*
* Clear the input buffer.
*/
void StringCommand::clearBuffer() {
buffer[0] = '\0';
bufPos = 0;
}
/**
* Retrieve the next token ("word" or "argument") from the command buffer.
* Returns NULL if no more tokens exist.
*/
char *StringCommand::next() {
return strtok_r(NULL, delim, &last);
}
char *StringCommand::order() {
return strtok_r(buffer, delim, &main);
}

View File

@@ -0,0 +1,77 @@
/**
* SerialCommand - A Wiring/Arduino library to tokenize and parse commands
* received over a serial port.
*
* Copyright (C) 2012 Stefan Rado
* Copyright (C) 2011 Steven Cogswell <steven.cogswell@gmail.com>
* http://husks.wordpress.com
*
* Version 20120522
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef StringCommand_h
#define StringCommand_h
#if defined(WIRING) && WIRING >= 100
#include <Wiring.h>
#elif defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <string.h>
// Size of the input buffer in bytes (maximum length of one command plus arguments)
#define SERIALCOMMAND_BUFFER 128 //256
// Maximum length of a command excluding the terminating null
#define SERIALCOMMAND_MAXCOMMANDLENGTH 16
// Uncomment the next line to run the library in debug mode (verbose messages)
//#define SERIALCOMMAND_DEBUG
class StringCommand {
public:
StringCommand(); // Constructor
void addCommand(const char *command, void(*function)()); // Add a command to the processing dictionary.
void setDefaultHandler(void (*function)(const char *)); // A handler to call when no valid command received.
void readStr(String sBuffer ); // Main entry point.
void clearBuffer(); // Clears the input buffer.
char *next(); // Returns pointer to next token found in command buffer (for getting arguments to commands).
char *order();
private:
// Command/handler dictionary
struct StringCommandCallback {
char command[SERIALCOMMAND_MAXCOMMANDLENGTH + 1];
void (*function)();
}; // Data structure to hold Command/Handler function key-value pairs
StringCommandCallback *commandList; // Actual definition for command/handler array
byte commandCount;
// Pointer to the default handler function
void (*defaultHandler)(const char *);
char delim[2]; // null-terminated list of character to be used as delimeters for tokenizing (default " ")
char term; // Character that signals end of command (default '\n')
char buffer[SERIALCOMMAND_BUFFER + 1]; // Buffer of stored characters while waiting for terminator character
byte bufPos; // Current position in the buffer
char *last; // State variable used by strtok_r during processing
char *main;
};
#endif //StringCommand_h

View File

@@ -0,0 +1,23 @@
#######################################
# Datatypes (KEYWORD1)
#######################################
StringCommand KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
addCommand KEYWORD2
setDefaultHandler KEYWORD2
readString KEYWORD2
clearBuffer KEYWORD2
next KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -0,0 +1,5 @@
StringCommand
=============
Библиотека для ESP8266 позволяющая связать запуск пользовательских функций с строковой переменной.

View File

@@ -42,7 +42,7 @@ void asyncWebServerInit() {
// динамические данные
// server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest *request) {
// request->send(200, "application/json", configLiveJson);
// request->send(200, "application/json", paramsFlashJson);
//});
//
// server.on("/config.store.json", HTTP_GET, [](AsyncWebServerRequest *request) {

46
src/Buffers.cpp Normal file
View File

@@ -0,0 +1,46 @@
#include "Buffers.h"
//генеирует событие
void eventGen2(String eventName, String eventValue) {
if (!jsonReadBool(settingsFlashJson, "scen")) {
return;
}
String event = eventName + " " + eventValue + ",";
eventBuf += event;
SerialPrint("I", "Event add", eventName + " " + eventValue);
if (jsonReadBool(settingsFlashJson, "MqttOut")) {
if (eventName != "timenow") {
publishEvent(eventName, eventValue);
}
}
}
void spaceCmdExecute(String& cmdStr) {
cmdStr += "\r\n";
cmdStr.replace("\r\n", "\n");
cmdStr.replace("\r", "\n");
while (cmdStr.length()) {
String buf = selectToMarker(cmdStr, "\n");
if (buf != "") {
sCmd.readStr(buf);
SerialPrint("I", F("Order done W"), buf);
}
cmdStr = deleteBeforeDelimiter(cmdStr, "\n");
}
}
String getValueJson(String& key) {
String live = jsonReadStr(paramsHeapJson, key);
String store = jsonReadStr(paramsFlashJson, key);
if (live != nullptr) {
return live;
} else if (store != nullptr) {
return store;
} else if (store == nullptr && live == nullptr) {
return "no value";
} else {
return "data error";
}
}

View File

@@ -10,6 +10,8 @@ void configure(String& path) {
//=============================
} else if (value == F("pwm-out")) {
//=============================
} else if (value == F("analog-adc")) {
//=============================
} else {
SerialPrint(F("E"), F("Config"), F("config.json error, type not exist"));
}

View File

@@ -7,6 +7,7 @@
TickerScheduler ts(MYTEST + 1);
WiFiClient espClient;
PubSubClient mqtt(espClient);
StringCommand sCmd;
#ifdef ASYNC_WEB_SERVER
AsyncWebServer server(80);
#endif
@@ -33,6 +34,10 @@ String settingsFlashJson = "{}"; //переменная в которой хр
String paramsFlashJson = "{}"; //переменная в которой хранятся все параметры, находится в оперативной памяти и синхронизированна с flash памятью
String paramsHeapJson = "{}"; //переменная в которой хранятся все параметры, находится в оперативной памяти только
// buf
String orderBuf = "";
String eventBuf = "";
// Mqtt
String mqttServer = "";
int mqttPort = 0;

39
src/classes/IoTSensor.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "Utils/JsonUtils.h"
#include "Utils/SerialPrint.h"
#include "Classes/ScenarioClass3.h"
#include "Classes/IoTSensor.h"
void IoTSensor::init(String key, String id, unsigned long interval) {
_interval = interval * 1000;
_key = key;
_id = id;
}
IoTSensor::IoTSensor() {}
IoTSensor::~IoTSensor() {}
String IoTSensor::getKey() {
return _key;
}
String IoTSensor::getID() {
return _id;
};
void IoTSensor::loop() {
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= _interval) {
prevMillis = millis();
this->doByInterval();
}
}
void IoTSensor::regEvent(String value, String consoleInfo = "") {
eventGen2(_id, String(value));
jsonWriteStr(paramsFlashJson, _id, String(value));
publishStatus(_id, String(value));
SerialPrint("I", "Sensor", "'" + _id + "' data: " + String(value) + "' " + consoleInfo);
}
void IoTSensor::doByInterval() {}

View File

@@ -0,0 +1,3 @@
#include "Classes/ScenarioClass3.h"
Scenario* myScenario;

View File

@@ -1,12 +0,0 @@
#include "Utils/Pretty.h"
String prettyBytes(size_t size) {
if (size < 1024)
return String(size) + "b";
else if (size < (1024 * 1024))
return String(size / 1024.0) + "kB";
else if (size < (1024 * 1024 * 1024))
return String(size / 1024.0 / 1024.0) + "MB";
else
return String(size / 1024.0 / 1024.0 / 1024.0) + "GB";
}

170
src/utils/StringUtils.cpp Normal file
View File

@@ -0,0 +1,170 @@
#include "Utils/StringUtils.h"
String selectToMarkerLast(String str, String found) {
int p = str.lastIndexOf(found);
return str.substring(p + found.length());
}
String selectToMarker(String str, String found) {
int p = str.indexOf(found);
return str.substring(0, p);
}
String extractInner(String str) {
int p1 = str.indexOf("[");
int p2 = str.indexOf("]");
return str.substring(p1 + 1, p2);
}
String deleteAfterDelimiter(String str, String found) {
int p = str.indexOf(found);
return str.substring(0, p);
}
String deleteBeforeDelimiter(String str, String found) {
int p = str.indexOf(found) + found.length();
return str.substring(p);
}
String deleteBeforeDelimiterTo(String str, String found) {
int p = str.indexOf(found);
return str.substring(p);
}
String deleteToMarkerLast(String str, String found) {
int p = str.lastIndexOf(found);
return str.substring(0, p);
}
String selectToMarkerPlus(String str, String found, int plus) {
int p = str.indexOf(found);
return str.substring(0, p + plus);
}
String selectFromMarkerToMarker(String str, String tofind, int number) {
if (str.indexOf(tofind) == -1) {
return "not found";
}
str += tofind; // добавим для корректного поиска
uint8_t i = 0; // Индекс перебора
do {
if (i == number) {
// если индекс совпал с позицией
return selectToMarker(str, tofind);
}
// отбросим проверенный блок до разделителя
str = deleteBeforeDelimiter(str, tofind);
i++;
} while (str.length() != 0);
return "not found";
}
//преобразовываем байтовый массив в человеческий вид HEX в строке
void hex2string(byte array[], unsigned int len, char buffer[]) {
for (unsigned int i = 0; i < len; i++) {
byte nib1 = (array[i] >> 4) & 0x0F;
byte nib2 = (array[i] >> 0) & 0x0F;
buffer[i * 2 + 0] = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA;
buffer[i * 2 + 1] = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA;
}
buffer[len * 2] = '\0';
}
inline unsigned char ChartoHex(char ch) {
return ((ch >= 'A') ? (ch - 'A' + 0xA) : (ch - '0')) & 0x0F;
}
// str - указатель на массив символов
// bytes - выходной буфер
// функция возвращает колл-во байт
//
int string2hex(const char* str, unsigned char* bytes) {
unsigned char Hi, Lo;
int i = 0;
while ((Hi = *str++) && (Lo = *str++)) {
bytes[i++] = (ChartoHex(Hi) << 4) | ChartoHex(Lo);
}
return i;
}
uint8_t hexStringToUint8(String hex) {
uint8_t tmp = strtol(hex.c_str(), NULL, 0);
if (tmp >= 0x00 && tmp <= 0xFF) {
return tmp;
}
}
uint16_t hexStringToUint16(String hex) {
uint16_t tmp = strtol(hex.c_str(), NULL, 0);
if (tmp >= 0x0000 && tmp <= 0xFFFF) {
return tmp;
}
}
size_t itemsCount2(String str, const String& separator) {
// если строки поиск нет сразу выход
if (str.indexOf(separator) == -1) {
return 0;
}
// добавим для корректного поиска
str += separator;
size_t cnt = 0;
while (str.length()) {
// отбросим проверенный блок до разделителя
str = deleteBeforeDelimiter(str, separator);
cnt++;
}
return cnt;
}
size_t itemsCount(String& str, const char* delim) {
size_t cnt = 0;
char* cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
char* token;
while ((token = strtok_r(cstr, delim, &cstr))) {
cnt++;
// printf("%s\n", token);
}
delete[] cstr;
return cnt;
}
char* stringToChar(String& str) {
char* mychar = new char[str.length() + 1];
strcpy(mychar, str.c_str());
return mychar;
}
boolean isDigitStr(const String& str) {
for (size_t i = 0; i < str.length(); i++) {
if (!isDigit(str.charAt(i))) {
return false;
}
}
return str.length();
}
boolean isDigitDotCommaStr(const String& str) {
for (size_t i = 0; i < str.length(); i++) {
char latter = str.charAt(i);
if (!isDigit(latter) && latter != '.' && latter != '-') {
return false;
}
}
return true;
}
String prettyBytes(size_t size) {
if (size < 1024)
return String(size) + "b";
else if (size < (1024 * 1024))
return String(size / 1024.0) + "kB";
else if (size < (1024 * 1024 * 1024))
return String(size / 1024.0 / 1024.0) + "MB";
else
return String(size / 1024.0 / 1024.0 / 1024.0) + "GB";
}

View File

@@ -115,18 +115,18 @@ void breakEpochToTime(unsigned long epoch, Time_t& tm) {
tm.valid = (epoch > MIN_DATETIME);
}
//void timeInit() {
// ts.add(
// TIME, 1000, [&](void*) {
// String timenow = timeNow->getTimeWOsec();
// static String prevTime;
// if (prevTime != timenow) {
// prevTime = timenow;
// jsonWriteStr(configLiveJson, "timenow", timenow);
// eventGen2("timenow", timenow);
// SerialPrint("i", F("NTP"), timenow);
// }
// },
// nullptr, true);
// SerialPrint("i", F("NTP"), F("Handle time init"));
//}
// void timeInit() {
// ts.add(
// TIME, 1000, [&](void*) {
// String timenow = timeNow->getTimeWOsec();
// static String prevTime;
// if (prevTime != timenow) {
// prevTime = timenow;
// jsonWriteStr(paramsFlashJson, "timenow", timenow);
// eventGen2("timenow", timenow);
// SerialPrint("i", F("NTP"), timenow);
// }
// },
// nullptr, true);
// SerialPrint("i", F("NTP"), F("Handle time init"));
// }