From c078c816369f2ca372e27d67d0b40f0ba1e8ea2f Mon Sep 17 00:00:00 2001 From: biver Date: Tue, 16 May 2023 15:24:30 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D0=B5=D0=BC=20=D0=BC=D0=BE=D1=83=D0=BB=D1=8C=20Buzzer=20=D0=B8?= =?UTF-8?q?=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7=D0=B8?= =?UTF-8?q?=D1=80=D1=83=D0=B5=D0=BC=20def=20=D0=BF=D1=80=D0=BE=D1=84=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 +- data_svelte/items.json | 222 ++++++++++------ data_svelte/myProfile.json | 16 ++ myProfile.json | 16 ++ platformio.ini | 5 + src/modules/API.cpp | 8 + src/modules/exec/Buzzer/Buzzer.cpp | 382 +++++++++++++++++++++++++++ src/modules/exec/Buzzer/export.json | 268 +++++++++++++++++++ src/modules/exec/Buzzer/modinfo.json | 96 +++++++ 9 files changed, 936 insertions(+), 84 deletions(-) create mode 100644 src/modules/exec/Buzzer/Buzzer.cpp create mode 100644 src/modules/exec/Buzzer/export.json create mode 100644 src/modules/exec/Buzzer/modinfo.json diff --git a/.gitignore b/.gitignore index 41f063ef..d74a9041 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,3 @@ .pio -.vscode/.browse.c_cpp.db* -.vscode/c_cpp_properties.json -.vscode/launch.json -.vscode/ipch +.vscode /myProfile_wm.json -/myProfile.json -data_svelte/settings.json diff --git a/data_svelte/items.json b/data_svelte/items.json index 7e530a2f..f8cc2674 100644 --- a/data_svelte/items.json +++ b/data_svelte/items.json @@ -192,7 +192,19 @@ "header": "Сенсоры" }, { - "name": "13. Acs712 Ток", + "name": "13. A02 Дальность", + "type": "Reading", + "subtype": "A02Distance", + "id": "dist", + "widget": "anydataCm", + "page": "Сенсоры", + "descr": "Дальность", + "int": 5, + "round": 1, + "num": 13 + }, + { + "name": "14. Acs712 Ток", "type": "Reading", "subtype": "Acs712", "id": "amp", @@ -207,11 +219,11 @@ "sens": 100, "adczero": 512, "btn-setZero": "nil", - "num": 13 + "num": 14 }, { "global": 0, - "name": "14. AHTXX Температура", + "name": "15. AHTXX Температура", "type": "Reading", "subtype": "AhtXXt", "id": "Temp20", @@ -222,11 +234,11 @@ "addr": "0x38", "shtType": 1, "round": 1, - "num": 14 + "num": 15 }, { "global": 0, - "name": "15. AHTXX Влажность", + "name": "16. AHTXX Влажность", "type": "Reading", "subtype": "AhtXXh", "id": "Hum20", @@ -237,11 +249,11 @@ "addr": "0x38", "shtType": 1, "round": 1, - "num": 15 + "num": 16 }, { "global": 0, - "name": "16. Аналоговый сенсор", + "name": "17. Аналоговый сенсор", "type": "Reading", "subtype": "AnalogAdc", "id": "t", @@ -255,11 +267,11 @@ "pin": 0, "int": 15, "avgSteps": 1, - "num": 16 + "num": 17 }, { "global": 0, - "name": "17. BME280 Температура", + "name": "18. BME280 Температура", "type": "Reading", "subtype": "Bme280t", "id": "Tmp3", @@ -269,11 +281,11 @@ "int": 15, "addr": "0x77", "round": 1, - "num": 17 + "num": 18 }, { "global": 0, - "name": "18. BME280 Давление", + "name": "19. BME280 Давление", "type": "Reading", "subtype": "Bme280p", "id": "Press3", @@ -283,11 +295,11 @@ "int": 15, "addr": "0x77", "round": 1, - "num": 18 + "num": 19 }, { "global": 0, - "name": "19. BME280 Влажность", + "name": "20. BME280 Влажность", "type": "Reading", "subtype": "Bme280h", "id": "Hum3", @@ -297,11 +309,11 @@ "int": 15, "addr": "0x77", "round": 1, - "num": 19 + "num": 20 }, { "global": 0, - "name": "20. BME280 Tочка росы", + "name": "21. BME280 Tочка росы", "type": "Reading", "subtype": "Bme280dp", "id": "Dew3", @@ -311,11 +323,11 @@ "int": 15, "addr": "0x77", "round": 1, - "num": 20 + "num": 21 }, { "global": 0, - "name": "21. BMP280 Температура", + "name": "22. BMP280 Температура", "type": "Reading", "subtype": "Bmp280t", "id": "tmp3", @@ -325,11 +337,11 @@ "int": 15, "addr": "0x77", "round": 1, - "num": 21 + "num": 22 }, { "global": 0, - "name": "22. BMP280 Давление", + "name": "23. BMP280 Давление", "type": "Reading", "subtype": "Bmp280p", "id": "Press3", @@ -339,11 +351,11 @@ "int": 15, "addr": "0x77", "round": 1, - "num": 22 + "num": 23 }, { "global": 0, - "name": "23. DHT11 Температура", + "name": "24. DHT11 Температура", "type": "Reading", "subtype": "Dht1122t", "id": "tmp3", @@ -353,11 +365,11 @@ "int": 15, "pin": 0, "senstype": "dht11", - "num": 23 + "num": 24 }, { "global": 0, - "name": "24. DHT11 Влажность", + "name": "25. DHT11 Влажность", "type": "Reading", "subtype": "Dht1122h", "id": "Hum3", @@ -367,11 +379,11 @@ "int": 15, "pin": 0, "senstype": "dht11", - "num": 24 + "num": 25 }, { "global": 0, - "name": "25. DS18B20 Температура", + "name": "26. DS18B20 Температура", "type": "Reading", "subtype": "Ds18b20", "id": "dstmp", @@ -383,11 +395,11 @@ "index": 0, "addr": "", "round": 1, - "num": 25 + "num": 26 }, { "global": 0, - "name": "26. Аналоговый счетчик импульсов", + "name": "27. Аналоговый счетчик импульсов", "type": "Writing", "subtype": "Impulse", "id": "impulse", @@ -400,11 +412,11 @@ "pinMode": "INPUT", "debounceDelay": 3, "multiply": 1, - "num": 26 + "num": 27 }, { "global": 0, - "name": "27. PZEM 004t Напряжение", + "name": "28. PZEM 004t Напряжение", "type": "Reading", "subtype": "Pzem004v", "id": "v", @@ -414,11 +426,11 @@ "int": 15, "addr": "0xF8", "round": 1, - "num": 27 + "num": 28 }, { "global": 0, - "name": "28. PZEM 004t Сила тока", + "name": "29. PZEM 004t Сила тока", "type": "Reading", "subtype": "Pzem004a", "id": "a", @@ -428,11 +440,11 @@ "int": 15, "addr": "0xF8", "round": 1, - "num": 28 + "num": 29 }, { "global": 0, - "name": "29. PZEM 004t Мощность", + "name": "30. PZEM 004t Мощность", "type": "Reading", "subtype": "Pzem004w", "id": "w", @@ -442,11 +454,11 @@ "int": 15, "addr": "0xF8", "round": 1, - "num": 29 + "num": 30 }, { "global": 0, - "name": "30. PZEM 004t Энергия", + "name": "31. PZEM 004t Энергия", "type": "Reading", "subtype": "Pzem004wh", "id": "wh", @@ -456,11 +468,11 @@ "int": 15, "addr": "0xF8", "round": 1, - "num": 30 + "num": 31 }, { "global": 0, - "name": "31. PZEM 004t Частота", + "name": "32. PZEM 004t Частота", "type": "Reading", "subtype": "Pzem004hz", "id": "hz", @@ -470,11 +482,11 @@ "int": 15, "addr": "0xF8", "round": 1, - "num": 31 + "num": 32 }, { "global": 0, - "name": "32. PZEM 004t Косинус", + "name": "33. PZEM 004t Косинус", "type": "Reading", "subtype": "Pzem004pf", "id": "pf", @@ -484,11 +496,11 @@ "int": 15, "addr": "0xF8", "round": 1, - "num": 32 + "num": 33 }, { "global": 0, - "name": "33. PZEM настройка", + "name": "34. PZEM настройка", "type": "Reading", "subtype": "Pzem004cmd", "id": "set", @@ -500,11 +512,11 @@ "changeaddr": 0, "setaddr": "0x01", "reset": 0, - "num": 33 + "num": 34 }, { "global": 0, - "name": "34. Часы реального времени", + "name": "35. Часы реального времени", "type": "Reading", "subtype": "RTC", "id": "rtc", @@ -520,11 +532,25 @@ "int": 5, "btn-setUTime": "0", "btn-setSysTime": "nil", - "num": 34 + "num": 35 + }, + { + "name": "36. (S8) Cенсор качества воздуха", + "num": 36, + "type": "Reading", + "subtype": "S8co", + "id": "s8co", + "widget": "anydataPpm", + "page": "Сенсоры", + "descr": "S8_CO2", + "int": 15, + "round": 1, + "rxPin": 13, + "txPin": 15 }, { "global": 0, - "name": "35. Sht20 Температура", + "name": "37. Sht20 Температура", "type": "Reading", "subtype": "Sht20t", "id": "tmp2", @@ -533,11 +559,11 @@ "descr": "Температура", "int": 15, "round": 1, - "num": 35 + "num": 37 }, { "global": 0, - "name": "36. Sht20 Влажность", + "name": "38. Sht20 Влажность", "type": "Reading", "subtype": "Sht20h", "id": "Hum2", @@ -546,11 +572,11 @@ "descr": "Влажность", "int": 15, "round": 1, - "num": 36 + "num": 38 }, { "global": 0, - "name": "37. Sht30 Температура", + "name": "39. Sht30 Температура", "type": "Reading", "subtype": "Sht30t", "id": "tmp30", @@ -559,11 +585,11 @@ "descr": "SHT30 Температура", "int": 15, "round": 1, - "num": 37 + "num": 39 }, { "global": 0, - "name": "38. Sht30 Влажность", + "name": "40. Sht30 Влажность", "type": "Reading", "subtype": "Sht30h", "id": "Hum30", @@ -572,12 +598,12 @@ "descr": "SHT30 Влажность", "int": 15, "round": 1, - "num": 38 + "num": 40 }, { "global": 0, - "name": "39. HC-SR04 Ультразвуковой дальномер", - "num": 39, + "name": "41. HC-SR04 Ультразвуковой дальномер", + "num": 41, "type": "Reading", "subtype": "Sonar", "id": "sonar", @@ -589,7 +615,7 @@ "int": 5 }, { - "name": "40. UART", + "name": "42. UART", "type": "Reading", "subtype": "UART", "page": "", @@ -601,14 +627,14 @@ "line": 2, "speed": 9600, "eventFormat": 0, - "num": 40 + "num": 42 }, { "header": "Исполнительные устройства" }, { "global": 0, - "name": "41. Кнопка подключенная к пину", + "name": "43. Кнопка подключенная к пину", "type": "Writing", "subtype": "ButtonIn", "id": "btn", @@ -623,11 +649,11 @@ "debounceDelay": 50, "fixState": 0, "inv": 0, - "num": 41 + "num": 43 }, { "global": 0, - "name": "42. Управление пином", + "name": "44. Управление пином", "type": "Writing", "subtype": "ButtonOut", "needSave": 0, @@ -638,11 +664,51 @@ "int": 0, "inv": 0, "pin": 2, - "num": 42 + "num": 44 }, { "global": 0, - "name": "43. Сервопривод", + "name": "45. Пассивный звуковой извещатель", + "type": "Writing", + "subtype": "Buzzer", + "id": "buzzer", + "widget": "toggle", + "page": "Кнопки", + "descr": "Buzzer", + "int": 4000, + "pin": 14, + "freq": 2000, + "duration": 1000, + "beatLevel": 4, + "tempo": 120, + "tempoCorrection": 1, + "pauseBetween": 0, + "transpose": 0, + "cycle": 0, + "indication": 1, + "val": 0, + "num": 45 + }, + { + "global": 0, + "name": "46. Энкодер", + "type": "Writing", + "subtype": "Encoder", + "id": "enc", + "widget": "inputDgt", + "page": "Энкодер", + "descr": "Громкость", + "needSave": 0, + "val": "0", + "round": 0, + "step": 1, + "stepOnPress": 5, + "pins": "4,5,2", + "num": 46 + }, + { + "global": 0, + "name": "47. Сервопривод", "type": "Writing", "subtype": "IoTServo", "id": "servo", @@ -653,11 +719,11 @@ "pin": 12, "apin": -1, "amap": "0, 4096, 0, 180", - "num": 43 + "num": 47 }, { "global": 0, - "name": "44. Расширитель портов Mcp23017", + "name": "48. Расширитель портов Mcp23017", "type": "Reading", "subtype": "Mcp23017", "id": "Mcp", @@ -667,11 +733,11 @@ "int": "0", "addr": "0x20", "index": 1, - "num": 44 + "num": 48 }, { "global": 0, - "name": "45. MP3 плеер", + "name": "49. MP3 плеер", "type": "Reading", "subtype": "Mp3", "id": "mp3", @@ -681,11 +747,11 @@ "int": 1, "pins": "14,12", "volume": 20, - "num": 45 + "num": 49 }, { "global": 0, - "name": "46. Сенсорная кнопка", + "name": "50. Сенсорная кнопка", "type": "Writing", "subtype": "Multitouch", "id": "impulse", @@ -699,11 +765,11 @@ "pinMode": "INPUT", "debounceDelay": 50, "PWMDelay": 500, - "num": 46 + "num": 50 }, { "global": 0, - "name": "47. Расширитель портов Pcf8574", + "name": "51. Расширитель портов Pcf8574", "type": "Reading", "subtype": "Pcf8574", "id": "Pcf", @@ -713,11 +779,11 @@ "int": "0", "addr": "0x20", "index": 1, - "num": 47 + "num": 51 }, { "global": 0, - "name": "48. PWM ESP8266", + "name": "52. PWM ESP8266", "type": "Writing", "subtype": "Pwm8266", "id": "pwm", @@ -729,11 +795,11 @@ "freq": 5000, "val": 0, "apin": -1, - "num": 48 + "num": 52 }, { "global": 0, - "name": "49. Телеграм-Лайт", + "name": "53. Телеграм-Лайт", "type": "Writing", "subtype": "TelegramLT", "id": "tg", @@ -742,14 +808,14 @@ "descr": "", "token": "", "chatID": "", - "num": 49 + "num": 53 }, { "header": "Экраны" }, { "global": 0, - "name": "50. LCD экран 2004", + "name": "54. LCD экран 2004", "type": "Reading", "subtype": "Lcd2004", "id": "Lcd", @@ -761,10 +827,10 @@ "size": "20,4", "coord": "0,0", "id2show": "id датчика", - "num": 50 + "num": 54 }, { - "name": "51. LCD экран 1602", + "name": "55. LCD экран 1602", "type": "Reading", "subtype": "Lcd2004", "id": "Lcd", @@ -776,6 +842,6 @@ "size": "16,2", "coord": "0,0", "id2show": "id датчика", - "num": 51 + "num": 55 } ] \ No newline at end of file diff --git a/data_svelte/myProfile.json b/data_svelte/myProfile.json index 17ee601d..7432922b 100644 --- a/data_svelte/myProfile.json +++ b/data_svelte/myProfile.json @@ -64,6 +64,10 @@ } ], "Сенсоры": [ + { + "path": "src/modules/sensors/A02Distance", + "active": true + }, { "path": "src/modules/sensors/Acs712", "active": true @@ -168,6 +172,10 @@ "path": "src/modules/sensors/RTC", "active": true }, + { + "path": "src/modules/sensors/S8", + "active": true + }, { "path": "src/modules/sensors/Sds011", "active": false @@ -202,6 +210,14 @@ "path": "src/modules/exec/ButtonOut", "active": true }, + { + "path": "src/modules/exec/Buzzer", + "active": true + }, + { + "path": "src/modules/exec/Enconder", + "active": true + }, { "path": "src/modules/exec/EspCam", "active": false diff --git a/myProfile.json b/myProfile.json index 17ee601d..7432922b 100644 --- a/myProfile.json +++ b/myProfile.json @@ -64,6 +64,10 @@ } ], "Сенсоры": [ + { + "path": "src/modules/sensors/A02Distance", + "active": true + }, { "path": "src/modules/sensors/Acs712", "active": true @@ -168,6 +172,10 @@ "path": "src/modules/sensors/RTC", "active": true }, + { + "path": "src/modules/sensors/S8", + "active": true + }, { "path": "src/modules/sensors/Sds011", "active": false @@ -202,6 +210,14 @@ "path": "src/modules/exec/ButtonOut", "active": true }, + { + "path": "src/modules/exec/Buzzer", + "active": true + }, + { + "path": "src/modules/exec/Enconder", + "active": true + }, { "path": "src/modules/exec/EspCam", "active": false diff --git a/platformio.ini b/platformio.ini index 0fce3495..7f1d6593 100644 --- a/platformio.ini +++ b/platformio.ini @@ -375,6 +375,7 @@ lib_deps = robtillaart/SHT2x@^0.1.1 WEMOS SHT3x@1.0.0 plerup/EspSoftwareSerial + gyverlibs/EncButton @ ^2.0 adafruit/Adafruit MCP23017 Arduino Library@^2.1.0 adafruit/Adafruit BusIO @ ^1.13.2 dfrobot/DFRobotDFPlayerMini @ ^1.0.5 @@ -389,6 +390,7 @@ build_src_filter = + + + + + + + + @@ -399,12 +401,15 @@ build_src_filter = + + + + + + + + + + + + + + + + + + diff --git a/src/modules/API.cpp b/src/modules/API.cpp index 12480f10..e4f040c1 100644 --- a/src/modules/API.cpp +++ b/src/modules/API.cpp @@ -7,6 +7,7 @@ void* getAPI_Timer(String subtype, String params); void* getAPI_Variable(String subtype, String params); void* getAPI_VariableColor(String subtype, String params); void* getAPI_VButton(String subtype, String params); +void* getAPI_A02Distance(String subtype, String params); void* getAPI_Acs712(String subtype, String params); void* getAPI_AhtXX(String subtype, String params); void* getAPI_AnalogAdc(String subtype, String params); @@ -17,12 +18,15 @@ void* getAPI_Ds18b20(String subtype, String params); void* getAPI_Impulse(String subtype, String params); void* getAPI_Pzem004(String subtype, String params); void* getAPI_RTC(String subtype, String params); +void* getAPI_S8(String subtype, String params); void* getAPI_Sht20(String subtype, String params); void* getAPI_Sht30(String subtype, String params); void* getAPI_Sonar(String subtype, String params); void* getAPI_UART(String subtype, String params); void* getAPI_ButtonIn(String subtype, String params); void* getAPI_ButtonOut(String subtype, String params); +void* getAPI_Buzzer(String subtype, String params); +void* getAPI_Encoder(String subtype, String params); void* getAPI_IoTServo(String subtype, String params); void* getAPI_Mcp23017(String subtype, String params); void* getAPI_Mp3(String subtype, String params); @@ -41,6 +45,7 @@ if ((tmpAPI = getAPI_Timer(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Variable(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_VariableColor(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_VButton(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_A02Distance(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Acs712(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_AhtXX(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_AnalogAdc(subtype, params)) != nullptr) return tmpAPI; @@ -51,12 +56,15 @@ if ((tmpAPI = getAPI_Ds18b20(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Impulse(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Pzem004(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_RTC(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_S8(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Sht20(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Sht30(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Sonar(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_UART(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_ButtonIn(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_ButtonOut(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Buzzer(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Encoder(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_IoTServo(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Mcp23017(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Mp3(subtype, params)) != nullptr) return tmpAPI; diff --git a/src/modules/exec/Buzzer/Buzzer.cpp b/src/modules/exec/Buzzer/Buzzer.cpp new file mode 100644 index 00000000..5668b549 --- /dev/null +++ b/src/modules/exec/Buzzer/Buzzer.cpp @@ -0,0 +1,382 @@ +#include "Global.h" +#include "classes/IoTItem.h" + + +extern IoTGpio IoTgpio; + +class Buzzer : public IoTItem +{ +private: + int _pin; + int _freq; + int _duration; + int _beatLevel = 4; + int _originalTempo = 120; // bpm + float _tempoCorrection = 1; // less than 1 - is slower + float _pauseBetween = 0; + int _transpose = 0; + int _cycle = 0; + int _indication = 1; + + std::vector tonesList; // playMode 3 + std::vector melodyList; // playMode 4 + + int playMode = 0; + + bool firstTone = true; + int thisTone = 0; + int startPlayPrevTone = 0; + int pauseBetweenTones = 0; + int toneFrequency = 0; + int toneDuration = 0; + + bool firstNote = true; + int thisNote = 0; + bool pause = false; + int A4 = 440; // Ля 4-ой октавы + int freqToPlay = 440; + int prevFreqToPlay = 440; + float melodyFloat = 1; + int startPlayPrevNote = 0; + int pauseBetweenNotes = 0; + float intervalC0 = 69; // + float prevIntervalC0 = 69; // + + float natureInt[13] = {1, 1.0416666666667, 1.125, 1.2, 1.25, 1.3333333333, 1.3888888889, 1.5, 1.6, 1.6666666667, 1.8, 1.875, 2}; // New Nature + String notes[12] = {"C", "CS", "D", "DS", "E", "F", "FS", "G", "GS", "A", "AS", "B"}; + float minorSecond = 1.0416666666667; + float risingMinorSecond = 1.066667; + float majorSecond = 1.125; + float decreasingMajorSecond = 1.1111111; + +public: + Buzzer(String parameters) : IoTItem(parameters) + { + _interval = _interval / 1000; // корректируем величину интервала int, теперь он в миллисекундах + + jsonRead(parameters, "pin", _pin); + jsonRead(parameters, "freq", _freq); + jsonRead(parameters, "duration", _duration); + jsonRead(parameters, "beatLevel", _beatLevel); + jsonRead(parameters, "tempo", _originalTempo); + jsonRead(parameters, "tempoCorrection", _tempoCorrection); + jsonRead(parameters, "pauseBetween", _pauseBetween); + jsonRead(parameters, "transpose", _transpose); + jsonRead(parameters, "cycle", _cycle); + jsonRead(parameters, "indication", _indication); + + IoTgpio.pinMode(_pin, OUTPUT); + } + + void loop() + { + + switch (playMode) + { + case 0: // for stop + // noTone(_pin); + break; + + case 1: + // for doByIntervals + if (enableDoByInt) + { + currentMillis = millis(); + difference = currentMillis - prevMillis; + if (difference >= _interval) + { + prevMillis = millis(); + this->doByInterval(); + } + } + break; + + case 2: + // for tone + break; + case 3: + // for tones() ................................... + if (((millis() - startPlayPrevTone) > pauseBetweenTones)) + { + if (firstTone) + { + firstTone = false; + if (_indication) + { + value.valD = 1; + regEvent((String)(int)value.valD, "Buzzer", false, false); + } + } + else + { + thisTone = thisTone + 2; + } + + if (thisTone >= tonesList.size()) // если сиграли последнюю ноту + { + if (_cycle) + { + thisTone = 0; + } + else + { + playMode = 0; + if (_indication) + { + value.valD = 0; + regEvent((String)(int)value.valD, "Buzzer", false, false); + } + break; + } + } + + toneFrequency = tonesList[thisTone]; + toneDuration = tonesList[thisTone + 1]; + // noTone(_pin); // останавливаем, на всякий случай воспроизведение предыдущей ноты + tone(_pin, toneFrequency, toneDuration); + startPlayPrevTone = millis(); + pauseBetweenTones = toneDuration * (1 + _pauseBetween); + } + break; + + case 4: + // FOR melody ............................................ + if (((millis() - startPlayPrevNote) > pauseBetweenNotes)) + { + if (firstNote) + { + if (_indication) + { + value.valD = 1; + regEvent((String)(int)value.valD, "Buzzer", false, false); + } + } + else + { + thisNote++; + } + + if (thisNote >= melodyList.size()) // если сыграли последнюю ноту + { + if (_cycle) + { + thisNote = 0; + } + else + { + playMode = 0; + if (_indication) + { + value.valD = 0; + regEvent((String)(int)value.valD, "Buzzer", false, false); + } + break; + } + } + String melodyString = melodyList[thisNote]; + String fore, aft; + for (int i = 0; i < melodyString.length(); i++) + { + if (melodyString.charAt(i) == '.') + { + fore = melodyString.substring(0, i); // получили строку до точки + aft = melodyString.substring(i + 1); // получили строку после точки + break; + } + } + char last = fore.charAt(fore.length() - 1); // получили номер октавы + int octaveN = (int)(last - '0'); + String note = fore.substring(0, fore.length() - 1); // получили ноту + int noteindex; + pause = true; + for (int j = 0; j < 12; j++) + { + if (note == notes[j]) // если находим ноту, значит не пауза + { + noteindex = j; + pause = false; + break; + } + } + float noteDurationFloat = aft.toFloat(); // в миллидолях такта + int noteDuration = int(noteDurationFloat / (float(_originalTempo) / (_beatLevel * 60)) / _tempoCorrection); // в миллисекундах + if (!pause) // находим абсолютный интервал у ноты, паузу пропускаем + { + // номер октавы на нот в октаве номер ноты в октаве в целой части и длительность в дробной + intervalC0 = (octaveN + 1) * 12 + noteindex + _transpose; + pause = false; + int relIntervalC0 = int(intervalC0) - int(prevIntervalC0); // находим интервал от предыдущей ноты + float intervalA4 = 69 - int(intervalC0); + int monoFreqToPlay = A4 / pow(2.0, (intervalA4 / 12)); // расчет частоты по монохроматической гамме + if (firstNote) // для первой ноты не делаем перерасчет, играем как есть + { + freqToPlay = monoFreqToPlay; + } + else + { + if (relIntervalC0 == 0) // играем туже ноту + { + freqToPlay = prevFreqToPlay; + } + // далее расчет частоты новой ноты в природном интервале от предыдущей + if (relIntervalC0 > 0) + { + freqToPlay = prevFreqToPlay * (int(abs(relIntervalC0 / 12)) + natureInt[abs(relIntervalC0 - int(relIntervalC0 / 12) * 12)]); + } + if (relIntervalC0 < 0) + { + freqToPlay = prevFreqToPlay / (int(abs(relIntervalC0 / 12)) + natureInt[abs(relIntervalC0 - int(relIntervalC0 / 12) * 12)]); + } + // это приводит к рассогласованию нот и убеганию в конце произведения + if (freqToPlay < monoFreqToPlay) // делаем корректировку убегания с помощью выбора малых или больших секунд + { + natureInt[1] = risingMinorSecond; + natureInt[2] = majorSecond; + } + else + { + natureInt[2] = decreasingMajorSecond; + natureInt[1] = minorSecond; + } + } + } + else // если пауза + { + intervalC0 = prevIntervalC0; + freqToPlay = 0; + pause = false; + } + // noTone(_pin); // останавливаем, на всякий случай воспроизведение предыдущей ноты + if (freqToPlay < 31) + freqToPlay = 0; + // воспроизведём ноту + tone(_pin, freqToPlay, noteDuration); + startPlayPrevNote = millis(); + if (freqToPlay) // нулевые значения частоты (паузы) не сохраняем + { + prevFreqToPlay = freqToPlay; // if it was not 0 + } + prevIntervalC0 = intervalC0; + /* + Чтобы отделить ноты друг от друга, добавим небольшую паузу между ними + около 0.3 от длины ноты звучат неплохо + */ + pauseBetweenNotes = noteDuration * (1 + _pauseBetween); + if (firstNote) + firstNote = false; + } + break; + + default: + break; + } + } + + void doByInterval() + { + tone(_pin, _freq, _duration); + // regEvent(value.valD, "Buzzer"); + } + + IoTValue execute(String command, std::vector ¶m) + { + // param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22 + if (command == "tone") + { + playMode = 2; + tone(_pin, param[0].valD, param[1].valD); + SerialPrint("I", "Sensor Buzzer, tone(), playMode = ", String(playMode), _id); + } + else if (command == "tones") + { + int sizeOfParam = param.size(); + tonesList.clear(); + tonesList.reserve(sizeOfParam); + for (unsigned int i = 0; i < sizeOfParam; i++) + { + tonesList.push_back(param[i].valD); + } + playMode = 3; + SerialPrint("I", "Sensor Buzzer, tones(), playMode = ", String(playMode), _id); + startPlayPrevTone = 0; + pauseBetweenTones = 0; + firstTone = true; + thisTone = 0; + prevFreqToPlay = 440; + prevIntervalC0 = 69; + } + else if (command == "notone") + { + playMode = 0; + noTone(_pin); + if (_indication) + { + value.valD = 0; + regEvent((String)(int)value.valD, "Buzzer", false, false); + } + SerialPrint("I", "Sensor Buzzer, notone(), playMode = ", String(playMode), _id); + } + else if (command == "melodySetting") + { + if (param[0].isDecimal) + _beatLevel = param[0].valD; + if (param[1].isDecimal) + _originalTempo = param[1].valD; + if (param[2].isDecimal) + _tempoCorrection = param[2].valD; + if (param[3].isDecimal) + _pauseBetween = param[3].valD; + if (param[4].isDecimal) + _transpose = param[4].valD; + if (param[5].isDecimal) + _cycle = param[5].valD; + String input = "beatLevel = " + String(_beatLevel) + " originalTempo = " + String(_originalTempo) + " tempoCorrection = " + String(_tempoCorrection) + " pauseBetween = " + String(_pauseBetween) + " transpose = " + String(_transpose) + " cycle = " + String(_cycle); + SerialPrint("I", "Sensor Buzzer, melodySetting() exec", input, _id); + } + else if (command == "melody") + { + int sizeOfParam = param.size(); + melodyList.clear(); + melodyList.reserve(sizeOfParam); + for (unsigned int i = 0; i < sizeOfParam; i++) + { + melodyList.push_back(param[i].valS); + } + playMode = 4; + SerialPrint("I", "Sensor Buzzer, melody(), playMode = ", String(playMode), _id); + thisNote = 0; + firstNote = true; + startPlayPrevNote = 0; + pauseBetweenNotes = 0; + prevFreqToPlay = 440; + prevIntervalC0 = 69; + } + return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки + } + + void setValue(const IoTValue &Value, bool genEvent = true) + { + value = Value; + playMode = value.valD; + regEvent((String)(int)value.valD, "Buzzer", false, genEvent); + } + //======================================================================================================= + String getValue() + { + return (String)(int)value.valD; + } + + ~Buzzer(){}; +}; + +void *getAPI_Buzzer(String subtype, String param) +{ + if (subtype == F("Buzzer")) + { + return new Buzzer(param); + } + else + { + return nullptr; + } +} diff --git a/src/modules/exec/Buzzer/export.json b/src/modules/exec/Buzzer/export.json new file mode 100644 index 00000000..cfebf462 --- /dev/null +++ b/src/modules/exec/Buzzer/export.json @@ -0,0 +1,268 @@ +{ + "mark": "iotm", + "config": [ + { + "global": 0, + "type": "Writing", + "subtype": "Buzzer", + "id": "buzzer", + "widget": "toggle", + "page": "Кнопки", + "descr": "00.Buzzer", + "int": 4000, + "pin": 14, + "freq": 2000, + "duration": 1000, + "beatLevel": 4, + "tempo": "200", + "tempoCorrection": 1, + "pauseBetween": "0.1", + "transpose": 0, + "cycle": "1", + "indication": "1", + "val": 0 + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn1", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "01.Вкл. основаной сингал", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn2", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "02.Выкл. основаной сингал", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn3", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "03.Судовой свисток", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn4", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "04.European police", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn5", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "05.American police", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn6", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "06.Pirates of Caribbeans", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn7", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "07.Tigran Aivazian Opus71", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn8", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "08.Imperial March", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn9", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "09.Happy Birthday ", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn10", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "10.noTone Стоп", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn11", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "11.Settings Темп 200bpm", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn12", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "12.Settings Темп 100bpm", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn13", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "13.Setting Повтор (cycle)", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn14", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "14.Setting Пауза между нот", + "int": "0", + "val": "0" + }, + { + "global": 0, + "type": "Reading", + "subtype": "VButton", + "id": "vbtn15", + "needSave": 0, + "widget": "toggle", + "page": "Кнопки", + "descr": "15.Settings Default", + "int": "0", + "val": "0" + } + ] +} + +scenario=> +#включаем основаной одиночный сингал из настроек +if vbtn1 == 1 then {buzzer = 1 ;vbtn1 = 0;} + +#выключаем основаной одиночный сингал из настроек +if vbtn2 == 1 then {buzzer = 0 ;vbtn2 = 0;} + +#включаем одиночный сигнал ship's whistle +if vbtn3 == 1 then {buzzer.tone(200,3000); vbtn3 = 0;} + +# european police +if vbtn4 == 1 then {buzzer.tones(450,500, 600,500); vbtn4 = 0;} + +#american police +if vbtn5 == 1 then {buzzer.tones(600, 25, 606, 25, 613, 25, 620, 25, 626, 25, 633, 25, 640, 25, 647, 25, 654, 25, 662, 25, 669, 25, 676, 25, 684, 25, 691, 25, 699, 25, 706, 25, 714, 25, 722, 25, 730, 25, 738, 25, 746, 25, 754, 25, 763, 25, 771, 25, 780, 25, 788, 25, 797, 25, 806, 25, 815, 25, 824, 25, 833, 25, 842, 25, 851, 25, 860, 25, 870, 25, 879, 25, 889, 25, 899, 25, 909, 25, 919, 25, 929, 25, 939, 25, 949, 25, 960, 25, 970, 25, 981, 25, 992, 25, 1003, 25, 1014, 25, 1025, 25, 1036, 25, 1047, 25, 1058, 25, 1069, 25, 1080, 25, 1091, 25, 1103, 25, 1115, 25, 1127, 25, 1139, 25, 1151, 25, 1163, 25, 1175, 25, 1187, 25, 1200, 25, 1187, 25, 1174, 25, 1161, 25, 1148, 25, 1136, 25, 1123, 25, 1111, 25, 1099, 25, 1087, 25, 1075, 25, 1063, 25, 1052, 25, 1040, 25, 1029, 25, 1018, 25, 1007, 25, 996, 25, 985, 25, 974, 25, 964, 25, 953, 25, 943, 25, 933, 25, 922, 25, 912, 25, 902, 25, 893, 25, 883, 25, 873, 25, 864, 25, 854, 25, 845, 25, 836, 25, 827, 25, 818, 25, 809, 25, 800, 25, 791, 25, 783, 25, 774, 25, 766, 25, 757, 25, 749, 25, 741, 25, 733, 25, 725, 25, 717, 25, 709, 25, 702, 25, 694, 25, 686, 25, 679, 25, 672, 25, 664, 25, 657, 25, 650, 25, 643, 25, 636, 25, 629, 25, 622, 25, 615, 25, 609, 25, 602, 25);vbtn5=0} + + + + +#if vbtn7 == 0 then buzzer.notone() + +#включаем проигрывание мелодии Pirates of Caribbeans +if vbtn6 == 1 then {buzzer.melody("E4.125", "G4.125", "A4.250", "A4.125", "0.125", "A4.125", "B4.125", "C5.250", "C5.125", "0.125", "C5.125", "D5.125", "B4.250", "B4.125", "0.125", "A4.125", "G4.125", "A4.375", "0.125", "E4.125", "G4.125", "A4.250", "A4.125", "0.125", "A4.125", "B4.125", "C5.250", "C5.125", "0.125", "C5.125", "D5.125", "B4.250", "B4.125", "0.125", "A4.125", "G4.125", "A4.375", "0.125", "E4.125", "G4.125", "A4.250", "A4.125", "0.125", "A4.125", "C5.125", "D5.250", "D5.125", "0.125", "D5.125", "E5.125", "F5.250", "F5.125", "0.125", "E5.125", "D5.125", "E5.125", "A4.250", "0.125", "A4.125", "B4.125", "C5.250", "C5.125", "0.125", "D5.250", "E5.125", "A4.250", "0.125", "A4.125", "C5.125", "B4.250", "B4.125", "0.125", "C5.125", "A4.125", "B4.375", "0.375", "A4.250", "A4.125", "A4.125", "B4.125", "C5.250", "C5.125", "0.125", "C5.125", "D5.125", "B4.250", "B4.125", "0.125", "A4.125", "G4.125", "A4.375", "0.125", "E4.125", "G4.125", "A4.250", "A4.125", "0.125", "A4.125", "B4.125", "C5.250", "C5.125", "0.125", "C5.125", "D5.125", "B4.250", "B4.125", "0.125", "A4.125", "G4.125", "A4.375", "0.125", "E4.125", "G4.125", "A4.250", "A4.125", "0.125", "A4.125", "C5.125", "D5.250", "D5.125", "0.125", "D5.125", "E5.125", "F5.250", "F5.125", "0.125", "E5.125", "D5.125", "E5.125", "A4.250", "0.125", "A4.125", "B4.125", "C5.250", "C5.125", "0.125", "D5.250", "E5.125", "A4.250", "0.125", "A4.125", "C5.125", "B4.250", "B4.125", "0.125", "C5.125", "A4.125", "B4.375", "0.375", "E5.250", "0.125", "0.375", "F5.250", "0.125", "0.375", "E5.125", "E5.125", "0.125", "G5.125", "0.125", "E5.125", "D5.125", "0.125", "0.375", "D5.250", "0.125", "0.375", "C5.250", "0.125", "0.375", "B4.125", "C5.125", "0.125", "B4.125", "0.125", "A4.500", "E5.250", "0.125", "0.375", "F5.250", "0.125", "0.375", "E5.125", "E5.125", "0.125", "G5.125", "0.125", "E5.125", "D5.125", "0.125", "0.375", "D5.250", "0.125", "0.375", "C5.250", "0.125", "0.375", "B4.125", "C5.125", "0.125", "B4.125", "0.125", "A4.500"); vbtn6 = 0} + +# Tigran Aivazian Opus71-Melody +if vbtn7 == 1 then {buzzer.melody("P.999", "C4.250", "E4.250", "E4.250", "G4.250", "G4.250", "B4.250", "B4.250", "G4.250", "A4.250", "A4.125", "E4.125", "C4.250", "E4.250", "F4.250", "F4.125", "C4.125", "A3.250", "A3.250", "D4.250", "D4.125", "E4.125", "F4.250", "A4.250", "B4.250", "D5.125", "B4.125", "G4.250", "G4.250", "A4.125", "A4.125", "E4.125", "E4.125", "A4.500", "E4.125", "E4.125", "G4.125", "G4.125", "C4.500", "E4.250", "E4.125", "F4.125", "G4.250", "B4.250", "A4.250", "A4.125", "C5.125", "C5.250", "F4.250", "G4.250", "G4.125", "D4.125", "D4.250", "F4.250", "F4.250", "F4.125", "C4.125", "A3.250", "A3.250", "C4.250", "C4.125", "F4.125", "F4.250", "A4.250", "B4.250", "D5.125", "B4.125", "G4.250", "G4.250", "G4.125", "G4.125", "B4.125", "D4.125", "G4.500", "E4.250", "P.749", "P.250", "G4.125", "P.250", "E4.125", "P.500", "C4.500");vbtn7 = 0 } + +# Imperial Marsh +if vbtn8 == 1 then {buzzer.melody("E3.500", "E3.500", "E3.500", "CS3.250", "CS3.250", "E3.500", "E3.500", "E3.500", "CS3.250", "CS3.250", "E4.500", "E4.500", "E4.500", "C4.375", "G4.125", "E4.500", "C4.375", "G4.125", "E4.999", "B4.500", "B4.500", "B4.500", "CS5.375", "G4.125", "DS4.500", "C4.375", "G4.125", "F4.999", "E5.500", "E4.375", "E4.125", "E5.500", "DS5.375", "D5.125", "CS5.500", "F4.500", "AS4.500", "A4.375", "GS4.125", "G4.500", "C4.500", "DS4.500", "C4.375", "E4.125", "G4.500", "F4.375", "G4.125", "B4.999", "E5.500", "E4.375", "E4.125", "E5.500", "DS5.375", "D5.125", "CS5.500", "D4.500", "AS4.500", "A4.375", "GS4.125", "G4.500", "C4.500", "DS4.500", "C4.375", "G4.125", "F4.500", "C4.375", "G4.125", "E4.999", "E4.500", "E4.250");vbtn8 = 0 } + +# Happy Birthday +if vbtn9 == 1 then {buzzer.melody("C4.250", "C4.125", "D4.250", "C4.250", "F4.250", "E4.500", "C4.250", "C4.125", "D4.250", "C4.250", "G4.250", "F4.500", "C4.250", "C4.125", "C5.250", "A4.250", "F4.250", "E4.250", "D4.250", "AS4.250", "AS4.125", "A4.250", "F4.250", "G4.250", "F4.500", "P.500");vbtn9 = 0 } + +#stop +if vbtn10 == 1 then {buzzer.notone() ;vbtn10 = 0} + +# меняем настройки мелодии +if vbtn11 == 1 then {buzzer.melodySetting("beatLevel",200,"tempoCorr","pauseBetween","transpose","cycle"); +vbtn11=0} + +# меняем настройки мелодии +if vbtn12 == 1 then {buzzer.melodySetting("beatLevel",100,"tempoCorr","pauseBetween","transpose","cycle"); vbtn12 = 0} + +# меняем настройки мелодии +if vbtn13 == 1 then buzzer.melodySetting("beatLevel","tempo","tempoCorr","pauseBetween","transpose",1) + +# меняем настройки мелодии +if vbtn13 == 0 then buzzer.melodySetting("beatLevel","tempo","tempoCorr","pauseBetween","transpose",0) + +# меняем настройки мелодии +if vbtn14 == 1 then buzzer.melodySetting("beatLevel","tempo","tempoCorr",0.3,"transpose","cycle") + +# меняем настройки мелодии +if vbtn14 == 0 then buzzer.melodySetting("beatLevel","tempo","tempoCorr",0,"transpose","cycle") + + +# меняем настройки мелодии на базовые +if vbtn15 == 1 then {buzzer.melodySetting(4,120,1,0,1,0);vbtn15=0} + +# меняем настройки мелодии - шаблон +#if vbtn99 == 1 then buzzer.melodySetting("beatLevel","tempo","tempoCorr","pauseBetween","transpose","cycle") diff --git a/src/modules/exec/Buzzer/modinfo.json b/src/modules/exec/Buzzer/modinfo.json new file mode 100644 index 00000000..35f193a2 --- /dev/null +++ b/src/modules/exec/Buzzer/modinfo.json @@ -0,0 +1,96 @@ +{ + "menuSection": "Исполнительные устройства", + + "configItem": [{ + "global": 0, + "name": "Пассивный звуковой извещатель", + "type": "Writing", + "subtype": "Buzzer", + "id": "buzzer", + "widget": "toggle", + "page": "Кнопки", + "descr": "Buzzer", + "int": 4000, + "pin": 14, + "freq": 2000, + "duration": 1000, + "beatLevel": 4, + "tempo": 120, + "tempoCorrection": 1, + "pauseBetween": 0, + "transpose": 0, + "cycle": 0, + "indication": 1, + "val": 0 + }], + + "about": { + "authorName": "Alex K", + "authorContact": "https://t.me/cmche", + "authorGit": "https://github.com/CHE77/Buzzer_IotManager", + "exampleURL": "https://iotmanager.org/wiki", + "specialThanks": "@Biveraxe", + "moduleName": "Buzzer", + "moduleVersion": "1.0", + "usedRam": { + "esp32_4mb": 15, + "esp8266_4mb": 15 + }, + "title": "Пассивный звуковой извещатель", + "moduleDesc": "Генерирует одиночные ШИМ сигналы или их серию, нужной частоты и длительности или даже мелодию, до 256 нот. Мелодия проигрывается на основе природного звукоряда. Для Пьезо Извещателей High Level Trigger.", + "retInfo": "Статус элемента, извещателя: 0 - Выключен, 1 - Активирован на повторение сигнала в настроиках или проигрывается мелодия/серия сигналов", + "propInfo": { + "int": "Количество миллисекунд между повторами одиночного сигнала", + "pin": "Управляемый пин", + "freq": "Частота сигнала, Hz", + "duration": "Длительность сигнала, ms", + "beatLevel": "Долей в такте", + "tempo": "Оригинальный темп мелодии, bpm", + "tempoCorrection": "Коррекция темпа мелодии", + "pauseBetween": "Дополнительная пауза между нот, в долях от длительности ноты", + "transpose": "Транспонирование на количество полутонов. +/-12 - для повышения/понижения на октаву", + "cycle": "Повтор мелодии/серии сигналов", + "indication": "Индикация в виджет, что идет сигнал, играет мелодия", + "val": "Включение/Выключение повторяющегося сигнала указанного в настройках: int, freq, duration. Работает как через интерфейс, так и через сценарий" + }, + "funcInfo": [ + { + "name": "tone", + "descr": "Проигрывание одиночного сигнала (без индикации)", + "params": ["Частота", "Длительность (ms)"] + }, + { + "name": "tones", + "descr": "Проигрывание серии сигналов, до 128", + "params": ["Частота 1-го сигнала", "Длительность 1-го сигнала (ms)","Частота 2-го сигала", "Длительность 2-го сигнала", "....итд"] + }, + { + "name": "melody", + "descr": "Проигрывание мелодии, до 256 нот. Кодировка 'YYX.ZZZ'. Научная нотация: YY - обозначение ноты (C,CS,D,DS,E,F,FS,G,GS,A,AS,B), X - номер октавы (0-9), ZZZ - длительность в тысячных долях такта (0-999). Обязательно в двойных кавычках. 'AS4.50' - Ля# 4-й октавы, 1/2 такта. На Github лежит Excel файл для перекодировки.", + "params": ["Код 1-ой ноты","Код 2-й ноты"," и тд"] + }, + { + "name": "notone", + "descr": "Остановка звучания сигнала/ноты/мелодии", + "params": [] + }, + { + "name": "melodySetting", + "descr": "Перенастройка параметров мелодии: Долей в такте - (обычно 4), Оригинальный темп -(40-208 bpm), Коррекция темпа - в k раз быстрее/медленнее, Пауза между нот (стакато) - доля от длительности, Коррекция тональности (транспонирование) - в k раз выше/ниже, Повтор 1/0. Чтобы не изменялось значение вбить любой текст в ковычках ", + "params": ["Долей в такте", "Оригинальный темп", "Коррекция темпа", "Пауза между нот", "Коррекция тональности", "Повтор мелодии/серии сигналов"] + } + + ] + }, + + "defActive": true, + + "usedLibs": { + "esp32_4mb": [], + "esp8266_4mb": [], + "esp8266_1mb": [], + "esp8266_1mb_ota": [], + "esp8285_1mb": [], + "esp8285_1mb_ota": [] + } +}