Структурируем модули как надо

This commit is contained in:
2022-08-11 17:40:42 +03:00
parent 1ddc3aab9c
commit 799aff3383
70 changed files with 281 additions and 281 deletions

View File

@@ -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;
}
}

View File

@@ -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": []
}
}

View File

@@ -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> &param) {
// реакция на вызов команды модуля из сценария
// 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;
}
}

View File

@@ -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": []
}
}

View File

@@ -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> &param) {
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;
}
}

View File

@@ -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"
]
}
}

View File

@@ -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> &param) {
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;
}
}

View File

@@ -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": []
}
}

View File

@@ -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> &param) {
// реакция на вызов команды модуля из сценария
// 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;
}
}

View File

@@ -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"
]
}
}

View File

@@ -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;
}
}

View File

@@ -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": []
}
}

View File

@@ -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;
}
}

View File

@@ -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": []
}
}

View File

@@ -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> &param) {
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;
}
}

View File

@@ -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"
]
}
}

View File

@@ -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> &param) {
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;
}
}

View File

@@ -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"
]
}
}

View File

@@ -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> &param) {
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;
}
}

View File

@@ -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": []
}
}