mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-27 14:42:18 +03:00
Структурируем модули как надо
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
extern IoTGpio IoTgpio;
|
||||
|
||||
|
||||
class ButtonIn : public IoTItem {
|
||||
private:
|
||||
int _pin;
|
||||
bool _execLevel;
|
||||
int _fixState;
|
||||
String _pinMode;
|
||||
int _lastButtonState = LOW;
|
||||
unsigned long _lastDebounceTime = 0;
|
||||
unsigned long _debounceDelay = 50;
|
||||
int _buttonState;
|
||||
int _reading;
|
||||
|
||||
public:
|
||||
ButtonIn(String parameters): IoTItem(parameters) {
|
||||
jsonRead(parameters, "pin", _pin);
|
||||
jsonRead(parameters, "execLevel", _execLevel);
|
||||
jsonRead(parameters, "pinMode", _pinMode);
|
||||
jsonRead(parameters, "debounceDelay", _debounceDelay);
|
||||
jsonRead(parameters, "fixState", _fixState);
|
||||
//Serial.printf("vvvvvvvvvvvvvvvv =%d \n", _fixState);
|
||||
|
||||
IoTgpio.pinMode(_pin, INPUT);
|
||||
if (_pinMode == "INPUT_PULLUP") IoTgpio.digitalWrite(_pin, HIGH);
|
||||
else if (_pinMode == "INPUT_PULLDOWN") IoTgpio.digitalWrite(_pin, LOW);
|
||||
|
||||
|
||||
// TODO: загрузить значение из памяти иначе пока просто считываем значение текущего состояния PIN
|
||||
_lastButtonState = _buttonState = IoTgpio.digitalRead(_pin);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
_reading = IoTgpio.digitalRead(_pin);
|
||||
if (_reading != _lastButtonState) {
|
||||
// reset the debouncing timer
|
||||
_lastDebounceTime = millis();
|
||||
}
|
||||
|
||||
if ((millis() - _lastDebounceTime) > _debounceDelay) {
|
||||
if (_reading != _buttonState) {
|
||||
_buttonState = _reading;
|
||||
|
||||
if (_fixState == 1 && _buttonState == _execLevel) {
|
||||
value.valD = !value.valD;
|
||||
regEvent(value.valD, "ButtonIn");
|
||||
}
|
||||
|
||||
if (_fixState == 2) {
|
||||
value.valD = !value.valD;
|
||||
regEvent(value.valD, "ButtonIn");
|
||||
}
|
||||
|
||||
if (_fixState == 0) {
|
||||
value.valD = _buttonState;
|
||||
regEvent(value.valD, "ButtonIn");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_lastButtonState = _reading;
|
||||
}
|
||||
|
||||
~ButtonIn() {};
|
||||
};
|
||||
|
||||
void* getAPI_ButtonIn(String subtype, String param) {
|
||||
if (subtype == F("ButtonIn")) {
|
||||
return new ButtonIn(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "Кнопка (подключенная физически)",
|
||||
"type": "Writing",
|
||||
"subtype": "ButtonIn",
|
||||
"id": "btn",
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "",
|
||||
"int": 0,
|
||||
|
||||
"pin": 16,
|
||||
"execLevel": "1",
|
||||
"pinMode": "INPUT",
|
||||
"debounceDelay": 50,
|
||||
"fixState": 1
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "ButtonIn",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Позволяет интерпретировать сигналы на цифровом пине как кнопку, т.е. создает в системе объект для чтения булевых значений с внешнего физического источника. Может вести себя как кнопка или как переключатель.",
|
||||
"propInfo": {
|
||||
"pin": "Укажите GPIO номер пина для чтения состояний подключенной кнопки",
|
||||
"execLevel": "Высокий 1 или низкий 0 уровень переключения состояния",
|
||||
"pinMode": "Может быть INPUT_PULLUP INPUT_PULLDOWN INPUT",
|
||||
"debounceDelay": "Время обработки дребезга",
|
||||
"fixState": "Поведение входа, срабатывание на переходе или на фиксации уровня (триггерный режим)"
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [],
|
||||
"esp8266_4mb": []
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
extern IoTGpio IoTgpio;
|
||||
|
||||
|
||||
class ButtonOut : public IoTItem {
|
||||
private:
|
||||
int _pin, _inv;
|
||||
|
||||
public:
|
||||
ButtonOut(String parameters): IoTItem(parameters) {
|
||||
jsonRead(parameters, "pin", _pin);
|
||||
jsonRead(parameters, "inv", _inv);
|
||||
|
||||
IoTgpio.pinMode(_pin, OUTPUT);
|
||||
//TODO: прочитать состояние из памяти
|
||||
IoTgpio.digitalWrite(_pin, _inv?HIGH:LOW); // пока нет памяти, устанавливаем значение в ноль
|
||||
value.valD = 0;
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
//value.valD = IoTgpio.analogRead(_pin);
|
||||
|
||||
//regEvent(value.valD, "ButtonOut"); //обязательный вызов хотяб один
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
// реакция на вызов команды модуля из сценария
|
||||
// String command - имя команды после ID. (ID.Команда())
|
||||
// param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22
|
||||
|
||||
if (command == "change") {
|
||||
value.valD = 1 - IoTgpio.digitalRead(_pin);
|
||||
IoTgpio.digitalWrite(_pin, value.valD);
|
||||
regEvent(value.valD, "ButtonOut");
|
||||
}
|
||||
|
||||
return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки
|
||||
}
|
||||
|
||||
void setValue(IoTValue Value) {
|
||||
value = Value;
|
||||
IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD);
|
||||
if (value.isDecimal) regEvent(value.valD, "ButtonOut");
|
||||
else regEvent(value.valS, "ButtonOut");
|
||||
}
|
||||
//=======================================================================================================
|
||||
|
||||
~ButtonOut() {};
|
||||
};
|
||||
|
||||
void* getAPI_ButtonOut(String subtype, String param) {
|
||||
if (subtype == F("ButtonOut")) {
|
||||
return new ButtonOut(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "Кнопка управляющая пином (Реле с кнопкой)",
|
||||
"type": "Writing",
|
||||
"subtype": "ButtonOut",
|
||||
"id": "btn",
|
||||
"widget": "toggle",
|
||||
"page": "Кнопки",
|
||||
"descr": "",
|
||||
"int": 0,
|
||||
|
||||
"inv": 0,
|
||||
"pin": 2
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "ButtonOut",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Управляем состоянием конкретного пина по модели реле.",
|
||||
"propInfo": {
|
||||
"pin": "Укажите GPIO номер пина для управления выходом",
|
||||
"inv": "Инвертировать выходные сигналы"
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [],
|
||||
"esp8266_4mb": []
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
#include "esp_camera.h"
|
||||
#include "soc/soc.h" // Disable brownour problems
|
||||
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
|
||||
|
||||
|
||||
// Pin definition for CAMERA_MODEL_AI_THINKER
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#define PICBUF_SIZE 50000
|
||||
|
||||
|
||||
IoTItem* globalItem = nullptr;
|
||||
bool webTicker = false;
|
||||
|
||||
void handleGetCam() {
|
||||
//Serial.printf("try send pic by size=%d", lastPhotoBSize);
|
||||
if (globalItem && globalItem->value.extBinInfoSize) {
|
||||
//Serial.printf("try send pic by size=%d", globalItem->value.extBinInfoSize);
|
||||
HTTP.send_P(200, "image/jpeg", (char*)globalItem->value.extBinInfo, globalItem->value.extBinInfoSize);
|
||||
if (webTicker) globalItem->regEvent("webAsk", "EspCam");
|
||||
} else HTTP.send(200, "text/json", "Item EspCam not prepared yet or camera hasn't taken a picture yet");
|
||||
}
|
||||
|
||||
class EspCam : public IoTItem {
|
||||
private:
|
||||
camera_fb_t * fb = NULL;
|
||||
bool _useLed, _ticker, _webTicker;
|
||||
|
||||
public:
|
||||
EspCam(String parameters): IoTItem(parameters) {
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
|
||||
|
||||
jsonRead(parameters, "useLed", _useLed); // используем = 1 или нет = 0 подсветку (вспышку)
|
||||
jsonRead(parameters, "ticker", _ticker); // тикать = 1 - сообщаем всем, что сделали снимок и он готов
|
||||
jsonRead(parameters, "webTicker", _webTicker); // сообщать всем, что через веб попросили отдать картинку с камеры
|
||||
webTicker = _webTicker;
|
||||
globalItem = this; // выносим адрес переменной экземпляра для доступа к данным из обработчика событий веб
|
||||
|
||||
pinMode(4, OUTPUT);
|
||||
digitalWrite(4, LOW);
|
||||
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sscb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.pixel_format = PIXFORMAT_JPEG;
|
||||
|
||||
value.extBinInfo = (uint8_t*)malloc(sizeof(uint8_t) * PICBUF_SIZE);
|
||||
|
||||
if(psramFound()){
|
||||
config.frame_size = FRAMESIZE_SVGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
|
||||
config.jpeg_quality = 20; //0-63 lower number means higher quality
|
||||
config.fb_count = 1;
|
||||
Serial.printf("Camera psramFound\n");
|
||||
} else {
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.jpeg_quality = 20;
|
||||
config.fb_count = 1;
|
||||
}
|
||||
|
||||
// Init Camera
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("Camera init failed with error 0x%x\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
HTTP.on("/getcam", HTTP_GET, handleGetCam);
|
||||
}
|
||||
|
||||
void take_picture() {
|
||||
if (_useLed) digitalWrite(4, HIGH); //Turn on the flash
|
||||
|
||||
// Take Picture with Camera
|
||||
fb = esp_camera_fb_get();
|
||||
if(!fb || fb->len >= PICBUF_SIZE) {
|
||||
if (fb) {
|
||||
Serial.printf("Camera capture failed size=%d\n", fb->len);
|
||||
esp_camera_fb_return(fb);
|
||||
} else Serial.printf("Camera capture failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// if (value.extBinInfoSize < fb->len) {
|
||||
// if (value.extBinInfo) free(value.extBinInfo);
|
||||
// value.extBinInfo = (uint8_t*)malloc(sizeof(uint8_t) * fb->len);
|
||||
// }
|
||||
memcpy(value.extBinInfo, fb->buf, fb->len);
|
||||
value.extBinInfoSize = fb->len;
|
||||
|
||||
Serial.printf("try send pic by size=%d", fb->len);
|
||||
|
||||
if (_useLed) digitalWrite(4, LOW);
|
||||
if (_ticker) regEvent("shot", "EspCam");
|
||||
esp_camera_fb_return(fb);
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
take_picture();
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
if (command == "shot") {
|
||||
take_picture();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
~EspCam() {
|
||||
free(value.extBinInfo);
|
||||
//globalItem = nullptr;
|
||||
};
|
||||
};
|
||||
|
||||
void* getAPI_EspCam(String subtype, String param) {
|
||||
if (subtype == F("EspCam")) {
|
||||
return new EspCam(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "Camera OV2640 (ESPcam)",
|
||||
"type": "Reading",
|
||||
"subtype": "EspCam",
|
||||
"id": "EspCam",
|
||||
"widget": "",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
|
||||
"int": 60,
|
||||
"useLed": 0,
|
||||
"ticker": 0,
|
||||
"webTicker": 0
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "EspCam",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Предназначен для специальной платы esp32 со встроенной камерой. Добавляет в прошивку функцию создания фото и сохранения в оперативную память. Для сброса на флешкарту необходимо использовать парный модуль SDcard. Это экспериментальные модули и в будущем планируется пересобрать их.",
|
||||
"propInfo": {
|
||||
"int": "Пауза в секундах во время постоянной съемки.",
|
||||
"useLed": "использовать диод подсветки при съемке.",
|
||||
"ticker": "Генерировать(1) или нет(0) событие с интервалом int",
|
||||
"webTicker": "Генерировать(1) или нет(0) событие при обращении через веб-страницу с текущим фото в памяти."
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": false,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [
|
||||
"espressif/esp32-camera @ ^2.0.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
#include "classes/IoTGpio.h"
|
||||
|
||||
extern IoTGpio IoTgpio;
|
||||
|
||||
#include <Servo.h>
|
||||
|
||||
class IoTServo : public IoTItem {
|
||||
private:
|
||||
Servo servObj;
|
||||
int _apin, _oldValue;
|
||||
int _locmap1, _locmap2, _locmap3, _locmap4;
|
||||
|
||||
public:
|
||||
IoTServo(String parameters): IoTItem(parameters) {
|
||||
int pin;
|
||||
jsonRead(parameters, "pin", pin);
|
||||
servObj.attach(pin);
|
||||
|
||||
jsonRead(parameters, "apin", _apin);
|
||||
if (_apin >= 0) IoTgpio.pinMode(_apin, INPUT);
|
||||
|
||||
String map;
|
||||
jsonRead(parameters, F("amap"), map, false);
|
||||
if (map != "") {
|
||||
_locmap1 = selectFromMarkerToMarker(map, ",", 0).toInt();
|
||||
_locmap2 = selectFromMarkerToMarker(map, ",", 1).toInt();
|
||||
_locmap3 = selectFromMarkerToMarker(map, ",", 2).toInt();
|
||||
_locmap4 = selectFromMarkerToMarker(map, ",", 3).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (_apin >= 0) {
|
||||
value.valD = map(IoTgpio.analogRead(_apin), _locmap1, _locmap2, _locmap3, _locmap4);
|
||||
if (abs(_oldValue - value.valD) > 5) {
|
||||
_oldValue = value.valD;
|
||||
servObj.write(_oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
if (command == "rotate") {
|
||||
if (param.size()) {
|
||||
value.valD = param[0].valD;
|
||||
servObj.write(value.valD);
|
||||
regEvent(value.valD, "IoTServo");
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void setValue(IoTValue Value) {
|
||||
value = Value;
|
||||
if (value.isDecimal & (_oldValue != value.valD)) {
|
||||
_oldValue = value.valD;
|
||||
servObj.write(_oldValue);
|
||||
regEvent(value.valD, "IoTServo");
|
||||
}
|
||||
}
|
||||
|
||||
~IoTServo() {};
|
||||
};
|
||||
|
||||
void* getAPI_IoTServo(String subtype, String param) {
|
||||
if (subtype == F("IoTServo")) {
|
||||
return new IoTServo(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "Сервопривод",
|
||||
"type": "Writing",
|
||||
"subtype": "IoTServo",
|
||||
"id": "servo",
|
||||
"widget": "range",
|
||||
"page": "servo",
|
||||
"descr": "угол",
|
||||
|
||||
"int": 1,
|
||||
"pin": 12,
|
||||
"apin": -1,
|
||||
"amap": "0, 4096, 0, 180"
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "Oleg @Threedreality, Sergey @Serghei63",
|
||||
"moduleName": "IoTServo",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Предназначен для управления сервоприводом по уровню аналогово сигнала.",
|
||||
"propInfo": {
|
||||
"int": "Пауза в секундах между опросами аналогового входа. Если 0, то читаем постоянно",
|
||||
"pin": "Пин, к которому подключен сервопривод",
|
||||
"apin": "Номер GPIO аналогового пина. Если -1, то функция отключена.",
|
||||
"amap": "Настройки преобразования значений аналога в нужный диапазон сервы, имеет смысл, если аналог включен."
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [
|
||||
"https://github.com/RoboticsBrno/ServoESP32"
|
||||
],
|
||||
"esp8266_4mb": []
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
#include "SoftwareSerial.h" // Подключаем библиотеку SoftwareSerial
|
||||
#include "DFRobotDFPlayerMini.h" // Подключаем библиотеку DFPlayerMini_Fast
|
||||
|
||||
|
||||
class Mp3 : public IoTItem {
|
||||
private:
|
||||
SoftwareSerial* mySerial;
|
||||
DFRobotDFPlayerMini* myMP3;
|
||||
|
||||
public:
|
||||
Mp3(String parameters): IoTItem(parameters) {
|
||||
String tmpstr;
|
||||
int volumetmp;
|
||||
jsonRead(parameters, "pins", tmpstr);
|
||||
int pinRx = selectFromMarkerToMarker(tmpstr, ",", 0).toInt();
|
||||
int pinTx = selectFromMarkerToMarker(tmpstr, ",", 1).toInt();
|
||||
mySerial = new SoftwareSerial(pinRx, pinTx);
|
||||
pinMode(pinRx, INPUT);
|
||||
pinMode(pinTx, OUTPUT);
|
||||
|
||||
jsonRead(parameters, "volume", volumetmp);
|
||||
|
||||
if (mySerial) {
|
||||
mySerial->begin(9600);
|
||||
myMP3 = new DFRobotDFPlayerMini();
|
||||
}
|
||||
if (myMP3) {
|
||||
myMP3->begin(*mySerial);
|
||||
myMP3->volume(volumetmp);
|
||||
}
|
||||
|
||||
value.isDecimal = false; // значение объекта всегда будет строка
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (myMP3 && myMP3->available()) {
|
||||
switch (myMP3->readType()) {
|
||||
case TimeOut:
|
||||
value.valS = F("Time Out!");
|
||||
break;
|
||||
case WrongStack:
|
||||
value.valS = F("Stack Wrong!");
|
||||
break;
|
||||
case DFPlayerCardInserted:
|
||||
value.valS = F("Card Inserted!");
|
||||
break;
|
||||
case DFPlayerCardRemoved:
|
||||
value.valS = F("Card Removed!");
|
||||
break;
|
||||
case DFPlayerCardOnline:
|
||||
value.valS = F("Card Online!");
|
||||
break;
|
||||
case DFPlayerPlayFinished:
|
||||
value.valS = F("Play Finished!");
|
||||
break;
|
||||
case DFPlayerError:
|
||||
switch (myMP3->read()) {
|
||||
case Busy:
|
||||
value.valS = F("Card not found");
|
||||
break;
|
||||
case Sleeping:
|
||||
value.valS = F("Sleeping");
|
||||
break;
|
||||
case SerialWrongStack:
|
||||
value.valS = F("Get Wrong Stack");
|
||||
break;
|
||||
case CheckSumNotMatch:
|
||||
value.valS = F("Check Sum Not Match");
|
||||
break;
|
||||
case FileIndexOut:
|
||||
value.valS = F("File Index Out of Bound");
|
||||
break;
|
||||
case FileMismatch:
|
||||
value.valS = F("Cannot Find File");
|
||||
break;
|
||||
case Advertise:
|
||||
value.valS = F("In Advertise");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
// реакция на вызов команды модуля из сценария
|
||||
// String command - имя команды после ID. (ID.Команда())
|
||||
// param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22
|
||||
|
||||
if (myMP3) {
|
||||
if (command == "enableLoop") {
|
||||
myMP3->enableLoop();
|
||||
} else if (command == "disableLoop") {
|
||||
myMP3->disableLoop();
|
||||
} else if (command == "randomAll") {
|
||||
myMP3->randomAll();
|
||||
} else if (command == "stop") {
|
||||
myMP3->stop();
|
||||
} else if (command == "volume") {
|
||||
if (param.size()) {
|
||||
myMP3->volume(param[0].valD);
|
||||
}
|
||||
} else if (command == "playFolder") {
|
||||
if (param.size()) {
|
||||
myMP3->playFolder(param[0].valD, param[1].valD); // (folderNum, fileNum)
|
||||
}
|
||||
} else if (command == "play") {
|
||||
myMP3->play(1); //Play the first mp3
|
||||
} else if (command == "next") {
|
||||
myMP3->next(); //Play next mp3
|
||||
} else if (command == "previous") {
|
||||
myMP3->previous(); //Play previous mp3
|
||||
}
|
||||
}
|
||||
|
||||
return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки
|
||||
}
|
||||
|
||||
~Mp3() {};
|
||||
};
|
||||
|
||||
void* getAPI_Mp3(String subtype, String param) {
|
||||
if (subtype == F("Mp3")) {
|
||||
return new Mp3(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "MP3 плеер",
|
||||
"type": "Reading",
|
||||
"subtype": "Mp3",
|
||||
"id": "mp3",
|
||||
"widget": "",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
|
||||
"int": 1,
|
||||
"pins": "14,12",
|
||||
"volume": 20
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "Mp3",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Позволяет управлять модулем проигрывания MP3 файлов с SD-карты по serial интерфейсу (DFplayer mini).",
|
||||
"propInfo": {
|
||||
"int": "Периодичность в секундах опроса состояния плеера.",
|
||||
"pins": "Список GPIO через запятую, к которым подключен плеер.",
|
||||
"volume": "Уровень громкости при инициализации."
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [
|
||||
"dfrobot/DFRobotDFPlayerMini @ ^1.0.5"
|
||||
],
|
||||
"esp8266_4mb": [
|
||||
"dfrobot/DFRobotDFPlayerMini @ ^1.0.5"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "esp32-hal.h"
|
||||
#include "esp32-hal-ledc.h"
|
||||
|
||||
extern IoTGpio IoTgpio;
|
||||
|
||||
class Pwm32 : public IoTItem {
|
||||
private:
|
||||
int _pin;
|
||||
int _freq;
|
||||
int _apin, _oldValue;
|
||||
bool _freezVal = true;
|
||||
int _ledChannel;
|
||||
int _resolution;
|
||||
|
||||
public:
|
||||
Pwm32(String parameters): IoTItem(parameters) {
|
||||
_interval = _interval / 1000; // корректируем величину интервала int, теперь он в миллисекундах
|
||||
|
||||
jsonRead(parameters, "pin", _pin);
|
||||
jsonRead(parameters, "freq", _freq);
|
||||
jsonRead(parameters, "ledChannel", _ledChannel);
|
||||
jsonRead(parameters, "PWM_resolution", _resolution);
|
||||
|
||||
pinMode(_pin, OUTPUT);
|
||||
ledcSetup(_ledChannel, _freq, _resolution);
|
||||
ledcAttachPin(_pin, _ledChannel);
|
||||
ledcWrite(_ledChannel, value.valD);
|
||||
|
||||
_resolution = pow(2, _resolution); // переводим биты в значение
|
||||
|
||||
jsonRead(parameters, "apin", _apin);
|
||||
if (_apin >= 0) IoTgpio.pinMode(_apin, INPUT);
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (_apin >= 0) {
|
||||
value.valD = map(IoTgpio.analogRead(_apin), 0, 4095, 0, _resolution);
|
||||
if (value.valD > _resolution - 6) value.valD = _resolution; // нивелируем погрешность установки мин и макс
|
||||
else if (value.valD < 9) value.valD = 0; // из-за смягчения значений
|
||||
if (abs(_oldValue - value.valD) > 20) {
|
||||
_oldValue = value.valD;
|
||||
ledcWrite(_ledChannel, value.valD);
|
||||
_freezVal = false;
|
||||
} else {
|
||||
if (!_freezVal) { // отправляем событие только раз после серии изменений, чтоб не спамить события
|
||||
regEvent(value.valD, "Pwm32");
|
||||
_freezVal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setValue(IoTValue Value) {
|
||||
value = Value;
|
||||
ledcWrite(_ledChannel, value.valD);
|
||||
regEvent(value.valD, "Pwm32");
|
||||
}
|
||||
//=======================================================================================================
|
||||
|
||||
~Pwm32() {};
|
||||
};
|
||||
|
||||
|
||||
void* getAPI_Pwm32(String subtype, String param) {
|
||||
if (subtype == F("Pwm32")) {
|
||||
return new Pwm32(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "PWM ESP32",
|
||||
"type": "Writing",
|
||||
"subtype": "Pwm32",
|
||||
"id": "pwm",
|
||||
"widget": "range",
|
||||
"page": "Кнопки",
|
||||
"descr": "PWM",
|
||||
"int": 0,
|
||||
"pin": 2,
|
||||
"freq": 5000,
|
||||
"ledChannel": 2,
|
||||
"PWM_resolution": 10,
|
||||
"val": 0,
|
||||
"apin": -1
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Avaks",
|
||||
"authorContact": "https://t.me/Avaks",
|
||||
"authorGit": "https://github.com/avaksru",
|
||||
"specialThanks": "Serghei Crasnicov @Serghei63",
|
||||
"moduleName": "Pwm32",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Позволяет управлять Широтно-Импульсной Модуляцией на конкретном пине платы.",
|
||||
"propInfo": {
|
||||
"int": "Количество миллисекунд между опросами аналога. 0 - выключено.",
|
||||
"pin": "Управляемый пин",
|
||||
"apin": "Номер GPIO аналогового пина. Если -1, то функция отключена.",
|
||||
"ledChannel": "Канал ШИМ",
|
||||
"PWM_resolution": "Разрешение, определяет диапазон значений от 1 до 16 => от 1 до 65536",
|
||||
"freq": "Частота"
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": []
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
extern IoTGpio IoTgpio;
|
||||
|
||||
class Pwm8266 : public IoTItem {
|
||||
private:
|
||||
int _pin;
|
||||
int _freq;
|
||||
int _apin, _oldValue;
|
||||
bool _freezVal = true;
|
||||
|
||||
public:
|
||||
Pwm8266(String parameters): IoTItem(parameters) {
|
||||
_interval = _interval / 1000; // корректируем величину интервала int, теперь он в миллисекундах
|
||||
|
||||
jsonRead(parameters, "pin", _pin);
|
||||
jsonRead(parameters, "freq", _freq);
|
||||
|
||||
IoTgpio.pinMode(_pin, OUTPUT);
|
||||
analogWriteFreq(_freq);
|
||||
IoTgpio.analogWrite(_pin, value.valD);
|
||||
|
||||
jsonRead(parameters, "apin", _apin);
|
||||
if (_apin >= 0) IoTgpio.pinMode(_apin, INPUT);
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (_apin >= 0) {
|
||||
value.valD = IoTgpio.analogRead(_apin);
|
||||
if (value.valD > 1018) value.valD = 1024; // нивелируем погрешность установки мин и макс
|
||||
else if (value.valD < 9) value.valD = 0; // из-за смягчения значений
|
||||
if (abs(_oldValue - value.valD) > 5) {
|
||||
_oldValue = value.valD;
|
||||
analogWrite(_pin,value.valD);
|
||||
_freezVal = false;
|
||||
} else {
|
||||
if (!_freezVal) { // отправляем событие только раз после серии изменений, чтоб не спамить события
|
||||
regEvent(value.valD, "Pwm8266");
|
||||
_freezVal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setValue(IoTValue Value) {
|
||||
value = Value;
|
||||
IoTgpio.analogWrite(_pin, value.valD);
|
||||
regEvent(value.valD, "Pwm8266");
|
||||
}
|
||||
//=======================================================================================================
|
||||
|
||||
~Pwm8266() {};
|
||||
};
|
||||
|
||||
|
||||
void* getAPI_Pwm8266(String subtype, String param) {
|
||||
if (subtype == F("Pwm8266")) {
|
||||
return new Pwm8266(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "PWM ESP8266",
|
||||
"type": "Writing",
|
||||
"subtype": "Pwm8266",
|
||||
"id": "pwm",
|
||||
"widget": "range",
|
||||
"page": "Кнопки",
|
||||
"descr": "PWM",
|
||||
"int": 0,
|
||||
"pin": 15,
|
||||
"freq": 5000,
|
||||
"val": 0,
|
||||
"apin": -1
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Avaks",
|
||||
"authorContact": "https://t.me/Avaks",
|
||||
"authorGit": "https://github.com/avaksru",
|
||||
"specialThanks": "Serghei Crasnicov @Serghei63",
|
||||
"moduleName": "Pwm8266",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Позволяет управлять Широтно-Импульсной Модуляцией на конкретном пине платы.",
|
||||
"propInfo": {
|
||||
"int": "Количество миллисекунд между опросами аналога. 0 - выключено.",
|
||||
"pin": "Управляемый пин",
|
||||
"apin": "Номер GPIO аналогового пина. Если -1, то функция отключена.",
|
||||
"freq": "Частота"
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp8266_4mb": []
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
|
||||
#include "FS.h" // SD Card ESP32
|
||||
#include "SD_MMC.h" // SD Card ESP32
|
||||
|
||||
class SDcard : public IoTItem {
|
||||
private:
|
||||
|
||||
public:
|
||||
SDcard(String parameters): IoTItem(parameters) {
|
||||
// jsonRead(parameters, "useLed", _useLed); // используем = 1 или нет = 0 подсветку (вспышку)
|
||||
// jsonRead(parameters, "ticker", _ticker); // тикать = 1 - сообщаем всем, что сделали снимок и он готов
|
||||
// jsonRead(parameters, "webTicker", _webTicker); // сообщать всем, что через веб попросили отдать картинку с камеры
|
||||
|
||||
Serial.println("Starting SD Card");
|
||||
if(!SD_MMC.begin()){
|
||||
Serial.println("SD Card Mount Failed");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t cardType = SD_MMC.cardType();
|
||||
if(cardType == CARD_NONE){
|
||||
Serial.println("No SD Card attached");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void savePicture(String path, IoTValue srcValue) {
|
||||
if (srcValue.extBinInfoSize) {
|
||||
fs::FS &fs = SD_MMC;
|
||||
File file = fs.open(path.c_str(), FILE_WRITE);
|
||||
if(!file){
|
||||
Serial.println("Failed to open file in writing mode");
|
||||
}
|
||||
else {
|
||||
file.write(srcValue.extBinInfo, srcValue.extBinInfoSize); // payload (image), payload length
|
||||
Serial.printf("Picture file name: %s | bufsize: %d\n", path.c_str(), srcValue.extBinInfoSize);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
if (command == "saveBin") {
|
||||
if (param.size() == 2) {
|
||||
savePicture (param[0].valS, param[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
~SDcard() {
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
void* getAPI_SDcard(String subtype, String param) {
|
||||
if (subtype == F("SDcard")) {
|
||||
return new SDcard(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "SD карта",
|
||||
"type": "Writing",
|
||||
"subtype": "SDcard",
|
||||
"id": "sd",
|
||||
"widget": "",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
|
||||
"int": 1
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "SDcard",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Предназначен для специальной платы esp32 со встроенной камерой. Добавляет в прошивку функцию сохранения фото из оперативной памяти. Работает в паре с EspCam. Это экспериментальные модули и в будущем планируется пересобрать их.",
|
||||
"propInfo": {
|
||||
"int": "Не используется."
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": false,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [
|
||||
"espressif/esp32-camera @ ^2.0.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
#include "CTBot.h"
|
||||
|
||||
String uint64ToString(uint64_t input) {
|
||||
String result = "";
|
||||
uint8_t base = 10;
|
||||
|
||||
do {
|
||||
char c = input % base;
|
||||
input /= base;
|
||||
|
||||
if (c < 10)
|
||||
c +='0';
|
||||
else
|
||||
c += 'A' - 10;
|
||||
result = c + result;
|
||||
} while (input);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
class Telegram : public IoTItem {
|
||||
private:
|
||||
CTBot _myBot;
|
||||
String _token;
|
||||
bool _autos;
|
||||
bool _receiveMsg;
|
||||
int64_t _chatID;
|
||||
|
||||
String _prevMsg = "";
|
||||
|
||||
void telegramMsgParse(String msg) {
|
||||
if (msg.indexOf("set") != -1) {
|
||||
msg = deleteBeforeDelimiter(msg, "_");
|
||||
generateOrder(selectToMarker(msg, "_"), selectToMarkerLast(msg, "_"));
|
||||
_myBot.sendMessage(_chatID, "order done");
|
||||
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + String(msg));
|
||||
} else if (msg.indexOf("get") != -1) {
|
||||
msg = deleteBeforeDelimiter(msg, "_");
|
||||
IoTItem* item = findIoTItem(msg);
|
||||
if (item) {
|
||||
_myBot.sendMessage(_chatID, item->getValue());
|
||||
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + String(msg));
|
||||
}
|
||||
} else if (msg.indexOf("all") != -1) {
|
||||
String list = returnListOfParams();
|
||||
_myBot.sendMessage(_chatID, list);
|
||||
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + "\n" + list);
|
||||
} else if (msg.indexOf("help") != -1) {
|
||||
_myBot.sendMessage(_chatID, "ID: " + chipId);
|
||||
_myBot.sendMessage(_chatID, "chatID: " + uint64ToString(_chatID));
|
||||
_myBot.sendMessage(_chatID, F("Wrong order, use /all to get all values, /get_id to get value, or /set_id_value to set value"));
|
||||
} else {
|
||||
setValue(msg);
|
||||
}
|
||||
}
|
||||
|
||||
String returnListOfParams() {
|
||||
String out;
|
||||
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||||
if ((*it)->iAmLocal) out = out + (*it)->getID() + ": " + (*it)->getValue() + "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public:
|
||||
Telegram(String parameters): IoTItem(parameters) {
|
||||
jsonRead(parameters, "token", _token);
|
||||
jsonRead(parameters, "autos", _autos);
|
||||
jsonRead(parameters, "receiveMsg", _receiveMsg);
|
||||
|
||||
String tmp;
|
||||
jsonRead(parameters, "chatID", tmp);
|
||||
_chatID = atoll(tmp.c_str());
|
||||
|
||||
#ifdef ESP32
|
||||
_myBot.useDNS(true);
|
||||
#endif
|
||||
|
||||
_myBot.setTelegramToken(_token);
|
||||
_myBot.enableUTF8Encoding(true);
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (_receiveMsg) {
|
||||
TBMessage msg;
|
||||
if (_myBot.getNewMessage(msg)) {
|
||||
SerialPrint("->", F("Telegram"), "chat ID: " + uint64ToString(msg.sender.id) + ", msg: " + msg.text);
|
||||
if (_autos) {
|
||||
_chatID = msg.sender.id;
|
||||
}
|
||||
telegramMsgParse(String(msg.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
if (command == "sendMsg") {
|
||||
if (param.size()) {
|
||||
String strTmp;
|
||||
if (param[0].isDecimal) strTmp = param[0].valD; else strTmp = param[0].valS;
|
||||
sendTelegramMsg(false, strTmp);
|
||||
}
|
||||
} else if (command == "sendOftenMsg") {
|
||||
if (param.size()) {
|
||||
String strTmp;
|
||||
if (param[0].isDecimal) strTmp = param[0].valD; else strTmp = param[0].valS;
|
||||
sendTelegramMsg(true, strTmp);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void sendTelegramMsg(bool often, String msg) {
|
||||
if (often) {
|
||||
_myBot.sendMessage(_chatID, msg);
|
||||
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + msg);
|
||||
} else {
|
||||
if (_prevMsg != msg) {
|
||||
_prevMsg = msg;
|
||||
_myBot.sendMessage(_chatID, msg);
|
||||
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~Telegram() {
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
void* getAPI_Telegram(String subtype, String param) {
|
||||
if (subtype == F("Telegram")) {
|
||||
return new Telegram(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "Телеграм-Бот",
|
||||
"type": "Writing",
|
||||
"subtype": "Telegram",
|
||||
"id": "tg",
|
||||
"widget": "",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
"int": 10,
|
||||
|
||||
"token": "",
|
||||
"autos": 1,
|
||||
"receiveMsg": 0,
|
||||
"chatID": ""
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "Telegram",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Добавляет возможность отправлять сообщения от имени бота контакту в Телеграм-чате и получать команды.",
|
||||
"propInfo": {
|
||||
"token": "Токен для авторизации бота в системе Telegram",
|
||||
"autos": "Автоматически(1) или нет(0) запоминать ChatID по входящим сообщениям. Т.е. бот будет информировать тех, кто последний прислал сообщение.",
|
||||
"receiveMsg": "Обрабатывать(1) или нет(0) входящие сообщения.",
|
||||
"chatID": "ИД диалога с контактом. Необходим для отправки сообщений именно вам."
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": false,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [
|
||||
"CTBot @2.1.9"
|
||||
],
|
||||
"esp8266_4mb": [
|
||||
"CTBot @2.1.9"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
#include "Global.h"
|
||||
#include "classes/IoTItem.h"
|
||||
|
||||
extern IoTGpio IoTgpio;
|
||||
|
||||
|
||||
class Timer : public IoTItem {
|
||||
private:
|
||||
bool _unfin = false;
|
||||
bool _ticker = false;
|
||||
bool _repeat = false;
|
||||
bool _needSave = false;
|
||||
bool _pause = false;
|
||||
int _initValue;
|
||||
|
||||
public:
|
||||
Timer(String parameters): IoTItem(parameters) {
|
||||
jsonRead(parameters, "countDown", _initValue);
|
||||
_unfin = !_initValue;
|
||||
value.valD = _initValue;
|
||||
if (_initValue) value.valD = value.valD + 1; // +1 - компенсируем ранний вычет счетчика, ранний вычет, чтоб после события значение таймера не исказилось.
|
||||
// +0 - если изначально установили бесконечный счет
|
||||
|
||||
jsonRead(parameters, "ticker", _ticker);
|
||||
jsonRead(parameters, "repeat", _repeat);
|
||||
jsonRead(parameters, "needSave", _needSave); // нужно сохранять счетчик в постоянную память
|
||||
}
|
||||
|
||||
void doByInterval() {
|
||||
if (!_unfin && value.valD >= 0 && !_pause) {
|
||||
value.valD--;
|
||||
if (_repeat && value.valD == -1) value.valD = _initValue;
|
||||
if (_needSave) needSave = true;
|
||||
if (value.valD == 0) {
|
||||
regEvent(value.valD, "Time's up");
|
||||
}
|
||||
}
|
||||
|
||||
if (_ticker && (value.valD > 0 || _unfin) && !_pause) regEvent(value.valD, "Timer tick");
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m) {
|
||||
if (command == "stop") {
|
||||
_pause = true;
|
||||
} else if (command == "reset") {
|
||||
_pause = false;
|
||||
value.valD = _initValue;
|
||||
if (_initValue) value.valD = value.valD + 1;
|
||||
} else if (command == "continue") {
|
||||
_pause = false;
|
||||
} else if (command == "int") {
|
||||
if (param.size()) {
|
||||
setInterval(param[0].valD);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
~Timer() {};
|
||||
};
|
||||
|
||||
void* getAPI_Timer(String subtype, String param) {
|
||||
if (subtype == F("Timer")) {
|
||||
return new Timer(param);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"menuSection": "Модули управления",
|
||||
|
||||
"configItem": [{
|
||||
"name": "Таймер",
|
||||
"type": "Writing",
|
||||
"subtype": "Timer",
|
||||
"id": "timer",
|
||||
"widget": "",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
|
||||
"int": 1,
|
||||
"countDown": 15,
|
||||
"ticker": 0,
|
||||
"repeat": 0,
|
||||
"needSave": 0
|
||||
}],
|
||||
|
||||
"about": {
|
||||
"authorName": "Ilya Belyakov",
|
||||
"authorContact": "https://t.me/Biveraxe",
|
||||
"authorGit": "https://github.com/biveraxe",
|
||||
"specialThanks": "",
|
||||
"moduleName": "Timer",
|
||||
"moduleVersion": "1.0",
|
||||
"moduleDesc": "Добавляет инструмент таймеров обратного отсчета для организации периодичных операций или логических конструкций. Часто используется как вспомогательный элемент для автоматизации.",
|
||||
"propInfo": {
|
||||
"int": "Задает размер в секундах одного шага(тика) таймера.",
|
||||
"countDown": "Начальное значение таймера, с которого начинается обратный отсчет.",
|
||||
"ticker": "Генерировать(1) или нет(0) события при каждом тике таймера.",
|
||||
"repeat": "Сбрасывать(1) или нет(0) таймер в начальное состояние при достижении нуля.",
|
||||
"needSave": "Требуется сохранять(1) или нет(0) состояние в энерго независимую память. Функция находится в разработке."
|
||||
}
|
||||
},
|
||||
|
||||
"defActive": true,
|
||||
|
||||
"devices": {
|
||||
"esp32_4mb": [],
|
||||
"esp8266_4mb": []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user