diff --git a/.gitignore b/.gitignore index 65469d13..65bd8853 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch -lib/libraies-master - +data_svelte/settings.json diff --git a/PrepareProject.py b/PrepareProject.py new file mode 100644 index 00000000..bc120001 --- /dev/null +++ b/PrepareProject.py @@ -0,0 +1,179 @@ +# PrepareProject.py - инструмент для подготовки проекта к компиляции. +# Необходимо вызвать при изменении персональных настроек или состава модулей. +# +# При отсутствии файла с персональными настройками, myProfile.json будет создан автоматически +# python PrepareProject.py +# +# Если myProfile.json уже существует, можно запустить PrepareProject.py с параметром -u или --update для обновления списка модулей. +# Данная функция будет полезна для разработчиков при добавлении модуля в папку src/modules +# python PrepareProject.py --update +# python PrepareProject.py -u +# +# Возможно использовать несколько вариантов персональных настроек и уточнять имя файла при запуске с использованием параметра -p или -profile +# python PrepareProject.py --profile <ИмяФайла> +# python PrepareProject.py -p <ИмяФайла> +# +# + +import configparser +import os, json, sys, getopt +from pathlib import Path + + +config = configparser.ConfigParser() # создаём объекта парсера INI + +def printHelp(): + print('''Usage: + PrepareProject.py + -p --profile + -u --update + -h --help''') + + +def updateModulesInProfile(profJson): + profJson["modules"] = {} + for root,d_names,f_names in os.walk("src\\modules"): + for fname in f_names: + if fname == "modinfo.json": + with open(root + "\\" + fname, "r", encoding='utf-8') as read_file: + modinfoJson = json.load(read_file) + # проверяем есть ли уже узловой элемент и если нет, то создаем + if not modinfoJson['menuSection'] in profJson["modules"]: + profJson["modules"][modinfoJson['menuSection']] = [] + # добавляем информацию о модуле в узловой элемент + profJson["modules"][modinfoJson['menuSection']].append({ + 'path': root, + 'active': modinfoJson['defActive'] + }) + + + + + +update = False # признак необходимости обновить список модулей +profile = 'myProfile.json' # имя профиля. Будет заменено из консоли, если указано при старте + +argv = sys.argv[1:] +try: + opts, args = getopt.getopt(argv, 'hp:u', ['help', 'profile=', 'update']) +except getopt.GetoptError: + print('Ошибка обработки параметров!') + printHelp() + sys.exit(2) + +for opt, arg in opts: + if opt in ("-h", "--help"): + printHelp() + sys.exit() + elif opt in ("-p", "--profile"): + profile = arg + elif opt in ("-u", "--update"): + update = True + + +if Path(profile).is_file(): + # подтягиваем уже существующий профиль + with open(profile, "r", encoding='utf-8') as read_file: + profJson = json.load(read_file) + # если хотим обновить список модулей в существующем профиле + if update: + updateModulesInProfile(profJson) + with open(profile, "w", encoding='utf-8') as write_file: + json.dump(profJson, write_file, ensure_ascii=False, indent=4, sort_keys=False) +else: + # если файла нет - создаем по образу настроек из проекта + profJson = json.loads('{}') + # копируем параметры IOTM из settings.json в новый профиль + with open("data_svelte/settings.json", "r", encoding='utf-8') as read_file: + profJson['iotmSettings'] = json.load(read_file) + # устанавливаем параметры сборки + profJson['projectProp'] = { + 'platformio': { + 'default_envs': 'esp8266_4mb', + 'data_dir': 'data_svelte' + } + } + # загружаем список модулей для сборки + updateModulesInProfile(profJson) + # сохраняем новый профиль + with open(profile, "w", encoding='utf-8') as write_file: + json.dump(profJson, write_file, ensure_ascii=False, indent=4, sort_keys=False) + + +# генерируем файлы проекта на основе подготовленного профиля +# заполняем конфигурационный файл прошивки параметрами из профиля +with open("data_svelte/settings.json", "r", encoding='utf-8') as read_file: + iotmJson = json.load(read_file) +for key, value in profJson['iotmSettings'].items(): + iotmJson[key] = value +with open("data_svelte/settings.json", "w", encoding='utf-8') as write_file: + json.dump(iotmJson, write_file, ensure_ascii=False, indent=4, sort_keys=False) + +# определяем какое устройство используется в профиле +deviceName = profJson['projectProp']['platformio']['default_envs'] + +# собираем меню прошивки из модулей +# параллельно формируем список имен активных модулей +# параллельно собираем необходимые активным модулям библиотеки для включения в компиляцию для текущего типа устройства (esp8266_4m, esp32_4mb) +activeModulesName = [] # список имен активных модулей +allLibs = "" # подборка всех библиотек необходимых модулям для дальнейшей записи в конфигурацию platformio +itemsCount = 1; +includeDirs = "" # подборка путей ко всем модулям для дальнейшей записи в конфигурацию platformio +itemsJson = json.loads('[{"name": "Выберите элемент", "num": 0}]') +for section, modules in profJson['modules'].items(): + itemsJson.append({"header": section}) + for module in modules: + if module['active']: + with open(module['path'] + "\\modinfo.json", "r", encoding='utf-8') as read_file: + moduleJson = json.load(read_file) + if deviceName in moduleJson['devices']: # проверяем поддерживает ли модуль текущее устройство + activeModulesName.append(moduleJson['about']['moduleName']) # запоминаем имена для использования на след шагах + includeDirs = includeDirs + "\n+<" + module['path'].replace("src\\", "") + ">" # запоминаем пути к модулям для компиляции + for libPath in moduleJson['devices'][deviceName]: # запоминаем библиотеки необходимые модулю для текущей платы + allLibs = allLibs + "\n" + libPath + for configItemsJson in moduleJson['configItem']: + configItemsJson['num'] = itemsCount + configItemsJson['name'] = str(itemsCount) + ". " + configItemsJson['name'] + itemsCount = itemsCount + 1 + itemsJson.append(configItemsJson) +with open("data_svelte/items.json", "w", encoding='utf-8') as write_file: + json.dump(itemsJson, write_file, ensure_ascii=False, indent=4, sort_keys=False) + + +# учитываем вызовы модулей в API.cpp +allAPI_head = "" +allAPI_exec = "" +for activModuleName in activeModulesName: + allAPI_head = allAPI_head + "\nvoid* getAPI_" + activModuleName + "(String subtype, String params);" + allAPI_exec = allAPI_exec + "\nif ((tmpAPI = getAPI_" + activModuleName + "(subtype, params)) != nullptr) return tmpAPI;" +apicpp = '#include "ESPConfiguration.h"\n' +apicpp = apicpp + allAPI_head +apicpp = apicpp + '\n\nvoid* getAPI(String subtype, String params) {\nvoid* tmpAPI;' +apicpp = apicpp + allAPI_exec +apicpp = apicpp + '\nreturn nullptr;\n}' +with open('src/modules/API.cpp', 'w') as f: + f.write(apicpp) + +# корректируем параметры platformio +# собираем пути всех отключенных модулей для исключения их из процесса компиляции +# excludeDirs = "" +# for root,d_names,f_names in os.walk("src\\modules"): +# for fname in f_names: +# if fname == "modinfo.json": +# with open(root + "\\" + fname, "r", encoding='utf-8') as read_file: +# modinfoJson = json.load(read_file) +# if not modinfoJson['about']['moduleName'] in activeModulesName: +# excludeDirs = excludeDirs + "\n-<" + root.replace("src\\", "") + ">" + +# фиксируем изменения в platformio.ini +config.clear() +config.read("platformio.ini") +config["env:" + deviceName + "_fromitems"]["lib_deps"] = allLibs +config["env:" + deviceName + "_fromitems"]["build_src_filter"] = includeDirs +config["platformio"]["default_envs"] = deviceName +config["platformio"]["data_dir"] = profJson['projectProp']['platformio']['data_dir'] +with open("platformio.ini", 'w') as configFile: + config.write(configFile) + + + \ No newline at end of file diff --git a/accembleItems.py b/accembleItems.py deleted file mode 100644 index fae42c91..00000000 --- a/accembleItems.py +++ /dev/null @@ -1,100 +0,0 @@ -import configparser -import os -import json, pprint - -config = configparser.ConfigParser() # создаём объекта парсера INI -allLibs_esp8266_4mb = "" -allLibs_esp32_4mb = "" - -allMenuItems = json.loads('[]') -allMenuItemsCount = 1 - -allAPI_head = "" -allAPI_exec = "" - - -def getDirs(path): - for file in os.listdir(path): - if os.path.isdir(os.path.join(path, file)): - yield file - - -def getPIOLibs(patch): - global allLibs_esp8266_4mb, allLibs_esp32_4mb - for dir in getDirs(patch): - if (config.read(patch + dir + "/platformio.ini")): - print(patch + dir + "/platformio.ini") - allLibs_esp8266_4mb = allLibs_esp8266_4mb + config["env:esp8266_4mb"]["lib_deps"] - allLibs_esp32_4mb = allLibs_esp32_4mb + config["env:esp32_4mb"]["lib_deps"] - - -def getMenuItems(patch): - global allMenuItems, allMenuItemsCount - with open(patch + "items.json", "r") as read_file: - allMenuItems = allMenuItems + json.load(read_file) - - for dir in getDirs(patch): - with open(patch + dir + "/items.json", "r") as read_file: - print(patch + dir + "/items.json") - data = json.load(read_file) - for item in data: - item["name"] = str(allMenuItemsCount) + ". " + item["name"] - item["num"] = allMenuItemsCount - allMenuItemsCount = allMenuItemsCount + 1 - allMenuItems = allMenuItems + data - - -def getAPI(patch): - global allAPI_head, allAPI_exec - for dir in getDirs(patch): - print(patch + dir) - allAPI_head = allAPI_head + "\nvoid* getAPI_" + dir + "(String subtype, String params);" - allAPI_exec = allAPI_exec + "\nif ((tmpAPI = getAPI_" + dir + "(subtype, params)) != nullptr) return tmpAPI;" - - - -# читаем и запоминаем все либы мз каждого модуля -getPIOLibs("src/modules/system/") -getPIOLibs("src/modules/exec/") -getPIOLibs("src/modules/sensors/") -getPIOLibs("src/modules/lcd/") - - -# сохраняем собранные либы в настройках PIO -config.read("platformio.ini") -config["env:esp8266_4mb_fromitems"]["lib_deps"] = allLibs_esp8266_4mb -config["env:esp32_4mb_fromitems"]["lib_deps"] = allLibs_esp32_4mb -with open("platformio.ini", 'w') as configfile: - config.write(configfile) - - - -# готовим первый элемент меню -with open("src/modules/items.json", "r") as read_file: - allMenuItems = allMenuItems + json.load(read_file) - -# читаем и запоминаем пункты меню модуелей -getMenuItems("src/modules/system/") -getMenuItems("src/modules/exec/") -getMenuItems("src/modules/sensors/") -getMenuItems("src/modules/lcd/") - -# сохраняем пункты меню в общий файл -with open('data_svelte/items.json', 'w') as f: - json.dump(allMenuItems, f, ensure_ascii=False, indent=4, sort_keys=False) - - -# собираем списки API для интеграции вызовов модулей -getAPI("src/modules/system/") -getAPI("src/modules/exec/") -getAPI("src/modules/sensors/") -getAPI("src/modules/lcd/") - -# сохраняем все API в API.cpp -apicpp = '#include "ESPConfiguration.h"\n' -apicpp = apicpp + allAPI_head -apicpp = apicpp + '\n\nvoid* getAPI(String subtype, String params) {\nvoid* tmpAPI;' -apicpp = apicpp + allAPI_exec -apicpp = apicpp + 'return nullptr;\n}' -with open('src/modules/API.cpp', 'w') as f: - f.write(apicpp) \ No newline at end of file diff --git a/data_svelte/dev_conf.txt b/data_svelte/dev_conf.txt new file mode 100644 index 00000000..e69de29b diff --git a/data_svelte/edit.htm.gz b/data_svelte/edit.htm.gz new file mode 100644 index 00000000..d41d10c1 Binary files /dev/null and b/data_svelte/edit.htm.gz differ diff --git a/data_svelte/items.json b/data_svelte/items.json index 45a28d63..4885076c 100644 --- a/data_svelte/items.json +++ b/data_svelte/items.json @@ -4,50 +4,43 @@ "num": 0 }, { - "header": "Расширения" + "header": "Экраны" }, { - "name": "1. Расширитель портов Mcp23017", - "num": 1, + "name": "1. LCD экран 2004", "type": "Reading", - "subtype": "Mcp23017", - "id": "Mcp", + "subtype": "Lcd2004", + "id": "Lcd", "widget": "", "page": "", - "descr": "", - "int": "0", - "addr": "0x20", - "index": 1 + "descr": "T", + "int": 15, + "addr": "0x27", + "size": "20,4", + "coord": "0,0", + "id2show": "id датчика", + "num": 1 }, { - "name": "2. Доп. функции системы", - "num": 2, + "name": "2. LCD экран 1602", "type": "Reading", - "subtype": "SysExt", - "id": "SysExt", + "subtype": "Lcd2004", + "id": "Lcd", "widget": "", "page": "", - "descr": "", - "int": 15 - }, - { - "name": "3. Переменная", - "num": 3, - "type": "Reading", - "subtype": "Variable", - "id": "var", - "widget": "", - "page": "", - "descr": "", - "int": "0", - "val": "0" + "descr": "T", + "int": 15, + "addr": "0x27", + "size": "16,2", + "coord": "0,0", + "id2show": "id датчика", + "num": 2 }, { "header": "Модули управления" }, { - "name": "4. Кнопка (подключенная физически)", - "num": 4, + "name": "3. Кнопка (подключенная физически)", "type": "Writing", "subtype": "ButtonIn", "id": "btn", @@ -59,11 +52,11 @@ "execLevel": "1", "pinMode": "INPUT", "debounceDelay": 50, - "fixState": 1 + "fixState": 1, + "num": 3 }, { - "name": "5. Кнопка управляющая пином (Реле с кнопкой)", - "num": 5, + "name": "4. Кнопка управляющая пином (Реле с кнопкой)", "type": "Writing", "subtype": "ButtonOut", "id": "btn", @@ -72,31 +65,56 @@ "descr": "", "int": 0, "inv": 0, - "pin": 2 + "pin": 2, + "num": 4 + }, + { + "name": "5. Сервопривод", + "type": "Writing", + "subtype": "IoTServo", + "id": "servo", + "widget": "range", + "page": "servo", + "descr": "угол", + "int": 1, + "pin": 12, + "apin": -1, + "amap": "0, 4096, 0, 180", + "num": 5 + }, + { + "name": "6. MP3 плеер", + "type": "Reading", + "subtype": "Mp3", + "id": "mp3", + "widget": "", + "page": "", + "descr": "", + "int": 1, + "pins": "14,12", + "volume": 20, + "num": 6 + }, + { + "name": "7. Таймер", + "type": "Writing", + "subtype": "Timer", + "id": "timer", + "widget": "", + "page": "", + "descr": "", + "int": 1, + "countDown": 15, + "ticker": 0, + "repeat": 0, + "needSave": 0, + "num": 7 }, { "header": "Сенсоры" }, { - "name": "6. Датчик напряжения ADS1115", - "num": 6, - "type": "Reading", - "subtype": "Ads1115", - "id": "Ads3", - "widget": "anydataVlt", - "page": "Сенсоры", - "descr": "ADS_3", - "pin": "0", - "mode": "volt", - "gain": "3/4x", - "plus": 0, - "multiply": 1, - "round": 100, - "int": 10 - }, - { - "name": "7. Cенсор температуры AHT20", - "num": 7, + "name": "8. Cенсор температуры AHT20", "type": "Reading", "subtype": "Aht20t", "id": "Temp20", @@ -105,11 +123,11 @@ "descr": "AHT20 Температура", "int": 15, "addr": "0x38", - "round": 1 + "round": 1, + "num": 8 }, { - "name": "8. Cенсор влажности AHT20", - "num": 8, + "name": "9. Cенсор влажности AHT20", "type": "Reading", "subtype": "Aht20h", "id": "Hum20", @@ -118,11 +136,11 @@ "descr": "AHT20 Влажность", "int": 15, "addr": "0x38", - "round": 1 + "round": 1, + "num": 9 }, { - "name": "9. Аналоговый сенсор", - "num": 9, + "name": "10. Аналоговый сенсор", "type": "Reading", "subtype": "AnalogAdc", "id": "t", @@ -134,11 +152,12 @@ "multiply": 1, "round": 1, "pin": 0, - "int": 15 + "int": 15, + "avgSteps": 1, + "num": 10 }, { - "name": "10. Cенсор температуры Bme280", - "num": 10, + "name": "11. Cенсор температуры Bme280", "type": "Reading", "subtype": "Bme280t", "id": "tmp3", @@ -147,11 +166,11 @@ "descr": "Температура", "int": 15, "addr": "0x77", - "round": 1 + "round": 1, + "num": 11 }, { - "name": "11. Cенсор давления Bme280", - "num": 11, + "name": "12. Cенсор давления Bme280", "type": "Reading", "subtype": "Bme280p", "id": "Press3", @@ -160,11 +179,11 @@ "descr": "Давление", "int": 15, "addr": "0x77", - "round": 1 + "round": 1, + "num": 12 }, { - "name": "12. Cенсор влажности Bme280", - "num": 12, + "name": "13. Cенсор влажности Bme280", "type": "Reading", "subtype": "Bme280h", "id": "Hum3", @@ -173,11 +192,11 @@ "descr": "Влажность", "int": 15, "addr": "0x77", - "round": 1 + "round": 1, + "num": 13 }, { - "name": "13. Cенсор температуры Bmp280", - "num": 13, + "name": "14. Cенсор температуры Bmp280", "type": "Reading", "subtype": "Bmp280t", "id": "tmp3", @@ -186,11 +205,11 @@ "descr": "280 Температура", "int": 15, "addr": "0x77", - "round": 1 + "round": 1, + "num": 14 }, { - "name": "14. Cенсор давления Bmp280", - "num": 14, + "name": "15. Cенсор давления Bmp280", "type": "Reading", "subtype": "Bmp280p", "id": "Press3", @@ -199,11 +218,11 @@ "descr": "280 Давление", "int": 15, "addr": "0x77", - "round": 1 + "round": 1, + "num": 15 }, { - "name": "15. Cенсор температуры dht11", - "num": 15, + "name": "16. Cенсор температуры dht11", "type": "Reading", "subtype": "Dht1122t", "id": "tmp3", @@ -212,11 +231,11 @@ "descr": "Температура", "int": 15, "pin": 0, - "senstype": "dht11" + "senstype": "dht11", + "num": 16 }, { - "name": "16. Cенсор влажности dht11", - "num": 16, + "name": "17. Cенсор влажности dht11", "type": "Reading", "subtype": "Dht1122h", "id": "Hum3", @@ -225,11 +244,11 @@ "descr": "Влажность", "int": 15, "pin": 0, - "senstype": "dht11" + "senstype": "dht11", + "num": 17 }, { - "name": "17. Cенсор температуры ds18b20", - "num": 17, + "name": "18. Cенсор температуры ds18b20", "type": "Reading", "subtype": "Ds18b20", "id": "dstmp", @@ -240,11 +259,11 @@ "pin": 2, "index": 0, "addr": "", - "round": 1 + "round": 1, + "num": 18 }, { - "name": "18. Cенсор температуры GY21", - "num": 18, + "name": "19. Cенсор температуры GY21", "type": "Reading", "subtype": "GY21t", "id": "tmp4", @@ -252,11 +271,11 @@ "page": "Сенсоры", "descr": "Температура", "round": 1, - "int": 15 + "int": 15, + "num": 19 }, { - "name": "19. Cенсор влажности GY21", - "num": 19, + "name": "20. Cенсор влажности GY21", "type": "Reading", "subtype": "GY21h", "id": "Hum4", @@ -264,11 +283,11 @@ "page": "Сенсоры", "descr": "Влажность", "round": 1, - "int": 15 + "int": 15, + "num": 20 }, { - "name": "20. Cенсор температуры HDC1080", - "num": 20, + "name": "21. Cенсор температуры HDC1080", "type": "Reading", "subtype": "Hdc1080t", "id": "Temp1080", @@ -277,11 +296,11 @@ "descr": "1080 Температура", "int": 15, "addr": "0x40", - "round": 1 + "round": 1, + "num": 21 }, { - "name": "21. Cенсор влажности HDC1080", - "num": 21, + "name": "22. Cенсор влажности HDC1080", "type": "Reading", "subtype": "Hdc1080h", "id": "Hum1080", @@ -290,11 +309,11 @@ "descr": "1080 Влажность", "int": 15, "addr": "0x40", - "round": 1 + "round": 1, + "num": 22 }, { - "name": "22. Cенсор температуры MAX6675", - "num": 22, + "name": "23. Cенсор температуры MAX6675", "type": "Reading", "subtype": "Max6675t", "id": "maxtmp", @@ -304,131 +323,21 @@ "int": 15, "DO": 12, "CS": 13, - "CLK": 14 + "CLK": 14, + "num": 23 }, { - "name": "23. Датчик CO2 MHZ-19 UART", - "num": 23, - "type": "Reading", - "subtype": "Mhz19uart", - "id": "co2uart", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "CO2uart", - "plus": 0, - "multiply": 1, - "round": 1, - "pin": 0, - "rxPin": 14, - "txPin": 16, - "int": 15, - "range": 5000, - "ABC": 1 - }, - { - "name": "24. Датчик CO2 MHZ-19 PWM", + "name": "24. Сканер кнопок 433 MHz", "num": 24, "type": "Reading", - "subtype": "Mhz19pwm", - "id": "co2pwm", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "CO2pwm", - "plus": 0, - "multiply": 1, - "round": 1, - "pin": 16, - "int": 300 + "subtype": "RCswitch", + "id": "rsw", + "int": 500, + "pinRx": 12, + "pinTx": 12 }, { - "name": "25. Cенсор температуры от MHZ-19 UART", - "num": 25, - "type": "Reading", - "subtype": "Mhz19temp", - "id": "Mhz19temp", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "Температура", - "plus": 0, - "multiply": 1, - "round": 1, - "rxPin": 14, - "txPin": 16, - "ABC": 1, - "int": 30 - }, - { - "name": "26. Рабочий диапазон от MHZ-19 UART", - "num": 26, - "type": "Reading", - "subtype": "Mhz19range", - "id": "Mhz19range", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "Диапазон", - "plus": 0, - "multiply": 1, - "round": 1, - "rxPin": 14, - "txPin": 16, - "range": 5000, - "ABC": 1, - "int": 30 - }, - { - "name": "27. Автокалибровка от MHZ-19 UART", - "num": 27, - "type": "Reading", - "subtype": "Mhz19ABC", - "id": "Mhz19ABC", - "widget": "anydataDef", - "page": "Сенсоры", - "descr": "ABC", - "rxPin": 14, - "txPin": 16, - "range": 5000, - "ABC": 1, - "int": 30 - }, - { - "name": "28. Датчик пыли SDS011 PM25", - "num": 28, - "type": "Reading", - "subtype": "Sds011_25", - "id": "pmuart25", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "PM-2.5", - "plus": 0, - "multiply": 1, - "round": 10, - "rxPin": 13, - "txPin": 12, - "int": 15, - "warmUp": 30, - "period": 300 - }, - { - "name": "29. Датчик пыли SDS011 PM10", - "num": 29, - "type": "Reading", - "subtype": "Sds011_10", - "id": "pmuart10", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "PM-10", - "plus": 0, - "multiply": 1, - "round": 10, - "rxPin": 13, - "txPin": 12, - "int": 15, - "warmUp": 30, - "period": 300 - }, - { - "name": "30. Cенсор температуры Sht20", - "num": 30, + "name": "25. Cенсор температуры Sht20", "type": "Reading", "subtype": "Sht20t", "id": "tmp2", @@ -436,11 +345,11 @@ "page": "Сенсоры", "descr": "Температура", "int": 15, - "round": 1 + "round": 1, + "num": 25 }, { - "name": "31. Cенсор влажности Sht20", - "num": 31, + "name": "26. Cенсор влажности Sht20", "type": "Reading", "subtype": "Sht20h", "id": "Hum2", @@ -448,39 +357,76 @@ "page": "Сенсоры", "descr": "Влажность", "int": 15, - "round": 1 + "round": 1, + "num": 26 }, { - "header": "Экраны" - }, - { - "name": "32. LCD экран 2004", - "num": 32, + "name": "27. Сонар HC-SR04", + "num": 27, "type": "Reading", - "subtype": "Lcd2004", - "id": "Lcd", + "subtype": "Sonar", + "id": "sonar", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Расстояние (см)", + "pinTrig": 5, + "pinEcho": 4, + "int": 5 + }, + { + "header": "Расширения" + }, + { + "name": "28. Поддержка DS1302(1), DS1307(2), DS3231(3), RX8025(4)", + "type": "Reading", + "subtype": "IarduinoRTC", + "id": "RTC", "widget": "", "page": "", - "descr": "T", - "int": 15, - "addr": "0x27", - "size": "20,4", - "coord": "0,0", - "id2show": "id датчика" + "descr": "", + "int": "1", + "chipNum": 1, + "rst": 16, + "clk": 5, + "dat": 4, + "defFormat": "d-m-Y", + "ticker": 0, + "num": 28 }, { - "name": "33. LCD экран 1602", - "num": 33, + "name": "29. Расширитель портов Mcp23017", "type": "Reading", - "subtype": "Lcd2004", - "id": "Lcd", + "subtype": "Mcp23017", + "id": "Mcp", "widget": "", "page": "", - "descr": "T", + "descr": "", + "int": "0", + "addr": "0x20", + "index": 1, + "num": 29 + }, + { + "name": "30. Доп. функции системы", + "type": "Reading", + "subtype": "SysExt", + "id": "SysExt", + "widget": "", + "page": "", + "descr": "", "int": 15, - "addr": "0x27", - "size": "16,2", - "coord": "0,0", - "id2show": "id датчика" + "num": 30 + }, + { + "name": "31. Переменная", + "type": "Reading", + "subtype": "Variable", + "id": "var", + "widget": "", + "page": "", + "descr": "", + "int": "0", + "val": "0", + "num": 31 } ] \ No newline at end of file diff --git a/include/Const.h b/include/Const.h index e40a41fa..0ce78146 100644 --- a/include/Const.h +++ b/include/Const.h @@ -41,7 +41,7 @@ enum TimerTask_t { WIFI_SCAN, TIME, TIME_SYNC, UPTIME, - UDP, + UDP, //UDPP TIMES, PTASK }; diff --git a/include/StandWebServer.h b/include/StandWebServer.h index 230a712b..29ce3b26 100644 --- a/include/StandWebServer.h +++ b/include/StandWebServer.h @@ -5,10 +5,10 @@ extern void standWebServerInit(); extern bool handleFileRead(String path); extern String getContentType(String filename); -#ifdef REST_FILE_OPERATIONS +//#ifdef REST_FILE_OPERATIONS extern void handleFileUpload(); extern void handleFileDelete(); extern void handleFileCreate(); extern void handleFileList(); -#endif +//#endif #endif diff --git a/include/classes/IoTItem.h b/include/classes/IoTItem.h index f80d3098..bda22c1f 100644 --- a/include/classes/IoTItem.h +++ b/include/classes/IoTItem.h @@ -1,10 +1,14 @@ #pragma once #include "classes/IoTGpio.h" +#include struct IoTValue { float valD = 0; String valS = ""; bool isDecimal = true; + + uint8_t *extBinInfo = NULL; // дополнительные бинарные данные из модуля + size_t extBinInfoSize = 0; // размер дополнительных данных в байтах }; class IoTItem { @@ -22,17 +26,24 @@ class IoTItem { String getID(); String getValue(); + void setInterval(unsigned long interval); + unsigned long currentMillis; unsigned long prevMillis; unsigned long difference; - IoTValue value; // хранение основного значения, котрое обновляется из сценария, execute(), loop() или doByInterval() + IoTValue value; // хранение основного значения, которое обновляется из сценария, execute(), loop() или doByInterval() bool iAmDead = false; // признак необходимости удалить объект из базы bool iAmLocal = true; // признак локальной переменной + bool needSave = false; + bool enableDoByInt = true; + virtual IoTGpio* getGpioDriver(); + virtual iarduino_RTC_BASE* getRtcDriver(); virtual void setValue(IoTValue Value); + virtual void setValue(String valStr); protected: String _subtype; diff --git a/include/classes/IoTRTC.h b/include/classes/IoTRTC.h new file mode 100644 index 00000000..b2163aaf --- /dev/null +++ b/include/classes/IoTRTC.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include + +class iarduino_RTC_NTP: public iarduino_RTC_BASE { + public: + iarduino_RTC_NTP(); + ~iarduino_RTC_NTP(); + void begin(void); + uint8_t funcReadTimeIndex(uint8_t i); + void funcWriteTimeIndex(uint8_t i, uint8_t j); + uint8_t funcConvertNumToCode (uint8_t i) {return ((i/10) << 4) + (i%10);} +}; + +class IoTRTC : public iarduino_RTC { + public: + IoTRTC(uint8_t i, uint8_t j=SS, uint8_t k=SCK, uint8_t n=MOSI) : iarduino_RTC(i, j, k, n) { + if (i == 0) objClass = new iarduino_RTC_NTP(); + }; + + ~IoTRTC(); +}; \ No newline at end of file diff --git a/include/classes/ScenarioClass3.h b/include/classes/ScenarioClass3.h deleted file mode 100644 index 80b2446d..00000000 --- a/include/classes/ScenarioClass3.h +++ /dev/null @@ -1,255 +0,0 @@ -#pragma once -#include "Global.h" -#include "MqttClient.h" -#include "Buffers.h" - -class Scenario { - public: - void loop2() { - if (!jsonReadBool(settingsFlashJson, "scen")) { - return; - } - String allBlocks = scenario; - allBlocks += "\n"; - - String incommingEvent = selectToMarker(eventBuf, ","); - - String incommingEventKey = selectToMarker(incommingEvent, " "); - String incommingEventValue = selectToMarkerLast(incommingEvent, " "); - - while (allBlocks.length()) { - String oneBlock = selectToMarker(allBlocks, "end\n"); - String condition = selectToMarker(oneBlock, "\n"); - - //логическое и - if (condition.indexOf("&&") != -1) { - condition = condition += " && "; - - //посчитаем количество условий - int conditionCnt = itemsCount2(condition, "&&") - 1; - - //создадим и заполним динамический массив - bool *arr = new bool[conditionCnt]; - for (int i = 0; i < conditionCnt; i++) { - arr[i] = false; - } - - //есть ли входящее событие хотя бы в одном из условий и удавлетварено ли оно? - int evenInConditionNum = -1; - for (int i = 0; i < conditionCnt; i++) { - String buf = selectFromMarkerToMarker(condition, " && ", i); - if (isScenarioNeedToDo(buf, incommingEventKey, incommingEventValue, 1)) { - arr[i] = true; - evenInConditionNum = i; - } - } - - //если да то проверяем остальные условия по json - if (evenInConditionNum >= 0) { - for (int i = 0; i < conditionCnt; i++) { - String buf = selectFromMarkerToMarker(condition, " && ", i); - if (i != evenInConditionNum) { - if (isScenarioNeedToDoJson(buf)) { - arr[i] = true; - } - } - } - } - - //все элементы массива должны быть true - bool result = true; - for (int i = 0; i < conditionCnt; i++) { - if (!arr[i]) { - result = false; - } - } - - delete[] arr; - - if (result) { - oneBlock = deleteBeforeDelimiter(oneBlock, "\n"); - oneBlock.replace("end", ""); - - // SerialPrint("i", "Event done", incommingEvent); - SerialPrint("i", F("Scenario"), F("All conditions are matched")); - spaceCmdExecute(oneBlock); - } - - //логическое или - } else if (condition.indexOf("||") != -1) { - condition = condition += " || "; - - //посчитаем количество условий - int conditionCnt = itemsCount2(condition, "||") - 1; - - //создадим и заполним динамический массив - bool *arr = new bool[conditionCnt]; - for (int i = 0; i < conditionCnt; i++) { - arr[i] = false; - } - - //есть ли входящее событие хотя бы в одном из условий и удавлетварено ли оно? - int evenInConditionNum = -1; - for (int i = 0; i < conditionCnt; i++) { - String buf = selectFromMarkerToMarker(condition, " || ", i); - if (isScenarioNeedToDo(buf, incommingEventKey, incommingEventValue, 1)) { - arr[i] = true; - evenInConditionNum = i; - } - } - - //если да то проверяем остальные условия по json - if (evenInConditionNum >= 0) { - for (int i = 0; i < conditionCnt; i++) { - String buf = selectFromMarkerToMarker(condition, " || ", i); - if (i != evenInConditionNum) { - if (isScenarioNeedToDoJson(buf)) { - arr[i] = true; - } - } - } - } - - //хотя бы один элемент массива должн быть true - bool result = false; - for (int i = 0; i < conditionCnt; i++) { - if (arr[i]) { - result = true; - } - } - - delete[] arr; - - if (result) { - oneBlock = deleteBeforeDelimiter(oneBlock, "\n"); - oneBlock.replace("end", ""); - - // SerialPrint("i", "Event done", incommingEvent); - SerialPrint("i", F("Scenario"), F("One of all condition are matched")); - spaceCmdExecute(oneBlock); - } - - //если гистерезис - } else if (condition.indexOf("+-") != -1) { - if (isScenarioNeedToDo(condition, incommingEventKey, incommingEventValue, 2)) { - oneBlock = deleteBeforeDelimiter(oneBlock, "\n"); - oneBlock.replace("end", ""); - - // SerialPrint("i", "Event done", incommingEvent); - SerialPrint("i", F("Scenario"), "Condition are matched: " + condition); - spaceCmdExecute(oneBlock); - } - - //остальные случаи - } else { - if (isScenarioNeedToDo(condition, incommingEventKey, incommingEventValue, 1)) { - oneBlock = deleteBeforeDelimiter(oneBlock, "\n"); - oneBlock.replace("end", ""); - - // SerialPrint("i", "Event done", incommingEvent); - SerialPrint("i", F("Scenario"), "Condition are matched: " + condition); - spaceCmdExecute(oneBlock); - } - } - allBlocks = deleteBeforeDelimiter(allBlocks, "end\n"); - } - eventBuf = deleteBeforeDelimiter(eventBuf, ","); - } - - private: - bool isScenarioNeedToDo(String &condition, String &incommingEventKey, String &incommingEventValue, int type) { - bool res = false; - String setEventKey = selectFromMarkerToMarker(condition, " ", 0); - if (isEventExist(incommingEventKey, setEventKey)) { - String setEventSign; - String setEventValue; - if (type == 1) preCalculation(condition, setEventSign, setEventValue); - if (type == 2) preCalculationGisteresis(condition, setEventSign, setEventValue); - if (isConditionMatch(setEventSign, incommingEventValue, setEventValue)) { - res = true; - } - } - return res; - } - - bool isScenarioNeedToDoJson(String &condition) { - bool res = false; - String setEventKey = selectFromMarkerToMarker(condition, " ", 0); - String setEventSign; - String setEventValue; - preCalculation(condition, setEventSign, setEventValue); - String jsonValue = getValueJson(setEventKey); - if (isConditionMatch(setEventSign, jsonValue, setEventValue)) { - res = true; - } - return res; - } - - // bool isScenarioNeedToDoJson2(String &condition, String &incommingEventKey, String &incommingEventValue) { - // bool res = false; - // String setEventKey = selectFromMarkerToMarker(condition, " ", 0); - // if (isEventExist(incommingEventKey, setEventKey)) { - // String setEventSign; - // String setEventValue; - // preCalculation(condition, setEventSign, setEventValue); - // if (isConditionMatch(setEventSign, incommingEventValue, setEventValue)) { - // res = true; - // } - // } - // return res; - // } - - void preCalculation(String &condition, String &setEventSign, String &setEventValue) { - setEventSign = selectFromMarkerToMarker(condition, " ", 1); - setEventValue = selectFromMarkerToMarker(condition, " ", 2); - if (!isDigitDotCommaStr(setEventValue)) { - setEventValue = getValueJson(setEventValue); - } - } - - void preCalculationGisteresis(String &condition, String &setEventSign, String &setEventValue) { - setEventSign = selectFromMarkerToMarker(condition, " ", 1); - setEventValue = selectFromMarkerToMarker(condition, " ", 2); - if (!isDigitDotCommaStr(setEventValue)) { - String setEventValueName = selectToMarker(setEventValue, "+-"); - String gisteresisValue = selectToMarkerLast(setEventValue, "+-"); - gisteresisValue.replace("+-", ""); - String value = getValueJson(setEventValueName); - String upValue = String(value.toFloat() + gisteresisValue.toFloat()); - String lowValue = String(value.toFloat() - gisteresisValue.toFloat()); - if (setEventSign == ">") { - setEventValue = upValue; - } else if (setEventSign == "<") { - setEventValue = lowValue; - } - } - } - - bool isEventExist(String &incommingEventKey, String &setEventKey) { - bool res = false; - if (incommingEventKey == setEventKey) { - res = true; - } - return res; - } - - bool isConditionMatch(String &setEventSign, String &incommingEventValue, String &setEventValue) { - boolean flag = false; - if (setEventSign == "=") { - flag = incommingEventValue == setEventValue; - } else if (setEventSign == "!=") { - flag = incommingEventValue != setEventValue; - } else if (setEventSign == "<") { - flag = incommingEventValue.toFloat() < setEventValue.toFloat(); - } else if (setEventSign == ">") { - flag = incommingEventValue.toFloat() > setEventValue.toFloat(); - } else if (setEventSign == ">=") { - flag = incommingEventValue.toFloat() >= setEventValue.toFloat(); - } else if (setEventSign == "<=") { - flag = incommingEventValue.toFloat() <= setEventValue.toFloat(); - } - return flag; - } -}; - -extern Scenario *myScenario; diff --git a/lib/iarduino_RTC/LICENSE b/lib/iarduino_RTC/LICENSE new file mode 100644 index 00000000..8e99b7e9 --- /dev/null +++ b/lib/iarduino_RTC/LICENSE @@ -0,0 +1,13 @@ +Copyright © 2019 iarduino.ru + +Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: + +Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. + +ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/iarduino_RTC/README.md b/lib/iarduino_RTC/README.md new file mode 100644 index 00000000..c3d7253b --- /dev/null +++ b/lib/iarduino_RTC/README.md @@ -0,0 +1,104 @@ + +[![](https://iarduino.ru/img/logo.svg)](https://iarduino.ru)[![](https://wiki.iarduino.ru/img/git-shop.svg?3)](https://iarduino.ru) [![](https://wiki.iarduino.ru/img/git-wiki.svg?2)](https://wiki.iarduino.ru) [![](https://wiki.iarduino.ru/img/git-lesson.svg?2)](https://lesson.iarduino.ru)[![](https://wiki.iarduino.ru/img/git-forum.svg?2)](http://forum.trema.ru) + +# iarduino_RTC [СКАЧАТЬ](https://github.com/tremaru/iarduino_RTC/archive/1.2.1.zip) +Библиотека позволяет читать и записывать время RTC модулей на базе чипов: DS1302, [DS1307](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html), [DS3231](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html), ... +Преимуществом данной библиотеки является удобная реализация получения времени. +> Подробнее про установку библиотеки читайте в нашей [инструкции](https://wiki.iarduino.ru/page/Installing_libraries/). + +Пример подключения к [Arduino](https://iarduino.ru/shop/boards/arduino-uno-r3.html)/[Piranha UNO](https://iarduino.ru/shop/boards/piranha-uno-r3.html) с помощью [Trema Shield](https://iarduino.ru/shop/Expansion-payments/trema-shield.html) +Подробнее о [подключении модуля](https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/) +![enter image description here](https://iarduino.ru/img/upload/6a83fe7f3deb2f48d1408daac49284ba.png) + +| Модель | Ссылка на магазин| +|--|--| +| DS1307 ![enter image description here](https://wiki.iarduino.ru/img/resources/643/643.svg) | https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html| +| DS3231 ![enter image description here](https://wiki.iarduino.ru/img/resources/877/877.svg) | https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html | + + + +## Описание библиотеки: +Библиотека позволяет читать и записывать время RTC модулей на базе чипов: DS1302, [DS1307](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html), [DS3231](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html), … +Преимуществом данной библиотеки является удобная реализация получения времени. +**[ Подробное описание, подключение и примеры работы ](https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/)** + +## Назначение функций и переменных: +Подробное описание работы с библиотекой, находится в разделе https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + +**Подключаем библиотеку.** + + #include // Подключаем библиотеку. + + **Создаём объект.** + + + iarduino_RTC ОБЪЕКТ ( НАЗВАНИЕ [, ВЫВОД_RST [, ВЫВОД_CLK [, ВЫВОД_DAT ]]] ); // Создаём объект. + +**Инициализация работы RTC модуля.** + + Функция begin(); // Инициализация работы RTC модуля. + + **Установка времени.** + + Функция settime( СЕК [, МИН [, ЧАС [, ДЕНЬ [, МЕС [, ГОД [, ДН ]]]]]] ); // Установка времени. + + **Чтение времени.** + + Функция gettime( [ СТРОКА ] ); // Чтение времени. + +**Заставляет функцию gettime «мигать» указанным параметром времени.** + + функция blinktime( ПАРАМЕТР [ ЧАСТОТА ] ); // Заставляет функцию gettime «мигать» указанным параметром времени. + +**Указывает минимальный период обращения к модулю в минутах.** + + функция period( МИНУТЫ ); // Указывает минимальный период обращения к модулю в минутах. + +**Возвращает секунды от 0 до 59.** + + Переменная seconds // Возвращает секунды от 0 до 59. + + **Возвращает минуты от 0 до 59.** + + Переменная minutes // Возвращает минуты от 0 до 59. + +**Возвращает часы от 1 до 12.** + + Переменная hours // Возвращает часы от 1 до 12. + +**Возвращает часы от 0 до 23.** + + Переменная Hours // Возвращает часы от 0 до 23. + +**Возвращает полдень 0 или 1 (0-am, 1-pm).** + + Переменная midday // Возвращает полдень 0 или 1 (0-am, 1-pm). + +**Возвращает день месяца от 1 до 31.** + + Переменная day // Возвращает день месяца от 1 до 31. + +**Возвращает день недели от 0 до 6 (0-воскресенье, 6-суббота).** + + Переменная weekday // Возвращает день недели от 0 до 6 (0-воскресенье, 6-суббота). + +**Возвращает месяц от 1 до 12.** + + Переменная month // Возвращает месяц от 1 до 12. + +**Возвращает год от 0 до 99.** + + Переменная year // Возвращает год от 0 до 99. + + + + + + + + + + + + + diff --git a/lib/iarduino_RTC/examples/gettime/gettime.ino b/lib/iarduino_RTC/examples/gettime/gettime.ino new file mode 100644 index 00000000..066b7ec9 --- /dev/null +++ b/lib/iarduino_RTC/examples/gettime/gettime.ino @@ -0,0 +1,128 @@ +// Пример считывания текущего времени: // + // +// Раскомментируйте для программной реализации шины I2C: // +// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. +// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. +// Раскомментируйте для совместимости с большинством плат: // +// #include // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire. +// Ссылки для ознакомления: // +// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/ +// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + // +#include // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. +// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT. +// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C. + iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C. +// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C. + // +void setup(){ // + delay(300); // Ждем готовности модуля отвечать на запросы. + Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. + watch.begin(); // Инициируем работу с модулем. +} // +void loop(){ // + if(millis()%1000==0){ // Если прошла 1 секунда. + Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время. + delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс. + } // +} // + // +// ====================================================== // +// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: +// +// • Подключение библиотеки: +// #include +// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); +// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231); +// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22); +// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT. +// +// • Для работы с модулями, в библиотеке реализованы 7 функции: +// - Инициировать модуль begin(); +// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); +// - Получить время gettime(["строка с параметрами"]); +// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень); +// - Разгрузить шину period(минуты); +// - Получить Unix время gettimeUnix(); +// - Указать Unix время settimeUnix(секунды); +// +// • Функция begin(): +// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. +// +// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): +// - Функция записывает время в модуль. +// - Год указывается без учёта века, в формате 0-99. +// - Часы указываются в 24-часовом формате, от 0 до 23. +// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота. +// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение. +// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён. +// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений. +// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений. +// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений. +// +// • Функция gettime(["строка с параметрами"]): +// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время: +// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu". +// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05". +// - Указанные символы идентичны символам для функции date() в PHP: +// s - Вернуть секунды от 00 до 59 (два знака). +// i - Вернуть минуты от 00 до 59 (два знака). +// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака). +// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака). +// d - Вернуть день месяца от 01 до 31 (два знака). +// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота). +// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun). +// m - Вернуть месяц от 01 до 12 (два знака). +// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec). +// Y - Вернуть год от 2000 до 2099 (четыре знака). +// y - Вернуть год от 00 до 99 (два знака). +// a - Вернуть полдень am или pm (два знака, в нижнем регистре). +// A - Вернуть полдень AM или PM (два знака, в верхнем регистре). +// +// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных: +// - Пример: watch.gettime(); +// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы. +// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты. +// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды. +// seconds - Переменная содержит секунды 0-59. +// minutes - Переменная содержит минуты 0-59. +// hours - Переменная содержит часы 1-12. +// Hours - Переменная содержит часы 0-23. +// midday - Переменная содержит полдень 0-1 (0-am, 1-pm). +// day - Переменная содержит день месяца 1-31. +// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота). +// month - Переменная содержит месяц 1-12. +// year - Переменная содержит год 0-99. +// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix. +// +// • Функция blinktime(параметр [, частота ]): +// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами). +// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени. +// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете. +// - Первым аргументом функции указывается параметр в виде числа от 0 до 8: +// 0 - не мигать. +// 1 - мигают сек. +// 2 - мигают мин. +// 3 - мигают час. +// 4 - мигают дни. +// 5 - мигают мес. +// 6 - мигает год. +// 7 - мигают дни недели. +// 8 - мигает полдень. +// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц. +// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц. +// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц. +// +// • Функция period(минуты): +// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255). +// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю). +// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут. +// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения. +// +// • Функция gettimeUnix(): +// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года). +// +// • Функция settimeUnix(секунды): +// - Функция записывает время в модуль. +// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix. +// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00. \ No newline at end of file diff --git a/lib/iarduino_RTC/examples/gettimeUnix/gettimeUnix.ino b/lib/iarduino_RTC/examples/gettimeUnix/gettimeUnix.ino new file mode 100644 index 00000000..a11b0449 --- /dev/null +++ b/lib/iarduino_RTC/examples/gettimeUnix/gettimeUnix.ino @@ -0,0 +1,128 @@ +// Пример считывания секунд прошедших с начала эпохи Unix: // + // +// Раскомментируйте для программной реализации шины I2C: // +// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. +// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. +// Раскомментируйте для совместимости с большинством плат: // +// #include // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire. +// Ссылки для ознакомления: // +// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/ +// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + // +#include // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. +// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT. +// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C. + iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C. +// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C. + // +void setup(){ // + delay(300); // Ждем готовности модуля отвечать на запросы. + Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. + watch.begin(); // Инициируем работу с модулем. +} // +void loop(){ // + if (millis()%1000==0){ // Если прошла 1 секунда. + Serial.println( watch.gettimeUnix() ); // Выводим количество секунд прошедших с начала эпохи Unix (01.01.1970 00:00:00 GMT). + delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс. + } // +} // + // +// ====================================================== // +// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: +// +// • Подключение библиотеки: +// #include +// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); +// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231); +// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22); +// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT. +// +// • Для работы с модулями, в библиотеке реализованы 7 функции: +// - Инициировать модуль begin(); +// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); +// - Получить время gettime(["строка с параметрами"]); +// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень); +// - Разгрузить шину period(минуты); +// - Получить Unix время gettimeUnix(); +// - Указать Unix время settimeUnix(секунды); +// +// • Функция begin(): +// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. +// +// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): +// - Функция записывает время в модуль. +// - Год указывается без учёта века, в формате 0-99. +// - Часы указываются в 24-часовом формате, от 0 до 23. +// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота. +// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение. +// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён. +// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений. +// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений. +// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений. +// +// • Функция gettime(["строка с параметрами"]): +// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время: +// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu". +// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05". +// - Указанные символы идентичны символам для функции date() в PHP: +// s - Вернуть секунды от 00 до 59 (два знака). +// i - Вернуть минуты от 00 до 59 (два знака). +// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака). +// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака). +// d - Вернуть день месяца от 01 до 31 (два знака). +// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота). +// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun). +// m - Вернуть месяц от 01 до 12 (два знака). +// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec). +// Y - Вернуть год от 2000 до 2099 (четыре знака). +// y - Вернуть год от 00 до 99 (два знака). +// a - Вернуть полдень am или pm (два знака, в нижнем регистре). +// A - Вернуть полдень AM или PM (два знака, в верхнем регистре). +// +// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных: +// - Пример: watch.gettime(); +// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы. +// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты. +// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды. +// seconds - Переменная содержит секунды 0-59. +// minutes - Переменная содержит минуты 0-59. +// hours - Переменная содержит часы 1-12. +// Hours - Переменная содержит часы 0-23. +// midday - Переменная содержит полдень 0-1 (0-am, 1-pm). +// day - Переменная содержит день месяца 1-31. +// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота). +// month - Переменная содержит месяц 1-12. +// year - Переменная содержит год 0-99. +// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix. +// +// • Функция blinktime(параметр [, частота ]): +// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами). +// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени. +// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете. +// - Первым аргументом функции указывается параметр в виде числа от 0 до 8: +// 0 - не мигать. +// 1 - мигают сек. +// 2 - мигают мин. +// 3 - мигают час. +// 4 - мигают дни. +// 5 - мигают мес. +// 6 - мигает год. +// 7 - мигают дни недели. +// 8 - мигает полдень. +// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц. +// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц. +// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц. +// +// • Функция period(минуты): +// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255). +// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю). +// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут. +// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения. +// +// • Функция gettimeUnix(): +// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года). +// +// • Функция settimeUnix(секунды): +// - Функция записывает время в модуль. +// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix. +// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00. \ No newline at end of file diff --git a/lib/iarduino_RTC/examples/getvartime/getvartime.ino b/lib/iarduino_RTC/examples/getvartime/getvartime.ino new file mode 100644 index 00000000..5653d213 --- /dev/null +++ b/lib/iarduino_RTC/examples/getvartime/getvartime.ino @@ -0,0 +1,138 @@ +// Пример считывания текущего времени в переменные: // + // +// Раскомментируйте для программной реализации шины I2C: // +// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. +// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. +// Раскомментируйте для совместимости с большинством плат: // +// #include // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire. +// Ссылки для ознакомления: // +// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/ +// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + // +#include // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. +// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT. +// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C. + iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C. +// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C. + // +uint8_t D, M, Y, h, m, s, W; // Объявляем переменные для получения следующих значений: D-день, M-месяц, Y-год, h-часы, m-минуты, s-секунды, W-день недели. + // +void setup(){ // + delay(300); // Ждем готовности модуля отвечать на запросы. + Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. + watch.begin(); // Инициируем работу с модулем. +} // +void loop(){ // + if(millis()%1000==0){ // Если прошла 1 секунда. + watch.gettime(); // Считываем текущее время из модуля в буфер библиотеки. + D = watch.day; // Получаем из буфера библиотеки текущий день месяца 1-31. + M = watch.month; // Получаем из буфера библиотеки текущий месяц 1-12. + Y = watch.year; // Получаем из буфера библиотеки текущий год 0-99. + h = watch.Hours; // Получаем из буфера библиотеки текущие часы 0-23. + m = watch.minutes; // Получаем из буфера библиотеки текущие минуты 0-59. + s = watch.seconds; // Получаем из буфера библиотеки текущие секунды 0-59. + W = watch.weekday; // Получаем из буфера библиотеки текущий день недели 0-6. + Serial.println((String) D+"-"+M+"-"+Y+", "+h+":"+m+":"+s+", "+W); // Выводим время в монитор, одной строкой. + delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс. + } // +} // + // +// ================================================================== // +// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: +// +// • Подключение библиотеки: +// #include +// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); +// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231); +// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22); +// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT. +// +// • Для работы с модулями, в библиотеке реализованы 7 функции: +// - Инициировать модуль begin(); +// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); +// - Получить время gettime(["строка с параметрами"]); +// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень); +// - Разгрузить шину period(минуты); +// - Получить Unix время gettimeUnix(); +// - Указать Unix время settimeUnix(секунды); +// +// • Функция begin(): +// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. +// +// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): +// - Функция записывает время в модуль. +// - Год указывается без учёта века, в формате 0-99. +// - Часы указываются в 24-часовом формате, от 0 до 23. +// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота. +// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение. +// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён. +// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений. +// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений. +// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений. +// +// • Функция gettime(["строка с параметрами"]): +// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время: +// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu". +// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05". +// - Указанные символы идентичны символам для функции date() в PHP: +// s - Вернуть секунды от 00 до 59 (два знака). +// i - Вернуть минуты от 00 до 59 (два знака). +// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака). +// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака). +// d - Вернуть день месяца от 01 до 31 (два знака). +// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота). +// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun). +// m - Вернуть месяц от 01 до 12 (два знака). +// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec). +// Y - Вернуть год от 2000 до 2099 (четыре знака). +// y - Вернуть год от 00 до 99 (два знака). +// a - Вернуть полдень am или pm (два знака, в нижнем регистре). +// A - Вернуть полдень AM или PM (два знака, в верхнем регистре). +// +// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных: +// - Пример: watch.gettime(); +// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы. +// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты. +// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды. +// seconds - Переменная содержит секунды 0-59. +// minutes - Переменная содержит минуты 0-59. +// hours - Переменная содержит часы 1-12. +// Hours - Переменная содержит часы 0-23. +// midday - Переменная содержит полдень 0-1 (0-am, 1-pm). +// day - Переменная содержит день месяца 1-31. +// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота). +// month - Переменная содержит месяц 1-12. +// year - Переменная содержит год 0-99. +// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix. +// +// • Функция blinktime(параметр [, частота ]): +// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами). +// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени. +// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете. +// - Первым аргументом функции указывается параметр в виде числа от 0 до 8: +// 0 - не мигать. +// 1 - мигают сек. +// 2 - мигают мин. +// 3 - мигают час. +// 4 - мигают дни. +// 5 - мигают мес. +// 6 - мигает год. +// 7 - мигают дни недели. +// 8 - мигает полдень. +// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц. +// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц. +// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц. +// +// • Функция period(минуты): +// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255). +// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю). +// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут. +// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения. +// +// • Функция gettimeUnix(): +// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года). +// +// • Функция settimeUnix(секунды): +// - Функция записывает время в модуль. +// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix. +// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00. \ No newline at end of file diff --git a/lib/iarduino_RTC/examples/setsystime/setsystime.ino b/lib/iarduino_RTC/examples/setsystime/setsystime.ino new file mode 100644 index 00000000..9c393afc --- /dev/null +++ b/lib/iarduino_RTC/examples/setsystime/setsystime.ino @@ -0,0 +1,137 @@ +// Пример установки системного времени (вашего компьютера) // + // +// Раскомментируйте для программной реализации шины I2C: // +// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. +// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. +// Раскомментируйте для совместимости с большинством плат: // +// #include // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire. +// Ссылки для ознакомления: // +// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/ +// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + // +#include // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. +// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT. +// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C. + iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C. +// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C. + // +// Определяем системное время: // Время загрузки скетча. +const char* strM="JanFebMarAprMayJunJulAugSepOctNovDec"; // Определяем массив всех вариантов текстового представления текущего месяца находящегося в предопределенном макросе __DATE__. +const char* sysT=__TIME__; // Получаем время компиляции скетча в формате "SS:MM:HH". +const char* sysD=__DATE__; // Получаем дату компиляции скетча в формате "MMM:DD:YYYY", где МММ - текстовое представление текущего месяца, например: Jul. +// Парсим полученные значения в массив: // Определяем массив «i» из 6 элементов типа int, содержащий следующие значения: секунды, минуты, часы, день, месяц и год компиляции скетча. +const int i[6] {(sysT[6]-'0')*10+(sysT[7]-'0'), (sysT[3]-'0')*10+(sysT[4]-'0'), (sysT[0]-'0')*10+(sysT[1]-'0'), (sysD[4]-'0')*10+(sysD[5]-'0'), ((int)memmem(strM,36,sysD,3)+3-(int)&strM[0])/3, (sysD[9]-'0')*10+(sysD[10]-'0')}; + // +void setup(){ // + delay(300); // Ждем готовности модуля отвечать на запросы. + Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. + watch.begin(); // Инициируем работу с модулем. + watch.settime(i[0],i[1],i[2],i[3],i[4],i[5]); // Устанавливаем время в модуль: i[0] сек, i[1] мин, i[2] час, i[3] день, i[4] месяц, i[5] год, без указания дня недели. +// watch.settime(i[0],i[1],i[2],i[3],i[4],i[5], 2); // Можно установить время с указанием дня недели, где последний параметр, это день недели (указывается вручную) в формате: 0-воскресенье, 1-понедельник, ... , 6-суббота. +} // +void loop(){ // + if(millis()%1000==0){ // Если прошла 1 секунда. + Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время. + delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс. + } // +} // + // +// ====================================================== // +// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: +// +// • Подключение библиотеки: +// #include +// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); +// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231); +// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22); +// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT. +// +// • Для работы с модулями, в библиотеке реализованы 7 функции: +// - Инициировать модуль begin(); +// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); +// - Получить время gettime(["строка с параметрами"]); +// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень); +// - Разгрузить шину period(минуты); +// - Получить Unix время gettimeUnix(); +// - Указать Unix время settimeUnix(секунды); +// +// • Функция begin(): +// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. +// +// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): +// - Функция записывает время в модуль. +// - Год указывается без учёта века, в формате 0-99. +// - Часы указываются в 24-часовом формате, от 0 до 23. +// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота. +// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение. +// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён. +// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений. +// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений. +// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений. +// +// • Функция gettime(["строка с параметрами"]): +// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время: +// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu". +// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05". +// - Указанные символы идентичны символам для функции date() в PHP: +// s - Вернуть секунды от 00 до 59 (два знака). +// i - Вернуть минуты от 00 до 59 (два знака). +// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака). +// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака). +// d - Вернуть день месяца от 01 до 31 (два знака). +// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота). +// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun). +// m - Вернуть месяц от 01 до 12 (два знака). +// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec). +// Y - Вернуть год от 2000 до 2099 (четыре знака). +// y - Вернуть год от 00 до 99 (два знака). +// a - Вернуть полдень am или pm (два знака, в нижнем регистре). +// A - Вернуть полдень AM или PM (два знака, в верхнем регистре). +// +// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных: +// - Пример: watch.gettime(); +// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы. +// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты. +// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды. +// seconds - Переменная содержит секунды 0-59. +// minutes - Переменная содержит минуты 0-59. +// hours - Переменная содержит часы 1-12. +// Hours - Переменная содержит часы 0-23. +// midday - Переменная содержит полдень 0-1 (0-am, 1-pm). +// day - Переменная содержит день месяца 1-31. +// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота). +// month - Переменная содержит месяц 1-12. +// year - Переменная содержит год 0-99. +// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix. +// +// • Функция blinktime(параметр [, частота ]): +// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами). +// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени. +// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете. +// - Первым аргументом функции указывается параметр в виде числа от 0 до 8: +// 0 - не мигать. +// 1 - мигают сек. +// 2 - мигают мин. +// 3 - мигают час. +// 4 - мигают дни. +// 5 - мигают мес. +// 6 - мигает год. +// 7 - мигают дни недели. +// 8 - мигает полдень. +// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц. +// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц. +// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц. +// +// • Функция period(минуты): +// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255). +// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю). +// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут. +// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения. +// +// • Функция gettimeUnix(): +// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года). +// +// • Функция settimeUnix(секунды): +// - Функция записывает время в модуль. +// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix. +// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00. \ No newline at end of file diff --git a/lib/iarduino_RTC/examples/settime/settime.ino b/lib/iarduino_RTC/examples/settime/settime.ino new file mode 100644 index 00000000..fcf4c118 --- /dev/null +++ b/lib/iarduino_RTC/examples/settime/settime.ino @@ -0,0 +1,129 @@ +// Пример установки времени модуля: // + // +// Раскомментируйте для программной реализации шины I2C: // +// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. +// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. +// Раскомментируйте для совместимости с большинством плат: // +// #include // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire. +// Ссылки для ознакомления: // +// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/ +// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + // +#include // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. +// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT. +// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C. + iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C. +// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C. + // +void setup(){ // + delay(300); // Ждем готовности модуля отвечать на запросы. + Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. + watch.begin(); // Инициируем работу с модулем. + watch.settime(0,51,21,27,10,15,2); // Записываем время в модуль: 0 сек, 51 мин, 21 час, 27, октября, 2015 года, вторник. +} // +void loop(){ // + if(millis()%1000==0){ // Если прошла 1 секунда. + Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время. + delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс. + } // +} // + // +// ====================================================== // +// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: +// +// • Подключение библиотеки: +// #include +// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); +// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231); +// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22); +// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT. +// +// • Для работы с модулями, в библиотеке реализованы 7 функции: +// - Инициировать модуль begin(); +// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); +// - Получить время gettime(["строка с параметрами"]); +// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень); +// - Разгрузить шину period(минуты); +// - Получить Unix время gettimeUnix(); +// - Указать Unix время settimeUnix(секунды); +// +// • Функция begin(): +// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. +// +// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): +// - Функция записывает время в модуль. +// - Год указывается без учёта века, в формате 0-99. +// - Часы указываются в 24-часовом формате, от 0 до 23. +// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота. +// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение. +// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён. +// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений. +// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений. +// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений. +// +// • Функция gettime(["строка с параметрами"]): +// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время: +// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu". +// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05". +// - Указанные символы идентичны символам для функции date() в PHP: +// s - Вернуть секунды от 00 до 59 (два знака). +// i - Вернуть минуты от 00 до 59 (два знака). +// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака). +// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака). +// d - Вернуть день месяца от 01 до 31 (два знака). +// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота). +// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun). +// m - Вернуть месяц от 01 до 12 (два знака). +// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec). +// Y - Вернуть год от 2000 до 2099 (четыре знака). +// y - Вернуть год от 00 до 99 (два знака). +// a - Вернуть полдень am или pm (два знака, в нижнем регистре). +// A - Вернуть полдень AM или PM (два знака, в верхнем регистре). +// +// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных: +// - Пример: watch.gettime(); +// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы. +// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты. +// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды. +// seconds - Переменная содержит секунды 0-59. +// minutes - Переменная содержит минуты 0-59. +// hours - Переменная содержит часы 1-12. +// Hours - Переменная содержит часы 0-23. +// midday - Переменная содержит полдень 0-1 (0-am, 1-pm). +// day - Переменная содержит день месяца 1-31. +// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота). +// month - Переменная содержит месяц 1-12. +// year - Переменная содержит год 0-99. +// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix. +// +// • Функция blinktime(параметр [, частота ]): +// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами). +// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени. +// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете. +// - Первым аргументом функции указывается параметр в виде числа от 0 до 8: +// 0 - не мигать. +// 1 - мигают сек. +// 2 - мигают мин. +// 3 - мигают час. +// 4 - мигают дни. +// 5 - мигают мес. +// 6 - мигает год. +// 7 - мигают дни недели. +// 8 - мигает полдень. +// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц. +// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц. +// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц. +// +// • Функция period(минуты): +// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255). +// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю). +// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут. +// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения. +// +// • Функция gettimeUnix(): +// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года). +// +// • Функция settimeUnix(секунды): +// - Функция записывает время в модуль. +// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix. +// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00. \ No newline at end of file diff --git a/lib/iarduino_RTC/examples/settimeUnix/settimeUnix.ino b/lib/iarduino_RTC/examples/settimeUnix/settimeUnix.ino new file mode 100644 index 00000000..0c6e9b8d --- /dev/null +++ b/lib/iarduino_RTC/examples/settimeUnix/settimeUnix.ino @@ -0,0 +1,129 @@ +// Пример установки времени модуля значением Unix time: // + // +// Раскомментируйте для программной реализации шины I2C: // +// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. +// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. +// Раскомментируйте для совместимости с большинством плат: // +// #include // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire. +// Ссылки для ознакомления: // +// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/ +// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ + // +#include // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. +// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT. +// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C. + iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C. +// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C. + // +void setup(){ // + delay(300); // Ждем готовности модуля отвечать на запросы. + Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. + watch.begin(); // Инициируем работу с модулем. + watch.settimeUnix(1577836800); // Записываем время в модуль: 01.01.1970 00:00:00 (дата начала эпохи Unix) + 1577836800 сек = 01.01.2020 00:00:00. +} // +void loop(){ // + if(millis()%1000==0){ // Если прошла 1 секунда. + Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время. + delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс. + } // +} // + // +// ====================================================== // +// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ: +// +// • Подключение библиотеки: +// #include +// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]); +// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231); +// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22); +// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT. +// +// • Для работы с модулями, в библиотеке реализованы 7 функции: +// - Инициировать модуль begin(); +// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]); +// - Получить время gettime(["строка с параметрами"]); +// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень); +// - Разгрузить шину period(минуты); +// - Получить Unix время gettimeUnix(); +// - Указать Unix время settimeUnix(секунды); +// +// • Функция begin(): +// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д. +// +// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]): +// - Функция записывает время в модуль. +// - Год указывается без учёта века, в формате 0-99. +// - Часы указываются в 24-часовом формате, от 0 до 23. +// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота. +// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение. +// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён. +// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений. +// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений. +// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений. +// +// • Функция gettime(["строка с параметрами"]): +// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время: +// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu". +// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05". +// - Указанные символы идентичны символам для функции date() в PHP: +// s - Вернуть секунды от 00 до 59 (два знака). +// i - Вернуть минуты от 00 до 59 (два знака). +// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака). +// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака). +// d - Вернуть день месяца от 01 до 31 (два знака). +// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота). +// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun). +// m - Вернуть месяц от 01 до 12 (два знака). +// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec). +// Y - Вернуть год от 2000 до 2099 (четыре знака). +// y - Вернуть год от 00 до 99 (два знака). +// a - Вернуть полдень am или pm (два знака, в нижнем регистре). +// A - Вернуть полдень AM или PM (два знака, в верхнем регистре). +// +// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных: +// - Пример: watch.gettime(); +// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы. +// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты. +// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды. +// seconds - Переменная содержит секунды 0-59. +// minutes - Переменная содержит минуты 0-59. +// hours - Переменная содержит часы 1-12. +// Hours - Переменная содержит часы 0-23. +// midday - Переменная содержит полдень 0-1 (0-am, 1-pm). +// day - Переменная содержит день месяца 1-31. +// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота). +// month - Переменная содержит месяц 1-12. +// year - Переменная содержит год 0-99. +// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix. +// +// • Функция blinktime(параметр [, частота ]): +// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами). +// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени. +// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете. +// - Первым аргументом функции указывается параметр в виде числа от 0 до 8: +// 0 - не мигать. +// 1 - мигают сек. +// 2 - мигают мин. +// 3 - мигают час. +// 4 - мигают дни. +// 5 - мигают мес. +// 6 - мигает год. +// 7 - мигают дни недели. +// 8 - мигает полдень. +// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц. +// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц. +// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц. +// +// • Функция period(минуты): +// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255). +// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю). +// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут. +// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения. +// +// • Функция gettimeUnix(): +// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года). +// +// • Функция settimeUnix(секунды): +// - Функция записывает время в модуль. +// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix. +// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00. \ No newline at end of file diff --git a/lib/iarduino_RTC/extras/DS1302.pdf b/lib/iarduino_RTC/extras/DS1302.pdf new file mode 100644 index 00000000..fd672446 Binary files /dev/null and b/lib/iarduino_RTC/extras/DS1302.pdf differ diff --git a/lib/iarduino_RTC/extras/DS1307.pdf b/lib/iarduino_RTC/extras/DS1307.pdf new file mode 100644 index 00000000..276e7a16 Binary files /dev/null and b/lib/iarduino_RTC/extras/DS1307.pdf differ diff --git a/lib/iarduino_RTC/extras/DS3231.pdf b/lib/iarduino_RTC/extras/DS3231.pdf new file mode 100644 index 00000000..a445882a Binary files /dev/null and b/lib/iarduino_RTC/extras/DS3231.pdf differ diff --git a/lib/iarduino_RTC/extras/RX8025.txt b/lib/iarduino_RTC/extras/RX8025.txt new file mode 100644 index 00000000..efb28e28 --- /dev/null +++ b/lib/iarduino_RTC/extras/RX8025.txt @@ -0,0 +1,196 @@ +Модуль часов реального времени RX-8025 SA/NB: + +НАЗНАЧЕНИЕ ВЫВОДОВ: ++-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Вывод | I/O | Назначение: | ++-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+ +| SCL | I | Линия тактирования шины I2C. | +| SDA | I/O | Линия данных шины I2C. | ++-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+ +| FOUT | O | Выход тактового сигнала (32,768 кГц), работает при наличии 1 на выводе FOE. Если на FOE уровень 0 или OPEN, то FOUT=0. | +| FOE | I | Вход управления выводом FOUT. Если FOE=1 то FOUT=32.768кГц. Если FOE=0 то FOUT=0. Вывод FOE толерантен к 5.5В, он внутрисхемно прижат к GND. | ++-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+ +| /INTA | O | N-канальный выходом с открытым стоком, предназначен для вывода прерываний будильника Alarm_D и периодических прерываний. | +| /INTB | O | N-канальный выходом с открытым стоком, предназначен для вывода прерываний будильника Alarm_W. | ++-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+ +| TEST | − | Вывод используется производителем для тестирования. Обязательно подключите к Vcc. | +| VDD | − | Vcc от +1.7В до +5.5В, номинально 3.0В. | +| GND | − | GND. | +| N.C. | − | На чипе RX-8025NB контакты N.C. соеденены друг с другом. Оставьте их неподключёнными или подключите все к Vcc или все к GND. | ++-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+ + +ЛОГИЧЕСКИЕ УРОВНИ: +Vin 0 = 0В...0,2Vcc +Vin 1 = 0,8Vcc...5,5В + +ФУНКЦИИ МОДУЛЯ: + +1) ТЕКУЩЕЕ ВРЕМЯ: + Модуль позволяет устанавливать, синхронизировать и отображать данные, включая год (последние две цифры), месяц, дату, день, час, минуту и ​​секунду. + Любой (двузначный) год, кратный 4, считается високосным и рассчитывается автоматически до 2099 года. +2) ФУНКЦИЯ РЕГУЛИРОВКИ ТОЧНОСТИ ЧАСОВ: + Точность часов можно отрегулировать вперед или назад изменив частоту с кварца 32,768 кГц с шагом ±3,05 × 10^–6. + Для регулировки требуется записать в регистр Digital Offset знаковое значение в 7-битном двоичном коде (от −62 до +63). + На предделитель часов поступит частота = 32768 Гц - DigitalOffset * 3,05 × 10^–6. + Примечание: Можно настроить только точность часов. Настройки не влияют на выходной сигнал 32,768 кГц с вывода FOUT. +3) ФУНКЦИЯ ПЕРИОДИЧЕСКОГО ПРЕРЫВАНИЯ: + В дополнение к функции будильника Alarm_D через вывод /INTA могут выводиться периодические прерывания. + Периодическое прерывание настраивается битами CT2-CT0 регистра Control-1. + При срабатывании прерывания устанавливается флаг CTFG регистра Control-2, а на выводе /INTA устанавливается уровень логического 0. + Сброс флага CTFG освобождает вывод /INTA до следующего прерывания. + Биты CT2-CT0 позволяют выбрать частоту прерываний: 2 Гц (пол секунды), 1 Гц (ежесекундно), 1/60 Гц (ежеминутно), ежечасно или ежемесячно. +4) ФУНКЦИИ БУДИЛЬНИКА: + Модуль оснащен двумя будильниками (Alarm_D и Alarm_W), которые выводят сигнал прерывания (на выводы /INTA, /INTB) при совпадении времени. + • Будильник Alarm_W на основе дня недели, часа и минут, выводит сигнал прерывания через вывод /INTB. Будильник позволяет выбрать несколько деней недели. + Будильник срабатывает если он включён битом WALE регистра Control-1, при совпадении времени будильника с текущим временем. + При срабатывании будильника устанавливается флаг WAFG регистра Control-2, а на выводе /INTB устанавливается уровень логического 0. + Сброс флага WAFG освобождает вывод /INTB до следующего прерывания. + Если для будильника установить текущее время, то он сработает не немедленно, а при следующем совпадении времени. + Для установки нового времени будильника рекомендуется его отключить WALE=0, установить время будильника Alarm_W Minute/Hour/Day, сбросить прерывание будильника WAFG=0, включить будильник WALE=1. + • Будильник Alarm_D использует только часы и минуты, выводит сигнал прерывания через вывод /INTA. + Будильник срабатывает если он включён битом DALE регистра Control-1, при совпадении времени будильника с текущим временем. + При срабатывании будильника устанавливается флаг DAFG регистра Control-2, в на выводе /INTA устанавливается уровень логического 0. + Сброс флага DAFG освобождает вывод /INTA до следующего прерывания. + Если для будильника установить текущее время, то он сработает не немедленно, а при следующем совпадении времени. + Для установки нового времени будильника рекомендуется его отключить DALE=0, установить время будильника Alarm_D Minute/Hour, сбросить прерывание будильника DAFG=0, включить будильник DALE=1. +5) ФУНКЦИЯ ОБНАРУЖЕНИЯ ОСТАНОВКИ КОЛЕБАНИЙ: + При обнаружении остановки колебаний устанавливается флаг /XST регистра Control-2 (активный уровень 0) и остаётся в таком состоянии до его сброва в 1 по шине I2C. + Это позволяет определить, что данные часов стали некорректными. +6) ФУНКЦИЯ ОБНАРУЖЕНИЯ ПАДЕНИЯ МОЩНОСТИ (КОНТРОЛЬ НАПРЯЖЕНИЯ): + При снижении Vcc ниже порогового уровня, устанавливается флаг VDET регистра Control-2 и остаётся в таком состоянии до его перезаписи в 0 по шине I2C. + Выборка напряжения выполняется один раз в секунду. + Пороговый уровень выбирается битом VDSL регистра Control-2, доступны значения 1.3В и 2.1 В. +7) ФУНКЦИЯ ОБНАРУЖЕНИЯ СБРОСА ПРИ ВКЛЮЧЕНИИ ПИТАНИЯ: + При подаче питания происходит сброс регистров в значение по умолчанию и установка флага PON регистра Control-2 в значение 1, это значение остается до его перезаписи в 0 по шине I2C. + Пока флаг PON установлен в 1, все биты регистров Digital-Offset, Control-1 и Control-2 (кроме PON и /XST) сбрасываются в «0». Это также приводит к остановке прерываний на выводах /INTA и /INTB. + Для начала работы необходимо сбросить флаг PON в 0, что перезапустит функцию обнаружения сброса при включении питания. +8) ТАКТОВЫЙ ВЫХОД 32,768 кГц + Тактовая частота 32,768 кГц (с точностью, равной точности встроенного кварцевого генератора) может выводиться через вывод с открытым стоком FOUT. + Вывод FOUT включается подачей 1 на вход FOE. Если на вход FOE подать 0, то и на выходе FOUT будет 0. +9) ИНТЕРФЕЙС + Данные считываются и записываются через интерфейс шины I2C. Максимальная тактовая частота 400 кГц (при Vcc ≥ 1,7 В). + +КАРТА РЕГИСТРОВ: ++-------+-------------------+---------------------------------------------------------------------------------------------------+ +|Address| Function | 7 6 5 4 3 2 1 0 | ++-------+-------------------+---------------------------------------------------------------------------------------------------+ +| 0 | Seconds | (0) S40 S20 S10 S8 S4 S2 S1 | +| 1 | Minutes | (0) M40 M20 M10 M8 M4 M2 M1 | +| 2 | Hours | (0) (0) H20 P,/A H10 H8 H4 H2 H1 | +| 3 | Days | (0) (0) (0) (0) (0) W4 W2 W1 | Так написано в datasheet +| | | (0) Сб Пт Чт Ср Вт Пн Вс | А так на самом деле. И модуль не определяет день недели, а тупо его увеличивает после 23:59:59 +| 4 | Days | (0) (0) D20 D10 D8 D4 D2 D1 | +| 5 | Months | «0» (0) (0) MO10 MO8 MO4 MO2 MO1 | +| 6 | Years | Y80 Y40 Y20 Y10 Y8 Y4 Y2 Y1 | ++-------+-------------------+---------------------------------------------------------------------------------------------------+ +| 7 | Digital Offset | «0» F6 F5 F4 F3 F2 F1 F0 | Значения по умолчанию (с момента установки бита PON) 00000000 ++-------+-------------------+---------------------------------------------------------------------------------------------------+ +| 8 | Alarm_W Minute | (0) WM40 WM20 WM10 WM8 WM4 WM2 WM1 | +| 9 | Alarm_W Hour | (0) (0) WH20 WP,/A WH10 WH8 WH4 WH2 WH1 | +| A | Alarm_W Day | (0) WW6 WW5 WW4 WW3 WW2 WW1 WW0 | +| B | Alarm_D Minute | (0) DM40 DM20 DM10 DM8 DM4 DM2 DM1 | +| C | Alarm_D Hour | (0) (0) DH20 DP,/A DH10 DH8 DH4 DH2 DH1 | ++-------+-------------------+---------------------------------------------------------------------------------------------------+ +| D | Reserved | - - - - - - - - | ++-------+-------------------+---------------------------------------------------------------------------------------------------+ +| E | Control-1 | WALE DALE /12,24 • TEST CT2 CT1 CT0 | Значения по умолчанию (с момента установки бита PON) 00000000 +| F | Control-2 | VDSL VDET /XST PON • CTFG WAFG DAFG | Значения по умолчанию (с момента установки бита PON) 00?10000 ++-------+-------------------+---------------------------------------------------------------------------------------------------+ + +Осторожно: + Бит PON Является битом флага сброса при включении питания. Устанавливается в 1, когда происходит сброс, например, при первоначальном включении питания или при восстановлении после падения напряжения питания. + При этом все биты в регистрах Control-1 и Control-2, кроме битов PON и /XST, сбрасываются в 0. + Примечание: Пока бит PON не установится в 1 все остальные значения регистров не определены, поэтому обязательно выполните сброс перед использованием модуля. + Кроме того, избегайте ввода неверных данных о дате и времени, так как работа часов не гарантируется, если данные о времени неверны. + Бит TEST Используется производителем для тестирования. Убедитесь, что для этого бита установлено значение «0». + Reserved Регистр с адресом D используется для заводских настроек. Не читайте и не записывайте в этот регистр. + Биты «0» Должны быть установлены в 0 при записи. Их значение при чтении будет 0. + Биты (0) Доступны только для чтения. Их значение при чтении всегда равно 0. + Биты • Являются битами ОЗУ, которые могут содержать любое значение и доступны для чтения/записи. Однако эти биты сбрасываются в 0, когда значение бита PON равно 1. + +0) Seconds Регистр счётчика секунд в двоично-десятичном формате (0b X101 1001 = 59сек). +1) Minutes Регистр счётчика минут в двоично-десятичном формате (0b X101 1001 = 59мин). +2) Hours Регистр счётчика часов в двоично-десятичном формате (0b XX01 1001 = 19час). + H20 P,/A В 24-часовом формате бит функционирует как H20 + В 12-часовом формате бит функционирует как P,/A (0-AM, 1-PM). + Формат часов задаёт бит /12,24 регистра Control-1. +3) Days Регистр счётчика дней недели (1-Пн, 6-Сб, 0-Вс). Значение 7-недопустимо. Так написано в datasheet, типа у регистра активны только 3 младших бита формирующих число от 0 до 6. + А на самом деле регистр хранит 7 значащих бит. Установленный бит указывает на день недели: 0-бит Вс, 1-бит Пн, 2-бит Вт, ... 6-бит Сб, 7-бит всегда 0. +4) Days Регистр счётчика дней в двоично-десятичном формате (0b XX11 0001 = 31день). +5) Months Регистр счётчика месяцев в двоично-десятичном формате (0b XXX1 0010 = 12мес = декабрь). +6) Years Регистр счётчика лет в двоично-десятичном формате (0b 1001 1001 = 99год). +7) Digital Offset Регистр регулировки точности часов. Хранит знаковое значение в 7-битном двоичном коде (от −62 = 0bX1000010, до +63 = 0bX0111111) + Частота поступающая на предделитель = 32768 Гц - DigitalOffset * 3,05 × 10^–6. (32768Гц−62*3,05×10^–6 = 32768Гц+189.1×10^–6) + Функция цифрового смещения корректирует количество тактовых импульсов каждые 20 сек. (в 00сек, 20сек и 40сек каждой минуты) + Частота на выходе FOUT не изменяется. +8) Alarm_W Minute Регистр минут будильника Alarm_W. Формат хранения данных аналогичен регистру Minutes. +9) Alarm_W Hour Регистр часов будильника Alarm_W. Формат хранения данных аналогичен регистру Hours. + WH20 WP,/A В 24-часовом формате бит функционирует как WH20 + В 12-часовом формате бит функционирует как WP,/A (0-AM, 1-PM). + Формат часов задаёт бит /12,24 регистра Control-1. +A) Alarm_W Day Регистр дней недели будильника Alarm_W. Позволяет выбрать 1 до 7 дней недели. + WW6-WW0 WW1-Пн, WW2-Вт, WW3-ср, WW4-Чт, WW5-Пт, WW6-Сб, WW0-Вс. + Если все биты установлены в 0, то будильник Alarm_W выключен. +B) Alarm_D Minute Регистр минут будильника Alarm_D. Формат хранения данных аналогичен регистру Minutes. +C) Alarm_D Hour Регистр часов будильника Alarm_D. Формат хранения данных аналогичен регистру Hours. + DH20 DP,/A В 24-часовом формате бит функционирует как DH20 + В 12-часовом формате бит функционирует как DP,/A (0-AM, 1-PM). + Формат часов задаёт бит /12,24 регистра Control-1. +E) Control-1 Регистр управления 1 + WALE Бит разрешения работы будильника Alarm_W. + 0 - будильник Alarm_W отключён. + 1 - будильник Alarm_W включён, при совпадении времени на выводе /INTB появляется прерывание. + DALE Бит разрешения работы будильника Alarm_D. + 0 - будильник Alarm_D отключён. + 1 - будильник Alarm_D включён, при совпадении времени на выводе /INTA появляется прерывание. + /12,24 Бит выбора формата часов текущего времени и будильников. + 0 - Часы текущего времени и будильников хранятся в 12-часовом формате. + 1 - Часы текущего времени и будильников хранятся в 24-часовом формате. + • + TEST + CT2-CT0 Биты настройки периодического прерывания на выводе /INTA. + 000 − Периодическое прерывание отключено, вывод /INTA отключён. + 001 − Периодическое прерывание отключено, на выволе /INTA уровень 0. + 010 - Периодическое прерывание работает на частоте 2 Гц с коэффициентом заполнения 50%. + 011 - Периодическое прерывание работает на частоте 1 Гц с коэффициентом заполнения 50%. + 100 - Периодическое прерывание срабатывает в начале каждой секунды. + 101 - Периодическое прерывание срабатывает в начале 00 секунды каждой минуты. + 110 - Периодическое прерывание срабатывает в начале 00 секунды, 00 минуты каждого часа. + 111 - Периодическое прерывание срабатывает в начале 00 секунды, 00 минуты 00 часа каждого первого числа месяца. +F) Control-2 Регистр управления 2 + VDSL Выбор порогового значения напряжения для функции обнаружения падения мощности. + 0 - 2,1 В в качестве порога функции обнаружения падения мощности. + 1 - 1,3 В в качестве порога функции обнаружения падения мощности. + VDET Флаг функции обнаружения падения мощности. Устанавливается в 1 после падения Vcc ниже порога. + Чтение: 0 - Падение мощности не обнаружено. + 1 - Обнаружено падение Vcc ниже порогового. Флаг остаётся 1 до его перезаписи в 0 по шине I2C. + Запись: 0 - Сброс флага в 0 и перезапуск функции обнаружения падения мощности. + 1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА. + /XST Флаг функции обнаружения остановки колебаний. + Чтение: 0 - Обнаружена остановка колебаний. Флаг остаётся 0 до его перезаписи в 1 по шине I2C. + 1 - Остановка колебаний не обнаружено. + Запись: 0 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 0 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА. + 1 - Сброс флага в 1 и перезапуск функции обнаружения остановки колебаний. + PON Флаг функции обнаружения сброса при включении питания. + Чтение: 0 - Сброс при включении питания не обнаружен. + 1 - Обнаружен сброс при включении питания. Флаг остаётся 1 до его перезаписи в 0 по шине I2C. + Пока флаг установлен в 1, все биты регистров Digital-Offset, Control-1 и Control-2 (кроме PON и /XST) сбрасываются в «0». Это также приводит к остановке прерываний на выводах /INTA и /INTB. + Запись: 0 - Сброс флага в 0 и перезапуск функции обнаружения сброса при включении питания. + 1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА. + • Бит является битом ОЗУ, он может содержать любое значение и доступен для чтения/записи. Бит сбрасывается в 0 если обнаружен сброс при включении питания (PON=1). + CTFG Флаг наличия периодического прерывания на выводе /INTA. + Чтение: 0 - На выходе /INTA нет сигнала периодического прерывания. + 1 - На выходе /INTA установлен сигнал периодического прерывания. + Запись: 0 - Сброс флага в 0 и освобождение /INTA до следующего прерывания. Сброс возможен если не поступает очередное прерывание и не срабатывает будильник Alarm_D. + 1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА. + WAFG Флаг будильника Alarm_W. Значение флага актуально если бит WALE регистра Control-1 равен 1. + Чтение: 0 - Будильник Alarm_W не сработал или бит WALE регистра Control-1 равен 0. + 1 - Сработал будильник Alarm_W. Флаг остаётся 1 до его перезаписи в 0 по шине I2C. + Запись: 0 - Сброс флага в 0 и отключение прерывания на выводе /INTB. + 1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА. + DAFG Флаг будильника Alarm_D. Значение флага актуально если бит DALE регистра Control-1 равен 1. + Чтение: 0 - Будильник Alarm_D не сработал или бит DALE регистра Control-1 равен 0. + 1 - Сработал будильник Alarm_D. Флаг остаётся 1 до его перезаписи в 0 по шине I2C. + Запись: 0 - Сброс флага в 0 и отключение прерывания на выводе /INTA. + 1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА. + diff --git a/lib/iarduino_RTC/keywords.txt b/lib/iarduino_RTC/keywords.txt new file mode 100644 index 00000000..5345352b --- /dev/null +++ b/lib/iarduino_RTC/keywords.txt @@ -0,0 +1,30 @@ +# #################################################### +# СИНТАКСИЧЕСКАЯ РАСКРАСКА ДЛЯ БИБИЛИОТЕКИ: +# iarduino_RTC +# #################################################### +# ТИПЫ ДАННЫХ: (KEYWORD1) + iarduino_RTC KEYWORD1 +# #################################################### +# МЕТОДЫ И ФУНКЦИИ: (KEYWORD2) + begin KEYWORD2 + settime KEYWORD2 + gettime KEYWORD2 + settimeUnix KEYWORD2 + gettimeUnix KEYWORD2 + blinktime KEYWORD2 + period KEYWORD2 + seconds KEYWORD2 + minutes KEYWORD2 + hours KEYWORD2 + Hours KEYWORD2 + midday KEYWORD2 + day KEYWORD2 + weekday KEYWORD2 + month KEYWORD2 + year KEYWORD2 + Unix KEYWORD2 +# #################################################### +# КОНСТАНТЫ: (LITERAL1) + RTC_DS1302 LITERAL1 + RTC_DS1307 LITERAL1 + RTC_DS3231 LITERAL1 \ No newline at end of file diff --git a/lib/iarduino_RTC/library.properties b/lib/iarduino_RTC/library.properties new file mode 100644 index 00000000..21f3cc8c --- /dev/null +++ b/lib/iarduino_RTC/library.properties @@ -0,0 +1,10 @@ +name = iarduino RTC (часы реального времени) +version = 2.0.0 +author = iarduino +maintainer = Панькин Павел +sentence = Библиотека для работы с часами реального времени. +paragraph = Поддерживает часы на чипах: DS1302, DS1307, DS3231, RX8025, есть возможность добавлять часы на других чипах. Библиотека позволяет устанавливать и считывать дату/время. Преимуществом данной библиотеки является удобная реализация получения времени. Считывание даты/времени можно осуществить как через переменные (year, month, day, hours, minutes, seconds и т.д.), так и одной строкой в которую попадут значения в соответствии с указанным Вами шаблоном. +category = Timing +url = http://iarduino.ru/file/235.html +architectures = avr,esp8266,esp32 +includes = iarduino_RTC.h \ No newline at end of file diff --git a/lib/iarduino_RTC/src/iarduino_RTC.cpp b/lib/iarduino_RTC/src/iarduino_RTC.cpp new file mode 100644 index 00000000..959c79bd --- /dev/null +++ b/lib/iarduino_RTC/src/iarduino_RTC.cpp @@ -0,0 +1,134 @@ +#include "iarduino_RTC.h" + +// Вывод даты и времени +char* iarduino_RTC::gettime(String i){char j[i.length()+1]; i.toCharArray(j, i.length()); j[i.length()]=0; return gettime(j);} +char* iarduino_RTC::gettime(const char* i){ + uint8_t j, k, n; bool f; // Объявляем локальные переменные + if(valRequest > millis()){valRequest=0;} // Избавляемся от переполнения millis() +// Получаем текущее время: + if(valPeriod == 0) {funcReadTime();}else // Если минимальный период опроса модуля == 0 минут, то получаем время из регистров модуля, иначе ... + if(valRequest == 0 || (valPeriod+valRequest <= millis())) {funcReadTime();}else // Если время последнего опроса модуля превысило минимальный период опроса модуля, то получаем время из регистров модуля, иначе ... + {funcCalculationTime();} // Получаем время без обращения к модулю (время рассчитывая исходя из millis и valRequest) + funcSetMoreTime(); // Преобразуем переменные не читаемые из модуля +// Вычисляем размер блока памяти под строку с ответом: + n=strlen(i)+1; // Определяем размер равный введённой строке (i) + 1 символ конца строки + for(j=0; j0){n++;} if(k>9){n++;} if(k>11){n++;} // Увеличиваем размер (n) в соостветствии со значениём найденного служебного символа + }}} +// Выделяем блок памяти под строку с ответом: + free(charReturn); // Освобождаем ранее созданный блок памяти + charReturn = (char*) malloc(n); // Выделяем новый блок памяти размером n байт +// Заполняем выделенный блок памяти: + n=0; // Определяем позицию в блоке памяти для следующего подставляемого значения + for(j=0; j6 ){i=6; } charReturn[n]=f?32:i+48; break; + /* 2 знака */ case 1: if(i>99){i=99;} charReturn[n]=f?32:i/10+48; charReturn[n+1]=f?32:i%10+48; break; + /* AM / PM */ case 2: if(i>6 ){i=6; } charReturn[n]=f?32:charMidday[i]; charReturn[n+1]=f?32:charMidday[i+1]; break; + /* дн / мес */ case 3: if(i>54){i=54;} charReturn[n]=f?32:charDayMon[i]; charReturn[n+1]=f?32:charDayMon[i+1]; charReturn[n+2]=f?32:charDayMon[i+2]; break; + /* 4 знака */ case 4: if(i>99){i=99;} charReturn[n]=f?32:(valCentury-1)/10+48; charReturn[n+1]=f?32:(valCentury-1)%10+48; charReturn[n+2]=f?32:i/10+48; charReturn[n+3]=f?32:i%10+48; break; + } +} + +// Установка даты и времени +void iarduino_RTC::settime(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ // (сек, мин, час, день, мес, год, день_недели) + funcWriteTime(i1, i2, i3, i4, i5, i6, i7); // Записываем дату и время в регистры модуля + funcReadTime(); // Читаем дату и время из регистров модуля + funcSetMoreTime(); // Корректируем переменные не читаемые из модуля (hours, midday) +} + +// Установка даты и времени от начала эпохи Unix +void iarduino_RTC::settimeUnix(uint32_t i){ // (сек) + uint32_t j; uint8_t k; bool f=true; // Объявляем временные переменные. + seconds = i % 60; // Получаем текущее значение секунд. (остаток от деления секунд прошедших с начала эпохи Unix на количество секунд в минуте) + i = (i-seconds) / 60; // Получаем количество минут прошедших с начала эпохи Unix. + minutes = i % 60; // Получаем текущее значение минут. (остаток от деления минут прошедших с начала эпохи Unix на количество минут в часе) + i = (i-minutes) / 60; // Получаем количество часов прошедших с начала эпохи Unix. + Hours = i % 24; // Получаем текущее значение часов. (остаток от деления часов прошедших с начала эпохи Unix на количество часов в дне) + i = (i-Hours) / 24; // Получаем количество дней прошедших с начала эпохи Unix. + j = 0; while((((j+1)*365)+((j+2)/4))<=i){j++;} // Получаем количество лет прошедших с начала эпохи Unix. + weekday = (i+4) % 7; // Получаем текущий день недели. (0-воскресенье, 1-понедельник, ... , 6-суббота) + i = i - (j*365) - ((j+1)/4); // Получаем количество дней прошедших в текущем году. + valCentury = ((1970+j)/100)+1; // Получаем текущий век. + year = (1970+j)%100; // Получаем две последние цифры текущего года. + k = ((1970+j)%4)==0?29:28; // Получаем количество дней в феврале текущего года. + month = 0; while(f){month++; j=month; j=(((j+1)%2)^(j<8))?31:(j==2?k:30); if(i>=j){i-=j;}else{f=false;}} + day = i+1; // Получаем текущий день. + // Устанавливаем время: + settime(seconds, minutes, Hours, day, month, year, weekday); +} + +// Чтение даты и времени в переменные из регистров модуля: +void iarduino_RTC::funcReadTime(void){ // (без параметров) + seconds = arrCalculationTime[0] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(0)); // Получаем секунды + minutes = arrCalculationTime[1] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(1)); // Получаем минуты + Hours = arrCalculationTime[2] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(2)); // Получаем часы + day = arrCalculationTime[3] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(3)); // Получаем день + month = arrCalculationTime[4] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(4)); // Получаем месяц + year = arrCalculationTime[5] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(5)); // Получаем год + weekday = arrCalculationTime[6] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(6))-1; // Получаем день недели (в регистре значение от 1 до 7, а в переменной от 0 до 6) + Unix = funcCalculationUnix(); // Получаем количество секунд (прошедших с начала эпохи Unix) + valRequest = millis(); // Сохраняем время данного запроса +} + +// Запись даты и времени в регистры модуля: +void iarduino_RTC::funcWriteTime(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ // + if(i1<=60 && i1>=0){objClass -> funcWriteTimeIndex(0, funcConvertNumToCode(i1 ));} // Сохраняем секунды + if(i2<=60 && i2>=0){objClass -> funcWriteTimeIndex(1, funcConvertNumToCode(i2 ));} // Сохраняем минуты + if(i3<=23 && i3>=0){objClass -> funcWriteTimeIndex(2, funcConvertNumToCode(i3 ));} // Сохраняем часы + if(i4<=31 && i4>=1){objClass -> funcWriteTimeIndex(3, funcConvertNumToCode(i4 ));} // Сохраняем день + if(i5<=12 && i5>=1){objClass -> funcWriteTimeIndex(4, funcConvertNumToCode(i5 ));} // Сохраняем месяц + if(i6<=99 && i6>=0){objClass -> funcWriteTimeIndex(5, funcConvertNumToCode(i6 ));} // Сохраняем год + if(i7<= 6 && i7>=0){objClass -> funcWriteTimeIndex(6, funcConvertNumToCode(i7+1));} // Сохраняем день недели (в регистре значение от 1 до 7, а в переменной от 0 до 6) +} + +// Расчёт времени без обращения к модулю: +void iarduino_RTC::funcCalculationTime(void){ // (без параметров) + uint32_t i=(millis()-valRequest)/1000; // Определяем количество секунд (прошедших после последнего обращения к модулю) + uint8_t j=30 + ( (arrCalculationTime[4] + (arrCalculationTime[4]>7?1:0)) % 2 ); // Определяем количество дней в месяце (31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + if(arrCalculationTime[4]==2){j=28+((((uint16_t)valCentury-1)*100+arrCalculationTime[5])%4?0:1);}// Если текущий месяц - февраль, то меняем на ... (31, 28/29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + i+=arrCalculationTime[0]; seconds = i%60; i/=60; // Добавляем к прошедним секундам (i) посление прочитанные секунды (arrCalculationTime[0]), результатом будет остаток, а значение i превращаем в минуты + i+=arrCalculationTime[1]; minutes = i%60; i/=60; // Добавляем к прошедним минутам (i) посление прочитанные минуты (arrCalculationTime[1]), результатом будет остаток, а значение i превращаем в часы + i+=arrCalculationTime[2]; Hours = i%24; i/=24; // Добавляем к прошедним часам (i) посление прочитанные часы (arrCalculationTime[2]), результатом будет остаток, а значение i превращаем в дни + weekday = arrCalculationTime[6]+i; if(weekday>6){weekday=0;} // День недели увеличится на (i) от прочитанного дня недели (arrCalculationTime[6]) + i+=arrCalculationTime[3]; day = i%(j+1); i/=(j+1); day+=i; // Добавляем к прошедним дням (i) посление прочитанные дни (arrCalculationTime[3]), результатом будет остаток, а значение i превращаем в месяцы + i+=arrCalculationTime[4]; month = i%13; i/=13; month+=i; // Добавляем к прошедним месяцам (i) посление прочитанные месяцы (arrCalculationTime[4]), результатом будет остаток, а значение i превращаем в годы + i+=arrCalculationTime[5]; year = i%100; // Добавляем к прошедним годам (i) посление прочитанные годы (arrCalculationTime[5]), результатом будет остаток, а значение i превращаем в дни + Unix = funcCalculationUnix(); // Получаем количество секунд прошедших с начала эпохи Unix +} + +// Расчёт количества cекунд прошедших с начала эпохи Unix: +uint32_t iarduino_RTC::funcCalculationUnix(void){ // (без параметров) + uint32_t i; // Объявляем переменную для хранения результата. (рассчёты производятся из значений переменных: seconds, minutes, Hours, day, month, year и valCentury). + uint32_t j = (uint32_t)(valCentury-1) * 100 + year; // Определяем текущий год с учётом века. (valCentury - век, year - последние два знака текущего года). + i = j - 1970; // Определяем количество прошедших лет (с 01.01.1970 г.) + i = i * 365 + ((i+1)/4); // Определяем количество дней в прошедших годах ((i+1)/4) - количество прошедших високосных лет (без учёта текущего года). + i += (month-1)*30 + ( (month + (month<9?0:1) )/2 ); // Добавляем количество дней в прошедших месяцах ((month+(month<9?0:1))/2) - количество прошедших месяцев текущего года, содержащих 31 день. + i -= month>2? (j%4==0?1:2) : 0; // Вычитаем 1 или 2 дня из февраля текущего года ((month>2) - если февраль уже прошел, j%4==0 - если текущий год високосный) + i += day-1; // Добавляем количество прошедших дней этого месяца + i *= 86400; // Получаем количество секунд прошедших дней + i += (uint32_t)Hours * 3600 + (uint32_t)minutes * 60 + seconds; // Добавляем количество секунд текущего дня + return i; // Возвращаем результат +} diff --git a/lib/iarduino_RTC/src/iarduino_RTC.h b/lib/iarduino_RTC/src/iarduino_RTC.h new file mode 100644 index 00000000..7ab1a5d8 --- /dev/null +++ b/lib/iarduino_RTC/src/iarduino_RTC.h @@ -0,0 +1,107 @@ +// Библиотека для работы с часами реального времени: (на чипе DS1302) https://iarduino.ru/shop/Expansion-payments/rtc-modul-ds1302.html +// (на чипе DS1307) https://iarduino.ru/shop/Expansion-payments/kroshechnye-rtc-modul-realnogo-vremeni.html +// https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html +// (на чипе DS3231) https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-ds3231.html +// https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html +// (на чипе RX8025) +// Версия: 2.0.0 +// Последнюю версию библиотеки Вы можете скачать по ссылке: https://iarduino.ru/file/235.html +// Подробное описание функции бибилиотеки доступно по ссылке: https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/ +// Библиотека является собственностью интернет магазина iarduino.ru и может свободно использоваться и распространяться! +// При публикации устройств или скетчей с использованием данной библиотеки, как целиком, так и её частей, +// в том числе и в некоммерческих целях, просим Вас опубликовать ссылку: https://iarduino.ru +// Автор библиотеки: Панькин Павел +// Если у Вас возникли технические вопросы, напишите нам: shop@iarduino.ru + +#ifndef iarduino_RTC_h // +#define iarduino_RTC_h // + // +#define RTC_UNDEFINED 0 // Модуль часов реального времени не определён + // +#if defined(ARDUINO) && (ARDUINO >= 100) // +#include // +#else // +#include // +#endif // + // +#include "memorysaver.h" // Подключаем файл «хранитель памяти» (внутри файла есть комментарий поясняющий как сэкономить мапять) + // +class iarduino_RTC_BASE{ // Объявляем полиморфный класс + public: // + virtual void begin (void); // Объявляем функцию инициализации модуля (без параметров) + virtual uint8_t funcReadTimeIndex (uint8_t); // Объявляем функцию чтения 1 значения из регистров даты и времени (0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели) + virtual void funcWriteTimeIndex (uint8_t, uint8_t); // Объявляем функцию записи 1 значения в регистры даты и времени (0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, значение) +}; // + // +#include "iarduino_RTC_DS1302.h" // Подключаем файл iarduino_RTC_DS1302.h +#include "iarduino_RTC_DS1307.h" // Подключаем файл iarduino_RTC_DS1307.h +#include "iarduino_RTC_DS3231.h" // Подключаем файл iarduino_RTC_DS3231.h +#include "iarduino_RTC_RX8025.h" // Подключаем файл iarduino_RTC_RX8025.h + // +class iarduino_RTC{ // + public: // + /** Конструктор класса **/ // + iarduino_RTC(uint8_t i, uint8_t j=SS, uint8_t k=SCK, uint8_t n=MOSI){ // Конструктор основного класса (название [, вывод SS/RST [, вывод SCK/CLK [, вывод MOSI/DAT]]]) + switch(i){ // Тип выбранного модуля + #ifdef RTC_ENABLE_DS1302 // + case RTC_DS1302: objClass = new iarduino_RTC_DS1302(j,k,n); break; // Если используется модуль на базе чипа DS1302, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS1302 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE + #endif // + #ifdef RTC_ENABLE_DS1307 // + case RTC_DS1307: objClass = new iarduino_RTC_DS1307; break; // Если используется модуль на базе чипа DS1307, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS1307 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE + #endif // + #ifdef RTC_ENABLE_DS3231 // + case RTC_DS3231: objClass = new iarduino_RTC_DS3231; break; // Если используется модуль на базе чипа DS3231, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS3231 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE + #endif // + #ifdef RTC_ENABLE_RX8025 // + case RTC_RX8025: objClass = new iarduino_RTC_RX8025; break; // Если используется модуль на базе чипа RX8025, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_RX8025 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE + #endif // + } // + } // + /** Пользовательские функции **/ // + void begin (void) {objClass -> begin(); gettime();} // Определяем функцию инициализации модуля (без параметров) + void period (uint8_t i) {valPeriod=i; valPeriod*=60000;} // Определяем функцию задания минимального периода обращения к модулю (i = период в минутах) + void blinktime (uint8_t i, float j=1) {valBlink=i; valFrequency=uint32_t(1000/j);} // Определяем функцию позволяющую мигать одним из параметров времени (i = 0-нет / 1-сек / 2-мин / 3-час / 4-день / 5-мес / 6-год / 7-день_недели / 8-полдень , j = частота мигания в Гц) + void gettime (void) {gettime("");} // Определяем функцию получения даты и времени из переменных (без параметров) + char* gettime (String); // Объявляем функцию «дублёр» получения даты и времени из переменных (строка с параметрами) + char* gettime (const char*); // Объявляем функцию получения даты и времени ввиде строки (строка с параметрами) + void settime (int, int=-1, int=-1, int=-1, int=-1, int=-1, int=-1); // Объявляем функцию установки даты и времени (сек, мин, час, день, мес, год, день_недели) + uint32_t gettimeUnix (void) {gettime(""); return Unix;} // Определяем функцию получения cекунд прошедших с начала эпохи Unix (без параметров) + void settimeUnix (uint32_t); // Объявляем функцию установки cекунд прошедших с начала эпохи Unix (сек) + // + /** Переменные доступные для пользователя **/ // + uint8_t seconds = 0; // Секунды 0-59 + uint8_t minutes = 0; // Минуты 0-59 + uint8_t hours = 1; // Часы 1-12 + uint8_t Hours = 0; // Часы 0-23 + uint8_t midday = 0; // Полдень 0-1 (0-am, 1-pm) + uint8_t day = 1; // День месяца 1-31 + uint8_t weekday = 0; // День недели 0-6 (0-воскресенье, 1-понедельник, ... , 6-суббота) + uint8_t month = 1; // Месяц 1-12 + uint8_t year = 0; // Год 0-99 (без учёта века) + uint32_t Unix = 0; // Секунды прошедшие с начала эпохи Unix (01.01.1970 00:00:00 GMT) + // + /** Внутренние переменные **/ // + iarduino_RTC_BASE* objClass; // Объявляем указатель на объект полиморфного класса (функции данного класса будут переопределены, т.к. указателю будет присвоена ссылка на производный класс) + char* charReturn = (char*) malloc(1); // Определяем указатель на символьную область памяти в 1 байт (указатель будет ссылаться на строку вывода времени) + const char* charInput = "waAdhHimsyMDY"; // Определяем константу-строку с символами требующими замены (данные символы заменяются функцией gettime на значение времени) + const char* charMidday = "ampmAMPM"; // Определяем константу-строку для вывода полудня (am / pm / AM / PM) + const char* charDayMon = "SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec"; // Определяем константу-строку для вывода дня недели или месяца (Mon ... Sun / Jan ... Dec) + uint8_t arrCalculationTime[7]; // Объявляем массив для рассчёта времени без обращения к модулю (для хранения последних, прочитанных из модуля, значений даты и времени) + uint8_t valBlink = 0; // Определяем параметр времени, который должен мигать (1-сек / 2-мин / 3-час / 4-день / 5-мес / 6-год / 7-день_недели / 8-полдень) + uint32_t valFrequency = 1000; // Определяем частоту мигания параметра времени для функции blinktime (по умолчанию 1 Гц) + uint8_t valCentury = 21; // Определяем переменную для хранения текущего века (по умолчанию 21 век) + uint16_t valPeriod = 0; // Определяем минимальный период опроса модуля (в минутах, от 00 до 255) + uint32_t valRequest = 0; // Определяем время последнего чтения регистров времени + private: // + /** Внутренние функции **/ // + void funcReadTime (void); // Объявляем функцию чтения даты и времени из регистров модуля (без параметров) + void funcWriteTime (int, int, int, int, int, int, int); // Объявляем функцию записи даты и времени в регистры модуля (без параметров) + uint8_t funcConvertCodeToNum (uint8_t i) {return (i >> 4)*10 + (i & 0x0F);} // Определяем функцию преобразования двоично-десятичного кода в число (код) + uint8_t funcConvertNumToCode (uint8_t i) {return ((i/10) << 4) + (i%10);} // Определяем функцию преобразования числа в двоично-десятичный код (число) + void funcSetMoreTime (void){hours=(Hours%12)?(Hours%12):12; midday=(Hours<12)?0:1;} // Корректировка переменных не читаемых из модуля (без параметров) + void funcCalculationTime (void); // Объявляем функцию расчёта времени без обращения к модулю (без параметров) + uint32_t funcCalculationUnix (void); // Объявляем функцию расчёта cекунд прошедших с начала эпохи Unix (без параметров) + void funcFillChar (uint8_t, uint8_t, uint8_t, uint8_t); // Объявляем функцию заполнения строки вывода времени (данные, тип данных, позиция для вставки, мигание) +}; // + // +#endif // \ No newline at end of file diff --git a/lib/iarduino_RTC/src/iarduino_RTC_DS1302.h b/lib/iarduino_RTC/src/iarduino_RTC_DS1302.h new file mode 100644 index 00000000..bc71fc04 --- /dev/null +++ b/lib/iarduino_RTC/src/iarduino_RTC_DS1302.h @@ -0,0 +1,67 @@ +#ifndef iarduino_RTC_DS1302_h // +#define iarduino_RTC_DS1302_h // +#define RTC_DS1302 1 // Модуль часов реального времени с протоколом передачи данных SI3, памятью 040x8 (31 байт которой доступны для хранения данных пользователя) + // +class iarduino_RTC_DS1302: public iarduino_RTC_BASE{ // + public: // + /** Конструктор класса **/ // + iarduino_RTC_DS1302(uint8_t i=SS, uint8_t j=SCK, uint8_t k=MOSI){pinRES=i; pinCLK=j; pinDAT=k;} // (вывод RST, вывод CLK, вывод DAT) + /** функции доступные пользователю **/ // +// Инициализация модуля: // + void begin(void){ // (без параметров) +// Инициализация работы с трехпроводной шиной: // + funcBegin(); // (без параметров) +// Установка флагов управления и состояния модуля: // + varI=funcReadReg(0x81); if( varI & 0b10000000){funcWriteReg(0x81, (varI&~0b10000000));} // (если установлен 7 бит в 129 регистре, то сбрасываем его - запускаем генератор) + varI=funcReadReg(0x85); if( varI & 0b10000000){funcWriteReg(0x85, (varI&~0b10000000));} // (если установлен 7 бит в 133 регистре, то сбрасываем его - переводим модуль в 24 часовой режим) + varI=funcReadReg(0x8F); if( varI & 0b10000000){funcWriteReg(0x8F, (varI&~0b10000000));} // (если установлен 7 бит в 143 регистре, то сбрасываем его - разрешаем запись в регистры модуля) + } // + // +// Чтение одного значения из регистров даты и времени модуля: // + uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели) + delay(1); return funcReadReg(arrTimeRegAddr[i]) & arrTimeRegMack[i]; // + } // + // +// Запись одного значения в регистры даты и времени модуля: // + void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение) + varI=funcReadTimeIndex(i); // Читаем данные из регистра i + j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i + j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i + funcWriteReg(arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i] + } // + // + private: // + /** Внутренние переменные **/ // + uint8_t pinRES = 0; // Определяем переменную для хранения номера вывода RST трехпроводной шины + uint8_t pinCLK = 0; // Определяем переменную для хранения номера вывода CLK трехпроводной шины + uint8_t pinDAT = 0; // Определяем переменную для хранения номера вывода DAT трехпроводной шины + uint8_t arrTimeRegAddr[7] = {0x81,0x83,0x85,0x87,0x89,0x8D,0x8B}; // Определяем массив с адресами регистров чтения даты и времени (сек, мин, час, день, месяц, год, день недели) + uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и») + uint8_t busRate = 10; // Скорость передачи данных трехпроводной шине в кГц (до 255 кГц) + uint8_t varI; // + // + /** Внутренние функции **/ // +// Функция чтения данных из регистра модуля: // + uint8_t funcReadReg(uint8_t i){ // Определяем функцию читения данных из регистра модуля (аргумент: адрес_регистра) + varI=1; // Предустанавливаем переменную varI в значение 1, чтоб не вывести: 45 апреля 255 часов 127 минут и 200 секунд + digitalWrite (pinRES, 1); // Устанавливаем линию RES в активное состояние + funcWriteByte (i); // Отправляем адрес регистра + varI=funcReadByte (true); // Читаем байт из регистра с учётом предустановленного бита + digitalWrite (pinRES, 0); // Устанавливаем линию RES в неактивное состояние + return varI; // Возвращаем значение переменной varI + } // +// Функция записи данных в регистр модуля: // + void funcWriteReg(uint8_t i, uint8_t j){ // Определяем функцию записи данных в регистр модуля (аргументы: адрес_регистра, байт_данных) + digitalWrite (pinRES, 1); // Устанавливаем линию RES в активное состояние + funcWriteByte (i-1); // Отправляем адрес регистра (при чтении указывается адрес-1) + funcWriteByte (j); // Отправляем байт данных + digitalWrite (pinRES, 0); // Устанавливаем линию RES в неактивное состояние + } // + // + /** функции для работы с трехпроводной шиной **/ // + void funcWriteByte (uint8_t j) /* Передача одного байта (байт для передачи) */ {uint8_t i=0, n=500/busRate+1; pinMode(pinDAT, OUTPUT); while(i>=0 && i<8){digitalWrite(pinDAT, (j & _BV(i))); delayMicroseconds(n); digitalWrite(pinCLK, 1); delayMicroseconds(n); digitalWrite(pinCLK, 0); i++;} pinMode(pinDAT, INPUT);} + uint8_t funcReadByte (bool j) /* Получение одного байта (флаг чтения предустановленного бита с линии DAT) */ {uint8_t i=0, k=0, n=500/busRate+1; pinMode(pinDAT, INPUT); if(j){if(digitalRead(pinDAT)){k |= _BV(i);} i++;} while(i>=0 && i<8){digitalWrite(pinCLK, 1); delayMicroseconds(n); digitalWrite(pinCLK, 0); delayMicroseconds(n); if(digitalRead(pinDAT)){k |= _BV(i);} i++;} return k;} + void funcBegin (void) /* Подготовка выводов шины (без параметров) */ {pinMode(pinRES, OUTPUT); pinMode(pinCLK, OUTPUT); pinMode(pinDAT, INPUT); digitalWrite(pinCLK, 0); digitalWrite(pinRES, 0);} +}; // + // +#endif // \ No newline at end of file diff --git a/lib/iarduino_RTC/src/iarduino_RTC_DS1307.h b/lib/iarduino_RTC/src/iarduino_RTC_DS1307.h new file mode 100644 index 00000000..b742f9bf --- /dev/null +++ b/lib/iarduino_RTC/src/iarduino_RTC_DS1307.h @@ -0,0 +1,42 @@ +#ifndef iarduino_RTC_DS1307_h // +#define iarduino_RTC_DS1307_h // +#define RTC_DS1307 2 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 064x8 (56 байт которой доступны для хранения данных пользователя) +#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C + // +class iarduino_RTC_DS1307: public iarduino_RTC_BASE{ // + public: // + /** функции доступные пользователю **/ // +// Инициализация модуля: // + void begin(void){ // (без параметров) +// Инициализация работы с шиной I2C: // + objI2C.begin(100); // (скорость шины в кГц) +// Установка флагов управления и состояния модуля: // + varI=objI2C.readByte(valAddress, 0x00); if( varI & 0b10000000 ){objI2C.writeByte(valAddress, 0x00, (varI&~0b10000000) );} // (если установлен 7 бит в 0 регистре, то сбрасываем его - запускаем генератор) + varI=objI2C.readByte(valAddress, 0x02); if( varI & 0b01000000 ){objI2C.writeByte(valAddress, 0x02, (varI&~0b01000000) );} // (если установлен 6 бит в 2 регистре, то сбрасываем его - переводим модуль в 24 часовой режим) + varI=objI2C.readByte(valAddress, 0x07); if((varI & 0b00000011) || !(varI & 0b00010000)){objI2C.writeByte(valAddress, 0x07, (varI&~0b00000011)|0b00010000 );} // (если установлены 1 и 0 биты или сброшен 4 бит в 7 регистре, то сбрасываем 1 с 0 битами, а 4 устанавливаем - выводим меандр с частотой 1 Гц на выводе SQW/OUT модуля) + } // + // +// Чтение одного значения из регистров даты и времени модуля: // + uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели) + delay(1); // + return objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; // + } // + // +// Запись одного значения в регистры даты и времени модуля: // + void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение) + varI=funcReadTimeIndex(i); // Читаем данные из регистра i + j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i + j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i + objI2C.writeByte(valAddress, arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i] + } // + // + private: // + /** Внутренние переменные **/ // + iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C + uint8_t valAddress = 0x68; // Адрес модуля на шине I2C + uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели) + uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и») + uint8_t varI; // +}; // + // +#endif // \ No newline at end of file diff --git a/lib/iarduino_RTC/src/iarduino_RTC_DS3231.h b/lib/iarduino_RTC/src/iarduino_RTC_DS3231.h new file mode 100644 index 00000000..fd8a4618 --- /dev/null +++ b/lib/iarduino_RTC/src/iarduino_RTC_DS3231.h @@ -0,0 +1,42 @@ +#ifndef iarduino_RTC_DS3231_h // +#define iarduino_RTC_DS3231_h // +#define RTC_DS3231 3 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 019x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором +#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C + // +class iarduino_RTC_DS3231: public iarduino_RTC_BASE{ // + public: // + /** функции доступные пользователю **/ // +// Инициализация модуля: // + void begin(void){ // (без параметров) +// Инициализация работы с шиной I2C: // + objI2C.begin(100); // (скорость шины в кГц) +// Установка флагов управления и состояния модуля: // + varI=objI2C.readByte(valAddress, 0x02); if( varI & 0b01000000 ){objI2C.writeByte(valAddress, 0x02, (varI&~0b01000000) );} // (если установлен 6 бит в 2 регистре, то сбрасываем его - переводим модуль в 24 часовой режим) + varI=objI2C.readByte(valAddress, 0x0E); if( varI & 0b11011111 ){objI2C.writeByte(valAddress, 0x0E, (varI&~0b11011111) );} // (если установлены 7,6,4,3,2,1 и 0 биты в 14 регистре, то сбрасываем их - разрешаем генератору работать от батарейки, запрещаем выводу SQW работать от батарейки, выводим меандр с частотой 1Гц на вывод SQW, переводим вывод INT/SQW в режим SQW, запрещаем прерывания будильников) + varI=objI2C.readByte(valAddress, 0x0F); if((varI & 0b10000011) || !(varI & 0b00001000)){objI2C.writeByte(valAddress, 0x0F, (varI&~0b10000011)|0b00001000 );} // (если установлены 7,1 и 0 биты или сброшен 3 бит в 15 регистре, то сбрасываем 7,1 и 0 биты, а 3 устанавливаем - сбрасываем флаг остановки генератора, разрешаем меандр с частотой 32768Гц на выводе 32kHz, сбрасываем флаги будильников) + } // + // +// Чтение одного значения из регистров даты и времени модуля: // + uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели) + delay(1); // + return objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; // + } // + // +// Запись одного значения в регистры даты и времени модуля: // + void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение) + varI=funcReadTimeIndex(i); // Читаем данные из регистра i + j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i + j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i + objI2C.writeByte(valAddress, arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i] + } // + // + private: // + /** Внутренние переменные **/ // + iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C + uint8_t valAddress = 0x68; // Адрес модуля на шине I2C + uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели) + uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и») + uint8_t varI; // +}; // + // +#endif // \ No newline at end of file diff --git a/lib/iarduino_RTC/src/iarduino_RTC_I2C.h b/lib/iarduino_RTC/src/iarduino_RTC_I2C.h new file mode 100644 index 00000000..1f7cf17e --- /dev/null +++ b/lib/iarduino_RTC/src/iarduino_RTC_I2C.h @@ -0,0 +1,461 @@ +#ifndef iarduino_I2C_h // Разрешаем включить данный код в скетч, только если он не был включён ранее +#define iarduino_I2C_h // Запрещаем повторное включение данного кода в скетч + // +// Определяем тип реализации шины I2C: // + #define iarduino_I2C_SW // Объявляем константу iarduino_I2C_SW - Возможна программная реализация шины I2C. +#if (!defined(pin_SW_SDA) || !defined(pin_SW_SCL)) // Если выводы не определены пользователем, то ... + #undef iarduino_I2C_SW // Отменяем объявление константы iarduino_I2C_SW - Программная реализация шины I2C не возможна (так как выводы не указаны). + #if defined(ESP8266) || defined(ESP32) // Если используются указанные платы, то ... + #include // Подключаем библиотеку Wire. + #define pin_SW_SDA 255 // № вывода SDA не определён + #define pin_SW_SCL 255 // № вывода SCL не определён + #define iarduino_I2C_TW // Объявляем константу iarduino_I2C_TW - Будет использована аппаратная реализация шины I2C под управлением библиотеки Wire. + #elif defined(TwoWire_h) // Проверяем не подключена ли библиотека Wire. + #define pin_SW_SDA 255 // № вывода SDA не определён + #define pin_SW_SCL 255 // № вывода SCL не определён + #define iarduino_I2C_TW // Объявляем константу iarduino_I2C_TW - Будет использована аппаратная реализация шины I2C под управлением библиотеки Wire. + #elif (defined(SDA) && defined(SCL)) // Определяем выводы для шины I2C + #define pin_SW_SDA SDA // № вывода SDA = SDA + #define pin_SW_SCL SCL // № вывода SCL = SCL + #define iarduino_I2C_HW // Объявляем константу iarduino_I2C_HW - Будет использована аппаратная реализация шины I2C. + #elif (defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)) // Определяем выводы для шины I2C + #define pin_SW_SDA PIN_WIRE_SDA // № вывода SDA = PIN_WIRE_SDA + #define pin_SW_SCL PIN_WIRE_SCL // № вывода SCL = PIN_WIRE_SCL + #define iarduino_I2C_HW // Объявляем константу iarduino_I2C_HW - Будет использована аппаратная реализация шины I2C. + #elif (defined(SDA1) && defined(SCL1)) // Определяем выводы для шины I2C-1 + #define pin_SW_SDA SDA1 // № вывода SDA = SDA1 + #define pin_SW_SCL SCL1 // № вывода SCL = SCL1 + #define iarduino_I2C_HW_1 // Объявляем константу iarduino_I2C_HW_1 - Будет использована аппаратная реализация шины I2C-1. + #else // Если выводы определить не удалось, то ... + #define pin_SW_SDA 255 // № вывода SDA не определён - Аппаратная реализация шины I2C не возможна. + #define pin_SW_SCL 255 // № вывода SCL не определён - Аппаратная реализация шины I2C не возможна. + #endif // +#endif // + // +class iarduino_I2C_BASE{ // Определяем полиморфный класс + public: // Доступные методы и функции: +// ОСНОВНЫЕ ФУНКЦИИ: (поддерживаются библиотекой Wire) // + virtual void begin (uint32_t); // Объявляем функцию указания скорости шины I2C. Аргументы: скорость в кГц. + virtual uint8_t readByte (uint8_t, uint8_t ); // Объявляем функцию чтения байта данных из регистра модуля. Аргументы: адрес_модуля, адрес_регистра. (адрес регистра указывает модулю, данные какого регистра требуется отправить мастеру) + virtual bool writeByte (uint8_t, uint8_t, uint8_t); // Объявляем функцию записи байта данных в регистр модуля. Аргументы: адрес_модуля, адрес_регистра, байт_данных. (адрес регистра указывает модулю, в какой регистр требуется сохранить данные) + virtual uint8_t readByte (uint8_t ); // Объявляем функцию чтения байта данных из модуля. Аргументы: адрес_модуля (функция отличается тем, что она не отправляет модулю адрес регистра) + virtual bool writeByte (uint8_t, uint8_t); // Объявляем функцию записи байта данных в модуль. Аргументы: адрес_модуля, байт_данных. (функция отличается тем, что она не отправляет модулю адрес регистра) + virtual bool readBytes (uint8_t, uint8_t, uint8_t*, uint8_t); // Объявляем функцию чтения байтов данных из регистров модуля. Аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт. (адрес первого регистра указывает модулю, с какого регистра требуется начать передачу данных мастеру) + virtual bool writeBytes (uint8_t, uint8_t, uint8_t*, uint8_t); // Объявляем функцию записи байтов данных в регистры модуля. Аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт. (адрес первого регистра указывает модулю, начиная с какого регистра требуется сохранять данные) + virtual bool readBytes (uint8_t, uint8_t*, uint8_t); // Объявляем функцию чтения байтов данных из модуля. Аргументы: адрес_модуля, указатель_на_массив, количество_байт. (функция отличается тем, что она не отправляет модулю адрес первого регистра, а начинает цикл чтения сразу после отправки адреса модуля.) + virtual bool writeBytes (uint8_t, uint8_t*, uint8_t); // Объявляем функцию записи байтов данных в модуль. Аргументы: адрес_модуля, указатель_на_массив, количество_байт. (функция отличается тем, что после отправки адреса модуля она сразу начинает цикл отправки данных, без передачи адреса первого регистра.) +// ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: (поддерживаются библиотекой Wire) // + virtual uint8_t getType (void); // Объявляем функцию получения типа реализации шины I2C. Аргументы: отсутствуют. + virtual bool checkAddress(uint8_t); // Объявляем функцию поиска модуля на шине I2C. Аргументы: адрес_модуля. +// ФУНКЦИИ НИЖНЕГО УРОВНЯ: (не поддерживаются библиотекой Wire) // + virtual bool start (void); // Объявляем функцию установки состояния START. Аргументы: отсутствуют. + virtual bool reStart (void); // Объявляем функцию установки состояния RESTART. Аргументы: отсутствуют. + virtual void stop (void); // Объявляем функцию установки состояния STOP. Аргументы: отсутствуют. + virtual bool sendID (uint8_t, bool); // Объявляем функцию передачи адреса модуля. Аргументы: ID-адрес модуля, бит RW (0-запись, 1-чтение). + virtual bool setByte (uint8_t); // Объявляем функцию передачи байта данных. Аргументы: байт для передачи. + virtual uint8_t getByte (bool); // Объявляем функцию получения байта данных. Аргументы: бит подтверждения ACK/NACK + private: // + virtual bool setSCL (bool); // Объявляем функцию установки уровня на линии SCL. Аргументы: логический уровень. + virtual void setSDA (bool); // Объявляем функцию установки уровня на линии SDA. Аргументы: логический уровень. + virtual bool getSDA (void); // Объявляем функцию чтения уровня с линии SDA. Аргументы: отсутствуют. +}; // + // +class iarduino_I2C: public iarduino_I2C_BASE{ // Определяем производный класс + public: // Доступные методы и функции: + // + /** ОСНОВНЫЕ ФУНКЦИИ: **/ // + // +// Функция подготовки шины I2C: // Определяем функцию подготовки шины I2C. + void begin(uint32_t speed){ // Аргумент: скорость шины в кГц. +// _ _ _ _______ _ _ _ // +// SCL: _?_?_/ OUTPUT // +// _ _ _ _ _____ _ _ _ // +// SDA: _?_?_ _/ OUTPUT // +// // + #if defined(iarduino_I2C_TW) // + // Если используется шина I2C под управлением библиотеки Wire: // + Wire.setClock(speed*1000L); // Устанавливаем скорость передачи данных по шине I2C. + Wire.begin(); // Инициируем работу на шине I2C в качестве мастера. + #elif defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + pinMode(pin_SDA, INPUT ); digitalWrite(pin_SDA, HIGH); // Определяем вывод pin_SDA как вход и подтягиваем его к Vcc. + pinMode(pin_SCL, INPUT ); digitalWrite(pin_SCL, HIGH); // Определяем вывод pin_SCL как вход и подтягиваем его к Vcc. + TWBR=((F_CPU/(speed*1000L))-16)/2; // Определяем значение регистра скорости связи TWBR: speed = F_CPU / (16 + 2 * TWBR * 4^TWPS). Значит TWBR = (F_CPU/speed - 16) / (2 * 4^TWPS), но так как биты предделителя TWPS мы далее сбросим в 0, то формула упростится до: TWBR = (F_CPU/speed - 16) / 2. Так как speed указана в кГц, а F_CPU в Гц, то умножаем speed на 1000. + if(TWBR<10){TWBR=10;} // Если значение регистра скорости TWBR стало меньше 10 (параметр speed > 400 кГ) то оставляем значение этого регистра равным 10 иначе шина будет работать нестабильно. + TWSR&=(~(_BV(TWPS1)|_BV(TWPS0))); // Определяем значение регистра статуса TWSR: оставляем все его биты не тронутыми, кроме двух битов предделитея TWPS сбрасывая их в 0. + #elif defined(iarduino_I2C_SW) // + // Если используется программная шина I2C: // + port_SDA = digitalPinToPort (pin_SDA); // Определяем номер порта для вывода pin_SDA. + port_SCL = digitalPinToPort (pin_SCL); // Определяем номер порта для вывода pin_SCL. + mask_SDA = digitalPinToBitMask (pin_SDA); // Определяем маску для вывода pin_SDA. в переменной mask_SDA будет установлен только тот бит который соответствует позиции бита управления выводом pin_SDA. + mask_SCL = digitalPinToBitMask (pin_SCL); // Определяем маску для вывода pin_SCL. в переменной mask_SCL будет установлен только тот бит который соответствует позиции бита управления выводом pin_SCL. + mod_SDA = portModeRegister (port_SDA); // Определяем указатель на адрес регистра конфигурации направления работы выводов порта port_SDA. + mod_SCL = portModeRegister (port_SCL); // Определяем указатель на адрес регистра конфигурации направления работы выводов порта port_SCL. + inp_SDA = portInputRegister (port_SDA); // Определяем указатель на адрес регистра входных значений для управления портом port_SDA. + inp_SCL = portInputRegister (port_SCL); // Определяем указатель на адрес регистра входных значений для управления портом port_SCL. + out_SDA = portOutputRegister (port_SDA); // Определяем указатель на адрес регистра выходных значений для управления портом port_SDA. + out_SCL = portOutputRegister (port_SCL); // Определяем указатель на адрес регистра выходных значений для управления портом port_SCL. + setSCL(1); // Переводим вывод SCL в режим входа с подтяжкой к Vcc + setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc + #endif // + } // + // +// Функция чтения одного байта из регистра модуля: // + uint8_t readByte(uint8_t adr, uint8_t reg){ // Определяем функцию чтения одного байта данных из регистра модуля (аргументы: адрес_модуля, адрес_регистра) + uint8_t i=0; readBytes(adr, reg, &i, 1); return i; // Объявляем переменную i и указываем её ссылку для получения 1 байта из регистра reg модуля с адресом adr + } // + // +// Функция чтения одного байта из модуля: // + uint8_t readByte(uint8_t adr){ // Определяем функцию чтения одного байта данных из регистра модуля (аргументы: адрес_модуля) + uint8_t i=0; readBytes(adr, &i, 1); return i; // Объявляем переменную i и указываем её ссылку для получения 1 байта из модуля с адресом adr + } // + // +// Функция записи одного байта в регистр модуля: // + bool writeByte(uint8_t adr, uint8_t reg, uint8_t data){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_модуля, адрес_регистра, байт_данных) + return writeBytes(adr, reg, &data, 1); // Запысываем 1 байт по ссылке на переменную data в регистр reg модуля с адресом adr + } // + // +// Функция записи одного байта в модуль: // + bool writeByte(uint8_t adr, uint8_t data){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_модуля, байт_данных) + return writeBytes(adr, &data, 1); // Запысываем 1 байт по ссылке на переменную data в модуль с адресом adr + } // + // +// Функция пакетного чтения нескольких байт данных из регистров модуля: // + bool readBytes(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sum){ // Определяем функцию пакетного чтения нескольких байт данных из регистров модуля (аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт) + #if defined(iarduino_I2C_TW) // + // Если используется шина I2C под управлением библиотеки Wire: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это ответ по умолчанию. + Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся. + Wire.write(reg); // Определяем значение первого байта (reg - адреса регистра) который будет отправлен после байта адреса. Функция write() поместит указанный байт в буфер для передачи. + i=Wire.endTransmission(false); if(i){return 0;} // Выполняем инициированную ранее передачу данных (без установки состояния STOP). Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. + if(!Wire.requestFrom( adr, sum )) {return i;} // Читаем (запрашиваем) sum байт данных от устройства с адресом adr и битом RW=1 => чтение. Функция requestFrom() возвращает количество реально принятых байтов. Так как предыдущая функция не установила состояние STOP, то состояние START данной функции будет расценено как RESTART. + while(Wire.available() && i0){ *data=getByte(sum>1); // Получаем по одному байту из очередного регистра за каждый проход цикла while. Прочитанный байт записываются по указателю data. Аргумент функции getByte имеет значение true на всех проходах цикла кроме последнего + data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму прочитанных байт sum. + #if defined(iarduino_I2C_HW) // Проверить корректность чтения каждого байта можно только на аппаратном уровне + if (sum) { if(TWSR&0xF8!=0x50) { i=0;}} // Если после чтения очередного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x50 значит произошла ошибка при чтении + else { if(TWSR&0xF8!=0x58) { i=0;}} // Если после чтения последного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x58 значит произошла ошибка при чтении + #endif // + }}}}}} stop (); return i==5; // Отправляем команду STOP и возвращаем результат успешности чтения + #endif // + } // + // +// Функция пакетного чтения нескольких байт данных из модуля: // + bool readBytes(uint8_t adr, uint8_t *data, uint8_t sum){ // Определяем функцию пакетного чтения нескольких байт данных из модуля (аргументы: адрес_модуля, указатель_на_массив, количество_байт) + #if defined(iarduino_I2C_TW) // + // Если используется шина I2C под управлением библиотеки Wire: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это ответ по умолчанию. + if(!Wire.requestFrom( adr, sum )) {return i;} // Читаем (запрашиваем) sum байт данных от устройства с адресом adr и битом RW=1 => чтение. Функция requestFrom() возвращает количество реально принятых байтов. + while(Wire.available() && i0){ *data=getByte(sum>1); // Получаем по одному байту из очередного регистра за каждый проход цикла while. Прочитанный байт записываются по указателю data. Аргумент функции getByte имеет значение true на всех проходах цикла кроме последнего + data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму прочитанных байт sum. + #if defined(iarduino_I2C_HW) // Проверить корректность чтения каждого байта можно только на аппаратном уровне + if (sum) { if(TWSR&0xF8!=0x50) { i=0;}} // Если после чтения очередного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x50 значит произошла ошибка при чтении + else { if(TWSR&0xF8!=0x58) { i=0;}} // Если после чтения последного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x58 значит произошла ошибка при чтении + #endif // + }}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат успешности чтения + #endif // + } // + // +// Функция пакетной записи нескольких байт данных в регистр модуля: // + bool writeBytes(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sum){ // Определяем функцию пакетной записи нескольких байт данных в регистры модуля (аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт) + #if defined(iarduino_I2C_TW) // + // Если используется шина I2C под управлением библиотеки Wire: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи + Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся. + Wire.write(reg); // Определяем значение первого байта (reg - адреса регистра) который будет отправлен после байта адреса. Функция write() поместит указанный байт в буфер для передачи. + Wire.write(data, sum); // Определяем значения следующих байт (data - массив данных) который будет отправлен после байта регистра. Функция write() поместит sum элементов массива data в буфер для передачи. + i = Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу данных. Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true. + #else // + // Если шина управляется функциями нижнего уровня данного класса: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи + if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ... + if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ... + if ( setByte (reg) ) { i=3; // Если модуль ответил ACK на получение адреса регистра reg, то ... + while(sum>0){if(!setByte(*data )) { i=0;} // Передаём один байт из массива по указателю data в очередной регистр за каждый проход цикла while. Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum. + data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum. + }}}} stop (); return i==3; // Отправляем команду STOP и возвращаем результат записи. + #endif // + } // + // +// Функция пакетной записи нескольких байт данных в модуль: // + bool writeBytes(uint8_t adr, uint8_t *data, uint8_t sum){ // Определяем функцию пакетной записи нескольких байт данных в модуль (аргументы: адрес_модуля, указатель_на_массив, количество_байт) + #if defined(iarduino_I2C_TW) // + // Если используется шина I2C под управлением библиотеки Wire: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи + Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся. + Wire.write(data, sum); // Указываем массив данных который будет отправлен после байта адреса. Функция write() поместит sum элементов массива data в буфер для передачи. + i = Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу данных. Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true. + #else // + // Если шина управляется функциями нижнего уровня данного класса: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи + if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ... + if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ... + while(sum>0){if(!setByte(*data )) { i=0;} // Передаём один байт из массива по указателю data в очередной регистр за каждый проход цикла while. Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum. + data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum. + }}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат записи. + #endif // + } // + // + /** ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: **/ // + // +// Функция получения типа реализации шины I2C: // Определяем функцию получения типа шины Ш2С. + uint8_t getType(void){ // Аргументы: отсутсвуют. + #if defined(iarduino_I2C_TW) // + return 4; // Используется аппаратная реализация шины I2C под управлением библиотеки Wire. + #elif defined(iarduino_I2C_HW) // + return 3; // Используется аппаратная реализация шины I2C. + #elif defined(iarduino_I2C_HW_1) // + return 2; // Используется аппаратная реализация шины I2C-1. + #elif defined(iarduino_I2C_SW) // + return 1; // Используется программная реализация шины I2C. + #else // + return 0; // Тип реализации шины I2C не определён. + #endif // + } // + // +// Функция проверки наличия ведомого по его адресу: // + bool checkAddress(uint8_t adr){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_регистра, байт_данных) + #if defined(iarduino_I2C_TW) // + // Если используется шина I2C под управлением библиотеки Wire: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат проверки. + Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся. + i=Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу но без данных (отправится только START, байт адреса, STOP). Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true. + #else // + // Если шина управляется функциями нижнего уровня данного класса: // + uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи. + if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ... + if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ... + }} stop (); return i==2; // Отправляем команду STOP и возвращаем результат записи. + #endif // + } // + // + /** ФУНКЦИИ НИЖНЕГО УРОВНЯ: **/ // + // +// Функция нижнего уровня - установка состояния START: // Определяем функцию установки состояния START. + bool start(void){ // Аргументы: отсутствуют. +// _ _ _ _____:___ _ _ _ // +// SCL: : \___ _ _ _ _ _/ // +// _ _ _ _____: _ _ _ _ _ _ // Спад логического уровня на линии SDA с «1» в «0», при наличии уровня логической «1» на линии SCL +// SDA: :\______ _ _/_ _ _ _ _ _ // +// // + #if defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния start. + TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTA (бит условия START). + while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов. + if((TWSR & 0xF8)==0x08){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x08, значит состояние START установилось на шине I2C. + return false; // Если предыдущая строка не вернула true, значит состояние START не установилось на шине I2C, возвращаем false. + #elif defined(iarduino_I2C_SW) // + // Если используется программная шина I2C: // + bool i= setSCL(1); // Устанавливаем «1» на линии SCL. Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + setSDA(0); // Устанавливаем «0» на линии SDA + setSCL(0); // Устанавливаем «0» на линии SCL + return i; // Если счетчик i не дошел до 0 при ожидании «1» на линии SCL, то вернётся true. + #else // + // Если тип шины I2C не поддерживается или не определён: // + return false; // Возвращаем false. + #endif // + } // + // +// Функция нижнего уровня - установка состояния RESTART: // Определяем функцию установки состояния RESTART. + bool reStart(void){ // Аргументы: отсутствуют. +// _ _ _ ___:___ _ _ _ // +// SCL: \_ _ _ _ / : \___ _ _ _ _ _/ // +// _ _ _ _ _ ________: _ _ _ _ _ _ // Спад логического уровня на линии SDA с «1» в «0», при наличии уровня логической «1» на линии SCL +// SDA: _ _ _ _ _/ :\______ _ _/_ _ _ _ _ _ // Сигнал рестрат аналогичен сигналу старт и отличается лишь тем, что ему не предшествует сигнал STOP +// // + #if defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния RESTART. + TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTA (бит условия START). + while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов. + if((TWSR & 0xF8)==0x10){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x10, значит состояние RESTART установилось на шине I2C. + return false; // Если предыдущая строка не вернула true, значит состояние RESTART не установилось на шине I2C, возвращаем false. + #elif defined(iarduino_I2C_SW) // + // Если используется программная шина I2C: // + return start(); // Программная реализация состояния RESTART идентична программной реализации состояния START. + #else // + // Если тип шины I2C не поддерживается или не определён: // + return false; // Возвращаем false. + #endif // + } // + // +// Функция нижнего уровня - установка состояния STOP: // Определяем функцию установки состояния STOP. + void stop(void){ // Аргументы: отсутствуют. +// _ _ _ ___:____ _ _ _ // +// SCL: \_ _ _ _/ : // +// _ _ _ _ _ :____ _ _ _ // Подъём логического уровня на линии SDA с «0» в «1», при наличии уровня логической «1» на линии SCL +// SDA: _ _ _ _ _\______/: // +// // + #if defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния STOP + TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTO (бит условия STOP). + while((!(TWCR & _BV(TWSTO))) && i){i--;} // Ждём сброса бита условия стоп TWSTO в регистре управления TWCR, но не дольше чем i циклов + // if((TWSR & 0xF8)==0xA0){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0xA0, значит состояние STOP установилось на шине I2C. + delayMicroseconds(20); // Данная функция не возвращает результат, но в любом случае делаем задержку меджу завершением текущего пакета и возможным началом следующего + #elif defined(iarduino_I2C_SW) // + // Если используется программная шина I2C: // + setSDA(0); // Устанавливаем «0» на линии SDA + setSCL(1); // Устанавливаем «1» на линии SCL. Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + setSDA(1); // Устанавливаем «1» на линии SDA + #endif // + } // + // +// Функция нижнего уровня - передача первого байта АДРЕС+RW: // Определяем функцию передачи первого байта после cигнала START. Это байт адреса модуля с битом RW + bool sendID(uint8_t adr, bool rw){ // Аргументы: ID-адрес модуля, бит RW (0-запись, 1-чтение) +// 1 2 3 4 5 6 7 8 9 // +// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ // +// ________________________ // Передача 7-битного адреса и 1 бита RW. На 9 тактирубщем импульсе модуль отвечает ACK («0» - «я сдесь»), или NACK («1» - «нет») +// SDA: _ _ _ ___/________ADDRESS_______RW>----____ _ _ _ // +// вход // + #if defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания получения подтверждения от ведомого ввиде бита ACK. + TWDR = (adr<<1)+rw; // Определяем значение регистра данных TWDR: записываем в него адрес adr сдвигая его на 1 бит влево, при этом младший бит (освободившийся) займёт бит RW (0-запись / 1-чтение) + TWCR = _BV(TWINT) | _BV(TWEN); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины). + while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов + if((TWSR & 0xF8)==0x40 && rw){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x40, значит ведомый опознал свой адрес с битом RW=1 и отправил бит подтверждения ACK (в противном случае значение регистра TWSR будет равно 0x48). + if((TWSR & 0xF8)==0x18 && !rw){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x18, значит ведомый опознал свой адрес с битом RW=0 и отправил бит подтверждения ACK (в противном случае значение регистра TWSR будет равно 0x20). + return false; // Если предыдущая строка не вернула true, значит на шине нет ведомых у сказанным адресом, возвращаем false. + #elif defined(iarduino_I2C_SW) // + // Если используется программная шина I2C: // + bool i=true; // Определяем флаг возвращаемый данной функцией. + uint8_t j=7; // Определяем счётчик количества переданных бит адреса. + while(j){ j--; // Передаём 7 бит адреса adr в цикле + setSDA(adr & bit(j)); // Устанавливаем очередной бит адреса на линии SDA + if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) + } setSDA(rw); // Устанавливаем бит RW на линии SDA + if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) + setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc + if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + if( getSDA( ) ) {i=false;} // Если на линии SDA установлена «1» значит ведомый ответил NACK + setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) + return i; // Если линия SCL была занята или модуль ответил NACK, то вернётся false. + #else // + // Если тип шины I2C не поддерживается или не определён: // + return false; // Возвращаем false + #endif // + } // + // +// Функция нижнего уровня - передача одного байта данных: // Определяем функцию передачи одного байта (в любом месте между байтом адреса с битом RW=0 и сигналом STOP). + bool setByte(uint8_t data){ // Аргумент: байт для передачи. +// 1 2 3 4 5 6 7 8 9 // +// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ // +// ________________________ // Передача 1 байта, каждый бит читается модулем по фронту тактирубщих импульсов. На 9 тактирубщем импульсе модуль отвечает ACK («0» - «принял»), или NACK («1» - «нет») +// SDA: _ _ _ ___/__________DATA__________>----____ _ _ _ // +// вход // + #if defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания получения подтверждения от ведомого ввиде бита ACK. + TWDR = data; // Определяем значение регистра данных TWDR: записываем в него байт для передачи по шине I2C. + TWCR = _BV(TWINT) | _BV(TWEN); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины). + while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов + if((TWSR & 0xF8)==0x28){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x28, значит ведомый отправил бит подтверждения приёма данных ACK (в противном случае значение регистра TWSR будет равно 0x30). + return false; // Если предыдущая строка не вернула true, значит ведомый не принял отправленный ему байт, возвращаем false. + #elif defined(iarduino_I2C_SW) // + // Если используется программная шина I2C: // + bool i=true; // Определяем флаг возвращаемый данной функцией. + uint8_t j=8; // Определяем счётчик количества переданных байт. + while(j){ j--; // Передаём 8 бит байта data в цикле + setSDA(data & bit(j)); // Устанавливаем очередной бит байта на линии SDA + if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) + } setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc + if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false. + if( getSDA( ) ) {i=false;} // Если на линии SDA установлена «1» значит ведомый ответил NACK + setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) + return i; // Если счетчик i не дошел до 0 и не был сброшен в 0 при получении NACK, то вернётся true. + #else // + // Если тип шины I2C не поддерживается или не определён: // + return false; // Возвращаем false + #endif // + } // + // +// Функция нижнего уровня - получение одного байта данных: // Определяем функцию получения одного байта (в любом месте между байтом адреса с битом RW=1 и сигналом STOP). + uint8_t getByte(bool ack){ // Аргумент: бит подтверждения ACK/NACK +// 1 2 3 4 5 6 7 8 9 // +// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ // +// __ // Получение 1 байта, каждый бит читается мастером по фронту тактирубщих импульсов. На 9 тактирубщем импульсе мастер отвечает ACK («0» - «давай еще»), или NACK («1» - «хватит») +// SDA: _ _ _ ___/----------DATA-----------<__\____ _ _ _ // +// вход выход // + #if defined(iarduino_I2C_HW) // + // Если используется аппаратная шина I2C: // + uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания. + TWCR = _BV(TWINT) | _BV(TWEN) | ack<7) ){ j=1; } j=bit(j-1); } // Устанавливаем один бит в переменной j; + // if( i==6 ){j--;} // Если чип считает день недели как написано в datasheet, то раскомментируйте данную строку и закомментируйте предыдущую. + objI2C.writeByte(valAddress, arrTimeRegAddr[i], j&arrTimeRegMack[i]); // Сохраняем значение j в регистр arrTimeRegAddr[i] с маской arrTimeRegMack[i]. + } // + // + private: // + /** Внутренние переменные **/ // + iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C + uint8_t valAddress = 0x32; // Адрес модуля на шине I2C + uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели) + uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x7F}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и») + uint8_t varI; // +}; // + // +#endif // diff --git a/lib/iarduino_RTC/src/memorysaver.h b/lib/iarduino_RTC/src/memorysaver.h new file mode 100644 index 00000000..27cb6774 --- /dev/null +++ b/lib/iarduino_RTC/src/memorysaver.h @@ -0,0 +1,9 @@ +// Файл: «ХРАНИТЕЛЬ ПАМЯТИ» + +// Если закомментировать строки с названиями тех модулей которые не используются в Вашем устройстве, можно освободить около 50 байт флеш-памяти. +// Если закомментировать строку с названием используемого модуля, компилятор выдаст ошибку. + + #define RTC_ENABLE_DS1302 1 // Модуль часов реального времени (RTC) на базе чипа DS1302, с протоколом передачи данных SI3, памятью 040x8 (31 байт которой доступны для хранения данных пользователя). + #define RTC_ENABLE_DS1307 1 // Модуль часов реального времени (RTC) на базе чипа DS1307, с протоколом передачи данных I2C, памятью 064x8 (56 байт которой доступны для хранения данных пользователя). + #define RTC_ENABLE_DS3231 1 // Модуль часов реального времени (RTC) на базе чипа DS3231, с протоколом передачи данных I2C, памятью 019x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором. + #define RTC_ENABLE_RX8025 1 // Модуль часов реального времени (RTC) на базе чипа RX8025, с протоколом передачи данных I2C, памятью 016x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором. \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index d8dffba9..da9be68c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,9 +9,15 @@ board = nodemcuv2 board_build.ldscript = eagle.flash.4m1m.ld platform = espressif8266 @2.6.3 monitor_filters = esp8266_exception_decoder -upload_speed = 921600 +upload_speed = 115200 monitor_speed = 115200 board_build.filesystem = littlefs +build_src_filter = + +<*.cpp> + + + + + + + ${env:esp8266_4mb_fromitems.build_src_filter} [env:esp32_4mb] lib_deps = @@ -23,11 +29,17 @@ framework = arduino board = esp32dev platform = espressif32 @3.3.0 monitor_filters = esp32_exception_decoder -upload_speed = 921600 +upload_speed = 115200 monitor_speed = 115200 +build_src_filter = + +<*.cpp> + + + + + + + ${env:esp32_4mb_fromitems.build_src_filter} [platformio] -default_envs = esp8266_4mb +default_envs = esp32_4mb data_dir = data_svelte [common_env_data] @@ -38,8 +50,8 @@ lib_deps_external = [env:esp8266_4mb_fromitems] lib_deps = - adafruit/Adafruit MCP23017 Arduino Library@^2.0.2 - adafruit/Adafruit ADS1X15 @ ^2.3.0 + marcoschwartz/LiquidCrystal_I2C@^1.1.4 + dfrobot/DFRobotDFPlayerMini @ ^1.0.5 Adafruit AHTX0 adafruit/Adafruit BME280 Library adafruit/Adafruit BMP280 Library @@ -48,14 +60,39 @@ lib_deps = https://github.com/JonasGMorsch/GY-21.git ClosedCube HDC1080 adafruit/MAX6675 library - Nova Fitness Sds dust sensors library@1.5.1 + rc-switch @ ^2.6.4 robtillaart/SHT2x@^0.1.1 - marcoschwartz/LiquidCrystal_I2C@^1.1.4 + adafruit/Adafruit MCP23017 Arduino Library@^2.0.2 + adafruit/Adafruit BusIO @ ^1.13.0 +build_src_filter = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [env:esp32_4mb_fromitems] lib_deps = - adafruit/Adafruit MCP23017 Arduino Library@^2.0.2 - adafruit/Adafruit ADS1X15 @ ^2.3.0 + marcoschwartz/LiquidCrystal_I2C@^1.1.4 + https://github.com/RoboticsBrno/ServoESP32 + dfrobot/DFRobotDFPlayerMini @ ^1.0.5 Adafruit AHTX0 adafruit/Adafruit BME280 Library adafruit/Adafruit BMP280 Library @@ -64,7 +101,31 @@ lib_deps = https://github.com/JonasGMorsch/GY-21.git ClosedCube HDC1080 adafruit/MAX6675 library - Nova Fitness Sds dust sensors library@1.5.1 + rc-switch @ ^2.6.4 robtillaart/SHT2x@^0.1.1 - marcoschwartz/LiquidCrystal_I2C@^1.1.4 + adafruit/Adafruit MCP23017 Arduino Library@^2.0.2 + adafruit/Adafruit BusIO @ ^1.13.0 +build_src_filter = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/DeviceList.cpp b/src/DeviceList.cpp index 2fd5c732..2788afb7 100644 --- a/src/DeviceList.cpp +++ b/src/DeviceList.cpp @@ -54,7 +54,7 @@ void asyncUdpInit() { //будем отправлять каждые 30 секунд презентацию данного устройства ts.add( - UDP, 60000, [&](void*) { + UDP, 60000, [&](void*) { //UDPP if (isNetworkActive()) { SerialPrint("i", F("UDP"), F("Broadcast device presentation")); asyncUdp.broadcastTo(getThisDevice().c_str(), 4210); diff --git a/src/ESPConfiguration.cpp b/src/ESPConfiguration.cpp index de80d564..2c767798 100644 --- a/src/ESPConfiguration.cpp +++ b/src/ESPConfiguration.cpp @@ -1,7 +1,9 @@ #include "ESPConfiguration.h" #include "classes/IoTGpio.h" +#include "classes/IoTRTC.h" extern IoTGpio IoTgpio; +extern IoTRTC *watch; std::list IoTItems; void* getAPI(String subtype, String params); @@ -25,8 +27,22 @@ void configure(String path) { } else { myIoTItem = (IoTItem*)getAPI(subtype, jsonArrayElement); if (myIoTItem) { - IoTGpio* tmp = myIoTItem->getGpioDriver(); - if (tmp) IoTgpio.regDriver(tmp); + // пробуем спросить драйвер GPIO + IoTGpio* gpiotmp = myIoTItem->getGpioDriver(); + if (gpiotmp) IoTgpio.regDriver(gpiotmp); + + // пробуем спросить драйвер RTC + iarduino_RTC_BASE* rtctmp = myIoTItem->getRtcDriver(); + if (rtctmp) { + Serial.println("Start delete watch objClass"); + delete watch->objClass; + watch->objClass = rtctmp; + int valPeriod_save = watch->valPeriod; + watch->valPeriod = 0; + watch->gettime(); + watch->valPeriod = valPeriod_save; + } + IoTItems.push_back(myIoTItem); } } @@ -39,6 +55,7 @@ void configure(String path) { void clearConfigure() { Serial.printf("Start clearing config\n"); for (std::list::iterator it=IoTItems.begin(); it != IoTItems.end(); ++it) { + Serial.printf("Start delete iotitem %s \n", (*it)->getID().c_str()); if (*it) delete *it; } IoTItems.clear(); diff --git a/src/EventsAndOrders.cpp b/src/EventsAndOrders.cpp index 5f699b38..61436c4d 100644 --- a/src/EventsAndOrders.cpp +++ b/src/EventsAndOrders.cpp @@ -29,12 +29,7 @@ void handleOrder() { IoTItem* item = findIoTItem(selectToMarker(order, " ")); if (item) { String valStr = selectToMarkerLast(order, " "); - IoTValue value; - if (value.isDecimal = isDigitDotCommaStr(valStr)) - value.valD = valStr.toFloat(); - else - value.valS = valStr; - item->setValue(value); + item->setValue(valStr); } orderBuf = deleteBeforeDelimiter(orderBuf, ","); diff --git a/src/Main.cpp b/src/Main.cpp index 7c3ba04a..01b5d131 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,7 +1,16 @@ #include "Main.h" +#include "classes/IoTRTC.h" +#include IoTScenario iotScen; // объект управления сценарием +IoTRTC *watch; // объект хранения времени, при старте часы 00:00 +time_t iotTimeNow; + +String volStrForSave = ""; +unsigned long currentMillis; +unsigned long prevMillis; + void setup() { Serial.begin(115200); Serial.flush(); @@ -23,6 +32,29 @@ void setup() { //подключаемся к роутеру routerConnect(); + // настраиваем получение времени из сети Интернет + String ntpServer = jsonReadStr(settingsFlashJson, F("ntp")); + int timezone = jsonReadInt(settingsFlashJson, F("timezone")); + configTime(3600*timezone, 0, ntpServer.c_str(), "ru.pool.ntp.org", "pool.ntp.org"); + Serial.println("Start syncing NTP time"); + time(&iotTimeNow); + // int i = 0; + // while (isNetworkActive() && iotTimeNow < 1510592825 && i < 200) + // { + // time(&iotTimeNow); + // delay(300); + // Serial.print("."); + // i++; + // } + // Serial.println(); + + // настраиваем локальный RTC + watch = new IoTRTC(0); // создаем объект главного хранилища времени, но с заглушкой (0) для получения системного времени + watch->period(60); // время в минутах для синхронизации с часами реального времени или системным + watch->begin(); + //Serial.print(F("Time from Local: ")); + //Serial.println(watch->gettime("d-m-Y, H:i:s, M")); + //инициализация асинхронного веб сервера и веб сокетов #ifdef ASYNC_WEB_SERVER asyncWebServerInit(); @@ -56,7 +88,9 @@ void setup() { //загрузка сценария iotScen.loadScenario("/scenario.txt"); - // iotScen.ExecScenario(""); + // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке + IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); + generateEvent("onStart", ""); // test Serial.println("-------test start--------"); @@ -83,6 +117,13 @@ void setup() { } void loop() { + // if(millis()%2000==0){ + // //watch->settimeUnix(time(&iotTimeNow)); + // Serial.println(watch->gettime("d-m-Y, H:i:s, M")); + // delay(1); + // } + + //обновление задач таскера ts.update(); @@ -118,5 +159,24 @@ void loop() { handleEvent(); - // iotScen.ExecScenario(); + // сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение) + currentMillis = millis(); + if (currentMillis - prevMillis >= 1000) { + prevMillis = millis(); + volStrForSave = ""; + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + if ((*it)->needSave) { + (*it)->needSave = false; + volStrForSave = volStrForSave + (*it)->getID() + "=" + (*it)->getValue() + ";"; + } + } + + if (volStrForSave != "") { + Serial.print("volStrForSave: "); + Serial.println(volStrForSave.c_str()); + } + } + + + } diff --git a/src/MqttClient.cpp b/src/MqttClient.cpp index 805393d0..955033b7 100644 --- a/src/MqttClient.cpp +++ b/src/MqttClient.cpp @@ -125,7 +125,9 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) { payloadStr += (char)payload[i]; } - // SerialPrint("i", "=>MQTT", payloadStr); + //SerialPrint("i", "=>MQTT", payloadStr); + + //SerialPrint("i", F("=>MQTT"), "Msg from iotmanager: " + topicStr); if (payloadStr.startsWith("HELLO")) { SerialPrint("i", F("MQTT"), F("Full update")); @@ -153,8 +155,19 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) { if (topicStr.indexOf(chipId) == -1) { String devId = selectFromMarkerToMarker(topicStr, "/", 2); String id = selectFromMarkerToMarker(topicStr, "/", 3); - //добавим событие в базу - IoTItems.push_back((IoTItem*)new externalVariable(payloadStr)); + IoTItem* itemExist = findIoTItem(id); + if (itemExist) { + String valAsStr; + if (jsonRead(payloadStr, F("val"), valAsStr, false)) { + itemExist->setValue(valAsStr); + unsigned long interval; + jsonRead(payloadStr, F("int"), interval); + itemExist->setInterval(interval); + } + } else { + //добавим событие в базу + IoTItems.push_back((IoTItem*)new externalVariable(payloadStr)); + } //запустим проверку его в сценариях generateEvent(id, payloadStr); SerialPrint("i", F("=>MQTT"), "Received event from other device: '" + devId + "' " + id + " " + payloadStr); diff --git a/src/StandWebServer.cpp b/src/StandWebServer.cpp index 48192ec4..2445c9a1 100644 --- a/src/StandWebServer.cpp +++ b/src/StandWebServer.cpp @@ -48,36 +48,53 @@ void standWebServerInit() { // Запускаем HTTP сервер HTTP.begin(); -#ifdef REST_FILE_OPERATIONS - SPIFFS.begin(); - { - Dir dir = SPIFFS.openDir("/"); - while (dir.next()) { - String fileName = dir.fileName(); - size_t fileSize = dir.fileSize(); - } - } +//#ifdef REST_FILE_OPERATIONS + // SPIFFS.begin(); + // { + // Dir dir = SPIFFS.openDir("/"); + // while (dir.next()) { + // String fileName = dir.fileName(); + // size_t fileSize = dir.fileSize(); + // } + // } // HTTP страницы для работы с FFS + // list directory HTTP.on("/list", HTTP_GET, handleFileList); + //загрузка редактора editor HTTP.on("/edit", HTTP_GET, []() { - if (!handleFileRead("/edit.htm")) HTTP.send(404, "text/plain", "FileNotFound"); + if (!HTTP.args()) { + if (!handleFileRead("/edit.htm")) HTTP.send(404, "text/plain", "FileNotFound"); + } + + if (HTTP.hasArg("list")) { + handleFileList(); + } + + if (HTTP.hasArg("edit")) { + if (!handleFileRead(HTTP.arg("edit"))) HTTP.send(404, "text/plain", "FileNotFound"); + } + + if (HTTP.hasArg("download")) { + if (!handleFileRead(HTTP.arg("download"))) HTTP.send(404, "text/plain", "FileNotFound"); + } }); + //Создание файла HTTP.on("/edit", HTTP_PUT, handleFileCreate); + //Удаление файла HTTP.on("/edit", HTTP_DELETE, handleFileDelete); - // first callback is called after the request has ended with all parsed arguments - // second callback handles file uploads at that location - HTTP.on( - "/edit", HTTP_POST, []() { + + //Изменение файла + HTTP.on("/edit", HTTP_POST, []() { HTTP.send(200, "text/plain", ""); }, handleFileUpload); -#endif +//#endif + // called when the url is not defined here - // use it to load content from SPIFFS HTTP.onNotFound([]() { if (!handleFileRead(HTTP.uri())) HTTP.send(404, "text/plain", "FileNotFound"); @@ -92,6 +109,8 @@ bool handleFileRead(String path) { if (FileFS.exists(pathWithGz)) path += ".gz"; File file = FileFS.open(path, "r"); + if (contentType == "application/octet-stream") + HTTP.sendHeader("Content-Disposition", "attachment;filename=" + (String)file.name()); HTTP.streamFile(file, contentType); file.close(); return true; @@ -131,7 +150,7 @@ String getContentType(String filename) { return "text/plain"; } -#ifdef REST_FILE_OPERATIONS +//#ifdef REST_FILE_OPERATIONS // Здесь функции для работы с файловой системой void handleFileUpload() { if (HTTP.uri() != "/edit") return; @@ -181,27 +200,25 @@ void handleFileCreate() { } void handleFileList() { - if (!HTTP.hasArg("dir")) { + if (!HTTP.hasArg("list")) { HTTP.send(500, "text/plain", "BAD ARGS"); return; } - String path = HTTP.arg("dir"); - Dir dir = FileFS.openDir(path); - path = String(); + File dir = FileFS.open(HTTP.arg("list"), "r"); String output = "["; - while (dir.next()) { - File entry = dir.openFile("r"); + File entry; + while (entry = dir.openNextFile()) { if (output != "[") output += ','; - bool isDir = false; + bool isDir = entry.isDirectory(); output += "{\"type\":\""; output += (isDir) ? "dir" : "file"; output += "\",\"name\":\""; - output += String(entry.name()).substring(1); + output += String(entry.name()); output += "\"}"; entry.close(); } output += "]"; HTTP.send(200, "text/json", output); } -#endif +//#endif #endif diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 818c15c0..4c8adb35 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -1,4 +1,7 @@ #include "WsServer.h" +#include "classes/IoTScenario.h" +extern IoTScenario iotScen; + #ifdef STANDARD_WEB_SOCKETS void standWebSocketsInit() { standWebSocket.begin(); @@ -66,8 +69,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) //**сохранение**// if (headerStr == "/gifnoc|") { writeFileUint8tByFrames("config.json", payload, length, headerLenth, 256); - // clearConfigure(); - // configure("/config.json"); + Serial.println("Start clear"); + clearConfigure(); + Serial.println("Start config"); + configure("/config.json"); + iotScen.loadScenario("/scenario.txt"); } //**сохранение**// if (headerStr == "/tuoyal|") { @@ -76,6 +82,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) //**сохранение**// if (headerStr == "/oiranecs|") { writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth, 256); + iotScen.loadScenario("/scenario.txt"); + + // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке + IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); + generateEvent("onStart", ""); } // page connection=================================================================== //**отправка**// diff --git a/src/classes/IoTItem.cpp b/src/classes/IoTItem.cpp index 7813a956..aa937cd0 100644 --- a/src/classes/IoTItem.cpp +++ b/src/classes/IoTItem.cpp @@ -1,6 +1,5 @@ #include "utils/JsonUtils.h" #include "utils/SerialPrint.h" -#include "classes/ScenarioClass3.h" #include "classes/IoTItem.h" #include "WsServer.h" #include "ESPConfiguration.h" @@ -8,6 +7,7 @@ IoTItem::IoTItem(String parameters) { jsonRead(parameters, F("int"), _interval); + if (_interval == 0) enableDoByInt = false; _interval = _interval * 1000; jsonRead(parameters, F("subtype"), _subtype); jsonRead(parameters, F("id"), _id); @@ -42,10 +42,14 @@ String IoTItem::getID() { return _id; }; +void IoTItem::setInterval(unsigned long interval) { + _interval = interval; +} + String IoTItem::getValue() { if (value.isDecimal) - if (_round >= 0) { - char buf[8]; + if (_round >= 0 && _round <= 6) { + char buf[15]; sprintf(buf, ("%1." + (String)_round + "f").c_str(), value.valD); return (String)buf; } else return (String)value.valD; @@ -54,11 +58,13 @@ String IoTItem::getValue() { } void IoTItem::loop() { - currentMillis = millis(); - difference = currentMillis - prevMillis; - if (difference >= _interval) { - prevMillis = millis(); - this->doByInterval(); + if (enableDoByInt) { + currentMillis = millis(); + difference = currentMillis - prevMillis; + if (difference >= _interval) { + prevMillis = millis(); + this->doByInterval(); + } } } @@ -81,7 +87,7 @@ void IoTItem::regEvent(String value, String consoleInfo = "") { void IoTItem::regEvent(float regvalue, String consoleInfo = "") { if (_multiply) regvalue = regvalue * _multiply; - if (_plus) regvalue = regvalue + _multiply; + if (_plus) regvalue = regvalue + _plus; if (_round >= 0 && _round <= 6) { int sot = _round ? pow(10, (int)_round) : 1; regvalue = round(regvalue * sot) / sot; @@ -101,6 +107,10 @@ IoTGpio* IoTItem::getGpioDriver() { return nullptr; } +iarduino_RTC_BASE* IoTItem::getRtcDriver() { + return nullptr; +} + void IoTItem::setValue(IoTValue Value) { value = Value; if (value.isDecimal) @@ -109,6 +119,15 @@ void IoTItem::setValue(IoTValue Value) { regEvent(value.valS, ""); } +void IoTItem::setValue(String valStr) { + if (value.isDecimal = isDigitDotCommaStr(valStr)) { + value.valD = valStr.toFloat(); + } else { + value.valS = valStr; + } + setValue(value); +} + externalVariable::externalVariable(String parameters) : IoTItem(parameters) { prevMillis = millis(); // запоминаем текущее значение таймера для выполения doByInterval после int сек iAmLocal = false; // указываем, что это сущность прилетела из сети diff --git a/src/classes/IoTRTC.cpp b/src/classes/IoTRTC.cpp new file mode 100644 index 00000000..94b6c741 --- /dev/null +++ b/src/classes/IoTRTC.cpp @@ -0,0 +1,46 @@ +#include "classes/IoTRTC.h" + +IoTRTC::~IoTRTC() { + +} + + +iarduino_RTC_NTP::iarduino_RTC_NTP() { + +} + +void iarduino_RTC_NTP::begin(void) { + +} + +uint8_t iarduino_RTC_NTP::funcReadTimeIndex(uint8_t i) { + static tm localTimeVar; + if (i == 0) { + Serial.println(F("Read time from system.")); + time_t timeNowVar; + time(&timeNowVar); + localTimeVar = *localtime(&timeNowVar); + } + + switch (i) + { + case 0: return funcConvertNumToCode(localTimeVar.tm_sec); + case 1: return funcConvertNumToCode(localTimeVar.tm_min); + case 2: return funcConvertNumToCode(localTimeVar.tm_hour); + case 3: return funcConvertNumToCode(localTimeVar.tm_mday); + case 4: return funcConvertNumToCode(localTimeVar.tm_mon+1); + case 5: return funcConvertNumToCode(localTimeVar.tm_year-100); + case 6: return funcConvertNumToCode(localTimeVar.tm_wday); + } + + return 0; +} + +void iarduino_RTC_NTP::funcWriteTimeIndex(uint8_t i, uint8_t j) { + +} + +iarduino_RTC_NTP::~iarduino_RTC_NTP() { + +} + diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index f446d6ef..65c6baf9 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -44,7 +44,7 @@ public: IoTValue* exec() { if (isIotScenException) return nullptr; - Serial.printf("Call from NumberExprAST: %f\n", Val.valD); + //Serial.printf("Call from NumberExprAST: %f\n", Val.valD); return &Val; } }; @@ -57,7 +57,7 @@ public: IoTValue* exec() { if (isIotScenException) return nullptr; - Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str()); + //Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str()); return &Val; } }; @@ -85,9 +85,9 @@ public: if (isIotScenException) return nullptr; if (!ItemIsLocal) Item = findIoTItem(Name); if (Item) { - if (Item->value.isDecimal) - Serial.printf("Call from VariableExprAST: %s = %f\n", Name.c_str(), Item->value.valD); - else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str()); + //if (Item->value.isDecimal) + // Serial.printf("Call from VariableExprAST: %s = %f\n", Name.c_str(), Item->value.valD); + //else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str()); return &(Item->value); } @@ -100,6 +100,7 @@ class BinaryExprAST : public ExprAST { signed char Op; ExprAST *LHS, *RHS; IoTValue val; + String lhsStr, rhsStr; public: BinaryExprAST(signed char op, ExprAST *lhs, ExprAST *rhs) @@ -108,7 +109,7 @@ public: ~BinaryExprAST() { if (LHS) delete LHS; if (RHS) delete RHS; - Serial.printf("Call from BinaryExprAST delete\n"); + //Serial.printf("Call from BinaryExprAST delete\n"); } IoTValue* exec(){ @@ -121,7 +122,7 @@ public: else if (Op == tok_greateq) printStr = ">="; else printStr = printStr + (char)Op; - Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str()); + //Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str()); if (RHS == nullptr || LHS == nullptr) return nullptr; @@ -182,10 +183,18 @@ public: return &val; } - if (!lhs->isDecimal && !rhs->isDecimal) { + if (!lhs->isDecimal || !rhs->isDecimal) { + if (lhs->isDecimal) lhsStr = lhs->valD; else lhsStr = lhs->valS; + if (rhs->isDecimal) rhsStr = rhs->valD; else rhsStr = rhs->valS; switch (Op) { case tok_equal: - val.valD = lhs->valS == rhs->valS; + val.valD = compStr(lhsStr, rhsStr); + break; + + case '+': + val.valS = lhsStr + rhsStr; + val.valD = 1; + val.isDecimal = false; break; default: @@ -194,8 +203,19 @@ public: return &val; } } - return nullptr; + return &val; } + + bool compStr(String str1, String str2){ + if (str1.length() != str2.length()) return false; + for (int i = 0; i < str1.length(); i++) { + if (str1[i] == '*' || str2[i] == '*') continue; //считаем, что если есть подстановочная звезда, то символы равны + if (str1[i] != str2[i]) return false; + } + + return true;//str1 == str2; + } + }; /// CallExprAST - Класс узла выражения для вызова команды. @@ -240,8 +260,8 @@ public: ret = Item->execute(Cmd, ArgsAsIoTValue); // вызываем команду из модуля напрямую с передачей всех аргументов - if (ret.isDecimal) Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %f\n", Callee.c_str(), Cmd.c_str(), ret.valD); - else Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %s\n", Callee.c_str(), Cmd.c_str(), ret.valS.c_str()); + //if (ret.isDecimal) Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %f\n", Callee.c_str(), Cmd.c_str(), ret.valD); + //else Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %s\n", Callee.c_str(), Cmd.c_str(), ret.valS.c_str()); return &ret; } @@ -250,7 +270,7 @@ public: if (Args[i]) delete Args[i]; } Args.clear(); - Serial.printf("Call from CallExprAST delete\n"); + //Serial.printf("Call from CallExprAST delete\n"); } }; @@ -268,8 +288,8 @@ public: } bool hasEventIdName(String eventIdName) { - Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str()); - return _IDNames.indexOf(eventIdName) >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF + //Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str()); + return _IDNames.indexOf(" " + eventIdName + " ") >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF } IoTValue* exec() { @@ -280,7 +300,7 @@ public: if (Cond) cond_ret = Cond->exec(); if (!cond_ret) { - Serial.printf("Call from IfExprAST: Skip If\n"); + //Serial.printf("Call from IfExprAST: Skip If\n"); return nullptr; //&zeroIotVal; } @@ -292,9 +312,9 @@ public: res_ret = Else->exec(); } - if (!res_ret) Serial.printf("Call from IfExprAST: Cond result = %f, no body result\n", cond_ret->valD); - else if (res_ret->isDecimal) Serial.printf("Call from IfExprAST: Cond result = %f, result = %f\n", cond_ret->valD, res_ret->valD); - else Serial.printf("Call from IfExprAST: Cond result = %f, result = %s\n", cond_ret->valD, res_ret->valS.c_str()); + //if (!res_ret) Serial.printf("Call from IfExprAST: Cond result = %f, no body result\n", cond_ret->valD); + //else if (res_ret->isDecimal) Serial.printf("Call from IfExprAST: Cond result = %f, result = %f\n", cond_ret->valD, res_ret->valD); + //else Serial.printf("Call from IfExprAST: Cond result = %f, result = %s\n", cond_ret->valD, res_ret->valS.c_str()); Serial.printf("\n"); return cond_ret; } @@ -303,7 +323,7 @@ public: if (Cond) delete Cond; if (Then) delete Then; if (Else) delete Else; - Serial.printf("Call from IfExprAST delete\n"); + //Serial.printf("Call from IfExprAST delete\n"); } }; @@ -317,7 +337,7 @@ public: IoTValue* exec() { if (isIotScenException) return nullptr; - Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size()); + //Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size()); IoTValue* lastExecValue = nullptr; for (unsigned int i = 0; i < BracketsList.size(); i++) { @@ -334,7 +354,7 @@ public: } BracketsList.clear(); - Serial.printf("Call from BracketsExprAST delete\n"); + //Serial.printf("Call from BracketsExprAST delete\n"); } }; @@ -356,9 +376,9 @@ public: while (isspace(LastChar)) LastChar = getLastChar(); - if (isalpha(LastChar)) { // идентификатор: [a-zA-Z][a-zA-Z0-9]* + if (isalpha(LastChar) || LastChar == '_') { // идентификатор: [a-zA-Z][a-zA-Z0-9]* IdentifierStr = LastChar; - while (isalnum((LastChar = getLastChar()))){ + while (isalnum((LastChar = getLastChar())) || LastChar == '_'){ IdentifierStr += LastChar; } @@ -609,7 +629,7 @@ public: case tok_identifier: { if (IDNames) { String tmpstr = *IDNames; - *IDNames = tmpstr + " " + IdentifierStr; + *IDNames = tmpstr + " " + IdentifierStr + " "; } return ParseIdentifierExpr(IDNames); } @@ -707,7 +727,7 @@ public: Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); for (unsigned int i = 0; i < ScenarioElements.size(); i++) { if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec(); - else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); + //else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); if (isIotScenException) return; } } diff --git a/src/classes/ScenarioClass3.cpp b/src/classes/ScenarioClass3.cpp deleted file mode 100644 index a630a635..00000000 --- a/src/classes/ScenarioClass3.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "classes/ScenarioClass3.h" - -Scenario* myScenario; diff --git a/src/modules/API.cpp b/src/modules/API.cpp index cdbb5aff..ca2bbd17 100644 --- a/src/modules/API.cpp +++ b/src/modules/API.cpp @@ -1,11 +1,11 @@ #include "ESPConfiguration.h" -void* getAPI_Mcp23017(String subtype, String params); -void* getAPI_SysExt(String subtype, String params); -void* getAPI_Variable(String subtype, String params); +void* getAPI_Lcd2004(String subtype, String params); void* getAPI_ButtonIn(String subtype, String params); void* getAPI_ButtonOut(String subtype, String params); -void* getAPI_Ads1115(String subtype, String params); +void* getAPI_IoTServo(String subtype, String params); +void* getAPI_Mp3(String subtype, String params); +void* getAPI_Timer(String subtype, String params); void* getAPI_Aht20(String subtype, String params); void* getAPI_AnalogAdc(String subtype, String params); void* getAPI_Bme280(String subtype, String params); @@ -15,19 +15,22 @@ void* getAPI_Ds18b20(String subtype, String params); void* getAPI_GY21(String subtype, String params); void* getAPI_Hdc1080(String subtype, String params); void* getAPI_Max6675(String subtype, String params); -void* getAPI_Mhz19(String subtype, String params); -void* getAPI_Sds011(String subtype, String params); +void* getAPI_RCswitch(String subtype, String params); void* getAPI_Sht20(String subtype, String params); -void* getAPI_Lcd2004(String subtype, String params); +void* getAPI_Sonar(String subtype, String params); +void* getAPI_IarduinoRTC(String subtype, String params); +void* getAPI_Mcp23017(String subtype, String params); +void* getAPI_SysExt(String subtype, String params); +void* getAPI_Variable(String subtype, String params); void* getAPI(String subtype, String params) { void* tmpAPI; -if ((tmpAPI = getAPI_Mcp23017(subtype, params)) != nullptr) return tmpAPI; -if ((tmpAPI = getAPI_SysExt(subtype, params)) != nullptr) return tmpAPI; -if ((tmpAPI = getAPI_Variable(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Lcd2004(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_Ads1115(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_IoTServo(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Mp3(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Timer(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Aht20(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_AnalogAdc(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Bme280(subtype, params)) != nullptr) return tmpAPI; @@ -37,8 +40,12 @@ if ((tmpAPI = getAPI_Ds18b20(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_GY21(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Hdc1080(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Max6675(subtype, params)) != nullptr) return tmpAPI; -if ((tmpAPI = getAPI_Mhz19(subtype, params)) != nullptr) return tmpAPI; -if ((tmpAPI = getAPI_Sds011(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_RCswitch(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Sht20(subtype, params)) != nullptr) return tmpAPI; -if ((tmpAPI = getAPI_Lcd2004(subtype, params)) != nullptr) return tmpAPI;return nullptr; +if ((tmpAPI = getAPI_Sonar(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_IarduinoRTC(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Mcp23017(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_SysExt(subtype, params)) != nullptr) return tmpAPI; +if ((tmpAPI = getAPI_Variable(subtype, params)) != nullptr) return tmpAPI; +return nullptr; } \ No newline at end of file diff --git a/src/modules/lcd/Lcd2004/Lcd2004.cpp b/src/modules/display/Lcd2004/Lcd2004.cpp similarity index 74% rename from src/modules/lcd/Lcd2004/Lcd2004.cpp rename to src/modules/display/Lcd2004/Lcd2004.cpp index c7396a61..3feee118 100644 --- a/src/modules/lcd/Lcd2004/Lcd2004.cpp +++ b/src/modules/display/Lcd2004/Lcd2004.cpp @@ -4,6 +4,8 @@ #include "LiquidCrystal_I2C.h" #include +void scanI2C(); + LiquidCrystal_I2C *LCDI2C; class Lcd2004 : public IoTItem { @@ -14,12 +16,19 @@ class Lcd2004 : public IoTItem { String _descr; int _prevStrSize; + bool _isShow = true; // экран показывает + public: Lcd2004(String parameters) : IoTItem(parameters) { String addr, size, xy; _prevStrSize = 0; jsonRead(parameters, "addr", addr); + if (addr == "") { + scanI2C(); + return; + } + jsonRead(parameters, "size", size); int w = selectFromMarkerToMarker(size, ",", 0).toInt(); //количество столбцов int h = selectFromMarkerToMarker(size, ",", 1).toInt(); //количество строк @@ -48,8 +57,8 @@ class Lcd2004 : public IoTItem { else tmpStr = getItemValue(_id2show); LCDI2C->setCursor(_x, _y); LCDI2C->print(tmpStr); - - // LCDI2C->print("Helloy,Manager 404 !"); + + //LCDI2C->print("Helloy,Manager 404 !"); _prevStrSize = tmpStr.length(); } @@ -60,18 +69,36 @@ class Lcd2004 : public IoTItem { LCDI2C->noBacklight(); else if (command == "backlight") LCDI2C->backlight(); - else if (command == "noDisplay") + else if (command == "noDisplay") { LCDI2C->noDisplay(); - else if (command == "display") + _isShow = false; + } else if (command == "display") { LCDI2C->display(); - else if (command == "x") { - _x = param[0].valD; + _isShow = true; + } else if (command == "toggle") { + if (_isShow) { + LCDI2C->noDisplay(); + _isShow = false; + } else { + LCDI2C->display(); + _isShow = true; + } + } else if (command == "x") { + if (param.size()) { + _x = param[0].valD; + } } else if (command == "y") { - _y = param[0].valD; + if (param.size()) { + _y = param[0].valD; + } } else if (command == "descr") { - _descr = param[0].valS; + if (param.size()) { + _descr = param[0].valS; + } } else if (command == "id2show") { - _id2show = param[0].valS; + if (param.size()) { + _id2show = param[0].valS; + } } doByInterval(); diff --git a/src/modules/display/Lcd2004/modinfo.json b/src/modules/display/Lcd2004/modinfo.json new file mode 100644 index 00000000..59e4e2b0 --- /dev/null +++ b/src/modules/display/Lcd2004/modinfo.json @@ -0,0 +1,62 @@ +{ + "menuSection": "Экраны", + + "configItem": [{ + "name": "LCD экран 2004", + "type": "Reading", + "subtype": "Lcd2004", + "id": "Lcd", + "widget": "", + "page": "", + "descr": "T", + + "int": 15, + "addr": "0x27", + "size": "20,4", + "coord": "0,0", + "id2show": "id датчика" + }, + { + "name": "LCD экран 1602", + "type": "Reading", + "subtype": "Lcd2004", + "id": "Lcd", + "widget": "", + "page": "", + "descr": "T", + + "int": 15, + "addr": "0x27", + "size": "16,2", + "coord": "0,0", + "id2show": "id датчика" + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "Sergey @Serghei63", + "moduleName": "Lcd2004", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет выводить на символьные экраны по указанным позициям значения других элементов конфигурации.", + "propInfo": { + "int": "Период времени в секундах обновления информации на экране по конкретному элементу.", + "addr": "Адрес устройства на шине, обычно 0x27.", + "size": "Размерность матрицы экрана.", + "coord": "Координата позиции для вывода данных элемента конфигурации.", + "id2show": "id элемента конфигурации." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "marcoschwartz/LiquidCrystal_I2C@^1.1.4" + ], + "esp8266_4mb": [ + "marcoschwartz/LiquidCrystal_I2C@^1.1.4" + ] + } +} \ No newline at end of file diff --git a/src/modules/exec/ButtonIn/items.json b/src/modules/exec/ButtonIn/items.json deleted file mode 100644 index e501f50a..00000000 --- a/src/modules/exec/ButtonIn/items.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "name": "Кнопка (подключенная физически)", - "num": 31, - "type": "Writing", - "subtype": "ButtonIn", - "id": "btn", - "widget": "toggle", - "page": "Кнопки", - "descr": "", - "int": 0, - - "pin": 16, - "execLevel": "1", - "pinMode": "INPUT", - "debounceDelay": 50, - "fixState": 1 - } -] \ No newline at end of file diff --git a/src/modules/exec/ButtonIn/modinfo.json b/src/modules/exec/ButtonIn/modinfo.json new file mode 100644 index 00000000..642532fe --- /dev/null +++ b/src/modules/exec/ButtonIn/modinfo.json @@ -0,0 +1,44 @@ +{ + "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": [] + } +} \ No newline at end of file diff --git a/src/modules/exec/ButtonOut/ButtonOut.cpp b/src/modules/exec/ButtonOut/ButtonOut.cpp index 46481454..3f7ee697 100644 --- a/src/modules/exec/ButtonOut/ButtonOut.cpp +++ b/src/modules/exec/ButtonOut/ButtonOut.cpp @@ -15,7 +15,7 @@ class ButtonOut : public IoTItem { IoTgpio.pinMode(_pin, OUTPUT); //TODO: прочитать состояние из памяти - IoTgpio.digitalWrite(_pin, LOW); // пока нет памяти, устанавливаем значение в ноль + IoTgpio.digitalWrite(_pin, _inv?HIGH:LOW); // пока нет памяти, устанавливаем значение в ноль value.valD = 0; } @@ -30,7 +30,7 @@ class ButtonOut : public IoTItem { // String command - имя команды после ID. (ID.Команда()) // param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22 - if (command == "change") { // выполняем код при вызове спец команды из сценария: ID.reboot(); + if (command == "change") { value.valD = 1 - IoTgpio.digitalRead(_pin); IoTgpio.digitalWrite(_pin, value.valD); regEvent(value.valD, "ButtonOut"); @@ -41,7 +41,7 @@ class ButtonOut : public IoTItem { void setValue(IoTValue Value) { value = Value; - IoTgpio.digitalWrite(_pin, value.valD); + IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD); if (value.isDecimal) regEvent(value.valD, "ButtonOut"); else regEvent(value.valS, "ButtonOut"); } diff --git a/src/modules/exec/ButtonOut/items.json b/src/modules/exec/ButtonOut/items.json deleted file mode 100644 index 2ab65d68..00000000 --- a/src/modules/exec/ButtonOut/items.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "name": "Кнопка управляющая пином (Реле с кнопкой)", - "num": 31, - "type": "Writing", - "subtype": "ButtonOut", - "id": "btn", - "widget": "toggle", - "page": "Кнопки", - "descr": "", - "int": 0, - - "inv": 0, - "pin": 2 - } -] \ No newline at end of file diff --git a/src/modules/exec/ButtonOut/modinfo.json b/src/modules/exec/ButtonOut/modinfo.json new file mode 100644 index 00000000..d85a2220 --- /dev/null +++ b/src/modules/exec/ButtonOut/modinfo.json @@ -0,0 +1,38 @@ +{ + "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": [] + } +} \ No newline at end of file diff --git a/src/modules/exec/EspCam/EspCam.cpp b/src/modules/exec/EspCam/EspCam.cpp new file mode 100644 index 00000000..39866484 --- /dev/null +++ b/src/modules/exec/EspCam/EspCam.cpp @@ -0,0 +1,157 @@ +#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 ¶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; + } +} diff --git a/src/modules/exec/EspCam/modinfo.json b/src/modules/exec/EspCam/modinfo.json new file mode 100644 index 00000000..35768e3c --- /dev/null +++ b/src/modules/exec/EspCam/modinfo.json @@ -0,0 +1,42 @@ +{ + "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" + ] + } +} \ No newline at end of file diff --git a/src/modules/exec/IoTServo/IoTServo.cpp b/src/modules/exec/IoTServo/IoTServo.cpp new file mode 100644 index 00000000..8c7cc357 --- /dev/null +++ b/src/modules/exec/IoTServo/IoTServo.cpp @@ -0,0 +1,73 @@ +#include "Global.h" +#include "classes/IoTItem.h" +#include "classes/IoTGpio.h" + +extern IoTGpio IoTgpio; + +#include + +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 ¶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; + } +} diff --git a/src/modules/exec/IoTServo/modinfo.json b/src/modules/exec/IoTServo/modinfo.json new file mode 100644 index 00000000..c0936b75 --- /dev/null +++ b/src/modules/exec/IoTServo/modinfo.json @@ -0,0 +1,43 @@ +{ + "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": [] + } +} \ No newline at end of file diff --git a/src/modules/exec/Mp3/Mp3.cpp b/src/modules/exec/Mp3/Mp3.cpp new file mode 100644 index 00000000..80a33d3b --- /dev/null +++ b/src/modules/exec/Mp3/Mp3.cpp @@ -0,0 +1,135 @@ +#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 ¶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; + } +} diff --git a/src/modules/exec/Mp3/modinfo.json b/src/modules/exec/Mp3/modinfo.json new file mode 100644 index 00000000..74341161 --- /dev/null +++ b/src/modules/exec/Mp3/modinfo.json @@ -0,0 +1,43 @@ +{ + "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" + ] + } +} \ No newline at end of file diff --git a/src/modules/exec/SDcard/SDcard.cpp b/src/modules/exec/SDcard/SDcard.cpp new file mode 100644 index 00000000..6fecb900 --- /dev/null +++ b/src/modules/exec/SDcard/SDcard.cpp @@ -0,0 +1,70 @@ +#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 ¶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; + } +} diff --git a/src/modules/exec/SDcard/modinfo.json b/src/modules/exec/SDcard/modinfo.json new file mode 100644 index 00000000..7e6746a6 --- /dev/null +++ b/src/modules/exec/SDcard/modinfo.json @@ -0,0 +1,36 @@ +{ + "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" + ] + } +} \ No newline at end of file diff --git a/src/modules/exec/Telegram/Telegram.cpp b/src/modules/exec/Telegram/Telegram.cpp new file mode 100644 index 00000000..6e48d84a --- /dev/null +++ b/src/modules/exec/Telegram/Telegram.cpp @@ -0,0 +1,141 @@ +#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::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 ¶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; + } +} diff --git a/src/modules/exec/Telegram/modinfo.json b/src/modules/exec/Telegram/modinfo.json new file mode 100644 index 00000000..c6331aa8 --- /dev/null +++ b/src/modules/exec/Telegram/modinfo.json @@ -0,0 +1,46 @@ +{ + "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" + ] + } +} \ No newline at end of file diff --git a/src/modules/exec/Timer/Timer.cpp b/src/modules/exec/Timer/Timer.cpp new file mode 100644 index 00000000..9a8e28e6 --- /dev/null +++ b/src/modules/exec/Timer/Timer.cpp @@ -0,0 +1,69 @@ +#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 ¶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; + } +} diff --git a/src/modules/exec/Timer/modinfo.json b/src/modules/exec/Timer/modinfo.json new file mode 100644 index 00000000..e5e367a0 --- /dev/null +++ b/src/modules/exec/Timer/modinfo.json @@ -0,0 +1,43 @@ +{ + "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": [] + } +} \ No newline at end of file diff --git a/src/modules/exec/items.json b/src/modules/exec/items.json deleted file mode 100644 index 8cb113d8..00000000 --- a/src/modules/exec/items.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "header": "Модули управления" - } -] \ No newline at end of file diff --git a/src/modules/items.json b/src/modules/items.json deleted file mode 100644 index a71a6cfd..00000000 --- a/src/modules/items.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "name": "Выберите элемент", - "num": 0 - } -] \ No newline at end of file diff --git a/src/modules/lcd/Lcd2004/items.json b/src/modules/lcd/Lcd2004/items.json deleted file mode 100644 index 81118ea4..00000000 --- a/src/modules/lcd/Lcd2004/items.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "name": "LCD экран 2004", - "num": 25, - "type": "Reading", - "subtype": "Lcd2004", - "id": "Lcd", - "widget": "", - "page": "", - "descr": "T", - "int": 15, - "addr": "0x27", - "size": "20,4", - "coord": "0,0", - "id2show": "id датчика" - }, - { - "name": "LCD экран 1602", - "num": 26, - "type": "Reading", - "subtype": "Lcd2004", - "id": "Lcd", - "widget": "", - "page": "", - "descr": "T", - "int": 15, - "addr": "0x27", - "size": "16,2", - "coord": "0,0", - "id2show": "id датчика" - } -] \ No newline at end of file diff --git a/src/modules/lcd/Lcd2004/platformio.ini b/src/modules/lcd/Lcd2004/platformio.ini deleted file mode 100644 index bdecd531..00000000 --- a/src/modules/lcd/Lcd2004/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - marcoschwartz/LiquidCrystal_I2C@^1.1.4 - -[env:esp32_4mb] -lib_deps = - marcoschwartz/LiquidCrystal_I2C@^1.1.4 diff --git a/src/modules/lcd/items.json b/src/modules/lcd/items.json deleted file mode 100644 index c0739a1d..00000000 --- a/src/modules/lcd/items.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "header": "Экраны" - } -] \ No newline at end of file diff --git a/src/modules/sensors/Ads1115/items.json b/src/modules/sensors/Ads1115/items.json deleted file mode 100644 index 9cfc0bcd..00000000 --- a/src/modules/sensors/Ads1115/items.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "name": "Датчик напряжения ADS1115", - "num": 28, - "type": "Reading", - "subtype": "Ads1115", - "id": "Ads3", - "widget": "anydataVlt", - "page": "Сенсоры", - "descr": "ADS_3", - - "pin": "0", - "mode": "volt", - "gain": "3/4x", - - "plus": 0, - "multiply": 1, - "round": 100, - "int": 10 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Ads1115/modinfo.json b/src/modules/sensors/Ads1115/modinfo.json new file mode 100644 index 00000000..7b781efa --- /dev/null +++ b/src/modules/sensors/Ads1115/modinfo.json @@ -0,0 +1,49 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Датчик напряжения ADS1115", + "type": "Reading", + "subtype": "Ads1115", + "id": "Ads3", + "widget": "anydataVlt", + "page": "Сенсоры", + "descr": "ADS_3", + + "pin": "0", + "mode": "volt", + "gain": "3/4x", + + "plus": 0, + "multiply": 1, + "round": 2, + "int": 10 + }], + + "about": { + "authorName": "Serghei Crasnicov", + "authorContact": "https://t.me/Serghei63", + "authorGit": "https://github.com/Serghei63", + "specialThanks": "", + "moduleName": "Ads1115", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить относительную величину напряжения на понижающем трансформаторе.", + "propInfo": { + "pin": "GPIO номер, к которому подключен датчик.", + "mode": "", + "gain": "", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": false, + + "devices": { + "esp32_4mb": [ + "adafruit/Adafruit ADS1X15 @ ^2.3.0" + ], + "esp8266_4mb": [ + "adafruit/Adafruit ADS1X15 @ ^2.3.0" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Ads1115/platformio.ini b/src/modules/sensors/Ads1115/platformio.ini deleted file mode 100644 index 89446999..00000000 --- a/src/modules/sensors/Ads1115/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - adafruit/Adafruit ADS1X15 @ ^2.3.0 - -[env:esp32_4mb] -lib_deps = - adafruit/Adafruit ADS1X15 @ ^2.3.0 \ No newline at end of file diff --git a/src/modules/sensors/Aht20/items.json b/src/modules/sensors/Aht20/items.json deleted file mode 100644 index 91fcef48..00000000 --- a/src/modules/sensors/Aht20/items.json +++ /dev/null @@ -1,27 +0,0 @@ -[{ - "name": "Cенсор температуры AHT20", - "num": 12, - "type": "Reading", - "subtype": "Aht20t", - "id": "Temp20", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "AHT20 Температура", - "int": 15, - "addr": "0x38", - "round": 1 -}, -{ - "name": "Cенсор влажности AHT20", - "num": 13, - "type": "Reading", - "subtype": "Aht20h", - "id": "Hum20", - "widget": "anydataHum", - "page": "Сенсоры", - "descr": "AHT20 Влажность", - "int": 15, - "addr": "0x38", - "round": 1 -} -] \ No newline at end of file diff --git a/src/modules/sensors/Aht20/modinfo.json b/src/modules/sensors/Aht20/modinfo.json new file mode 100644 index 00000000..5ce12da0 --- /dev/null +++ b/src/modules/sensors/Aht20/modinfo.json @@ -0,0 +1,54 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры AHT20", + "type": "Reading", + "subtype": "Aht20t", + "id": "Temp20", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "AHT20 Температура", + "int": 15, + "addr": "0x38", + "round": 1 + }, + { + "name": "Cенсор влажности AHT20", + "type": "Reading", + "subtype": "Aht20h", + "id": "Hum20", + "widget": "anydataHum", + "page": "Сенсоры", + "descr": "AHT20 Влажность", + "int": 15, + "addr": "0x38", + "round": 1 + }], + + "about": { + "authorName": "Serghei Crasnicov", + "authorContact": "https://t.me/Serghei63", + "authorGit": "https://github.com/Serghei63", + "specialThanks": "", + "moduleName": "Aht20", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить температуру и влажность с Aht20.", + "propInfo": { + "pin": "GPIO номер, к которому подключен датчик.", + "addr": "Адрес датчика на шине, обычно 0x38.", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "Adafruit AHTX0" + ], + "esp8266_4mb": [ + "Adafruit AHTX0" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Aht20/platformio.ini b/src/modules/sensors/Aht20/platformio.ini deleted file mode 100644 index 5e37d73b..00000000 --- a/src/modules/sensors/Aht20/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - Adafruit AHTX0 - -[env:esp32_4mb] -lib_deps = - Adafruit AHTX0 diff --git a/src/modules/sensors/AnalogAdc/AnalogAdc.cpp b/src/modules/sensors/AnalogAdc/AnalogAdc.cpp index 75e3aa6d..167c9ac0 100644 --- a/src/modules/sensors/AnalogAdc/AnalogAdc.cpp +++ b/src/modules/sensors/AnalogAdc/AnalogAdc.cpp @@ -3,53 +3,82 @@ extern IoTGpio IoTgpio; -//Это файл сенсора, в нем осуществляется чтение сенсора. -//для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора -//Название должно быть уникальным, коротким и отражать суть сенсора. +// Это файл сенсора, в нем осуществляется чтение сенсора. +// для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора +// Название должно быть уникальным, коротким и отражать суть сенсора. class AnalogAdc : public IoTItem { private: //======================================================================================================= // Секция переменных. - //Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы - //впоследствии использовать их в loop и setup + // Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы + // впоследствии использовать их в loop и setup unsigned int _pin; + unsigned int _avgSteps, _avgCount; + unsigned long _avgSumm; public: //======================================================================================================= // setup() - //это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора. - //Такие как ...begin и подставлять в них параметры полученные из web интерфейса. - //Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: + // это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора. + // Такие как ...begin и подставлять в них параметры полученные из web интерфейса. + // Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: // jsonReadStr, jsonReadBool, jsonReadInt AnalogAdc(String parameters): IoTItem(parameters) { _pin = jsonReadInt(parameters, "pin"); + _avgSteps = jsonReadInt(parameters, "avgSteps"); + _avgSumm = 0; + _avgCount = 0; } + //======================================================================================================= // doByInterval() - //это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора - //а затем выполнить regEvent - это регистрация произошедшего события чтения - //здесь так же доступны все переменные из секции переменных, и полученные в setup - //если у сенсора несколько величин то делайте несколько regEvent - //не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции - //и выполнить за несколько тактов + // это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора + // а затем выполнить regEvent - это регистрация произошедшего события чтения + // здесь так же доступны все переменные из секции переменных, и полученные в setup + // если у сенсора несколько величин то делайте несколько regEvent + // не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции + // и выполнить за несколько тактов void doByInterval() { - value.valD = IoTgpio.analogRead(_pin); - + if (_avgSteps <= 1) value.valD = IoTgpio.analogRead(_pin); regEvent(value.valD, "AnalogAdc"); //обязательный вызов хотяб один } + //======================================================================================================= + // loop() + // полный аналог loop() из arduino. Нужно помнить, что все модули имеют равный поочередный доступ к центральному loop(), поэтому, необходимо следить + // за задержками в алгоритме и не создавать пауз. Кроме того, данная версия перегружает родительскую, поэтому doByInterval() отключается, если + // не повторить механизм расчета интервалов. + void loop() { + if (_avgSteps > 1) { + if (_avgCount > _avgSteps) { + value.valD = _avgSumm / _avgSteps; + _avgSumm = 0; + _avgCount = 0; + } + + _avgSumm = _avgSumm + IoTgpio.analogRead(_pin); + _avgCount++; + } + + currentMillis = millis(); + difference = currentMillis - prevMillis; + if (difference >= _interval) { + prevMillis = millis(); + this->doByInterval(); + } + } ~AnalogAdc() {}; }; -//после замены названия сенсора, на функцию можно не обращать внимания -//если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть -//создание и контроль соответствующих глобальных переменных +// после замены названия сенсора, на функцию можно не обращать внимания +// если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть +// создание и контроль соответствующих глобальных переменных void* getAPI_AnalogAdc(String subtype, String param) { - if (subtype == F("AnalogAdc")) { - return new AnalogAdc(param); - } else { - return nullptr; - } + if (subtype == F("AnalogAdc")) { + return new AnalogAdc(param); + } else { + return nullptr; + } } diff --git a/src/modules/sensors/AnalogAdc/items.json b/src/modules/sensors/AnalogAdc/items.json deleted file mode 100644 index df3eed30..00000000 --- a/src/modules/sensors/AnalogAdc/items.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "name": "Аналоговый сенсор", - "num": 1, - "type": "Reading", - "subtype": "AnalogAdc", - "id": "t", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "Температура", - "map": "1,1024,1,100", - "plus": 0, - "multiply": 1, - "round": 1, - "pin": 0, - "int": 15 - } -] \ No newline at end of file diff --git a/src/modules/sensors/AnalogAdc/modinfo.json b/src/modules/sensors/AnalogAdc/modinfo.json new file mode 100644 index 00000000..f7f5019c --- /dev/null +++ b/src/modules/sensors/AnalogAdc/modinfo.json @@ -0,0 +1,42 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Аналоговый сенсор", + "type": "Reading", + "subtype": "AnalogAdc", + "id": "t", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Температура", + "map": "1,1024,1,100", + "plus": 0, + "multiply": 1, + "round": 1, + "pin": 0, + "int": 15, + "avgSteps": 1 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "AnalogAdc", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить текущее значение на аналоговом GPIO или усредненное для avgSteps измерений каждого вызова loop.", + "propInfo": { + "pin": "Аналоговый GPIO номер, к которому подключен датчик.", + "avgSteps": "Количество считываний для усреднения. При <=1, считывается одно значение за каждый период опроса.", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [], + "esp8266_4mb": [] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Bme280/items.json b/src/modules/sensors/Bme280/modinfo.json similarity index 50% rename from src/modules/sensors/Bme280/items.json rename to src/modules/sensors/Bme280/modinfo.json index c04bc9c4..8c63a82a 100644 --- a/src/modules/sensors/Bme280/items.json +++ b/src/modules/sensors/Bme280/modinfo.json @@ -1,7 +1,8 @@ -[ - { +{ + "menuSection": "Сенсоры", + + "configItem": [{ "name": "Cенсор температуры Bme280", - "num": 9, "type": "Reading", "subtype": "Bme280t", "id": "tmp3", @@ -14,7 +15,6 @@ }, { "name": "Cенсор давления Bme280", - "num": 10, "type": "Reading", "subtype": "Bme280p", "id": "Press3", @@ -27,7 +27,6 @@ }, { "name": "Cенсор влажности Bme280", - "num": 11, "type": "Reading", "subtype": "Bme280h", "id": "Hum3", @@ -37,5 +36,30 @@ "int": 15, "addr": "0x77", "round": 1 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "Serghei Crasnicov @Serghei63", + "moduleName": "Bme280", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры, давления и влажности с Bme280.", + "propInfo": { + "addr": "Адрес датчика на шине, обычно 0x77.", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "adafruit/Adafruit BME280 Library" + ], + "esp8266_4mb": [ + "adafruit/Adafruit BME280 Library" + ] } -] \ No newline at end of file +} \ No newline at end of file diff --git a/src/modules/sensors/Bme280/platformio.ini b/src/modules/sensors/Bme280/platformio.ini deleted file mode 100644 index b4c83133..00000000 --- a/src/modules/sensors/Bme280/platformio.ini +++ /dev/null @@ -1,8 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - adafruit/Adafruit BME280 Library - -[env:esp32_4mb] -lib_deps = - adafruit/Adafruit BME280 Library - \ No newline at end of file diff --git a/src/modules/sensors/Bmp280/items.json b/src/modules/sensors/Bmp280/items.json deleted file mode 100644 index 1d5b7636..00000000 --- a/src/modules/sensors/Bmp280/items.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "name": "Cенсор температуры Bmp280", - "num": 7, - "type": "Reading", - "subtype": "Bmp280t", - "id": "tmp3", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "280 Температура", - "int": 15, - "addr": "0x77", - "round": 1 - }, - { - "name": "Cенсор давления Bmp280", - "num": 8, - "type": "Reading", - "subtype": "Bmp280p", - "id": "Press3", - "widget": "anydataMm", - "page": "Сенсоры", - "descr": "280 Давление", - "int": 15, - "addr": "0x77", - "round": 1 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Bmp280/modinfo.json b/src/modules/sensors/Bmp280/modinfo.json new file mode 100644 index 00000000..4428497a --- /dev/null +++ b/src/modules/sensors/Bmp280/modinfo.json @@ -0,0 +1,53 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры Bmp280", + "type": "Reading", + "subtype": "Bmp280t", + "id": "tmp3", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "280 Температура", + "int": 15, + "addr": "0x77", + "round": 1 + }, + { + "name": "Cенсор давления Bmp280", + "type": "Reading", + "subtype": "Bmp280p", + "id": "Press3", + "widget": "anydataMm", + "page": "Сенсоры", + "descr": "280 Давление", + "int": 15, + "addr": "0x77", + "round": 1 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "Serghei Crasnicov @Serghei63", + "moduleName": "Bmp280", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры и давления с Bmp280.", + "propInfo": { + "addr": "Адрес датчика на шине, обычно 0x77.", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "adafruit/Adafruit BMP280 Library" + ], + "esp8266_4mb": [ + "adafruit/Adafruit BMP280 Library" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Bmp280/platformio.ini b/src/modules/sensors/Bmp280/platformio.ini deleted file mode 100644 index 037efd48..00000000 --- a/src/modules/sensors/Bmp280/platformio.ini +++ /dev/null @@ -1,8 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - adafruit/Adafruit BMP280 Library - -[env:esp32_4mb] -lib_deps = - adafruit/Adafruit BMP280 Library - \ No newline at end of file diff --git a/src/modules/sensors/Dht1122/items.json b/src/modules/sensors/Dht1122/items.json deleted file mode 100644 index e3a90111..00000000 --- a/src/modules/sensors/Dht1122/items.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "name": "Cенсор температуры dht11", - "num": 5, - "type": "Reading", - "subtype": "Dht1122t", - "id": "tmp3", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "Температура", - "int": 15, - "pin": 0, - "senstype": "dht11" - }, - { - "name": "Cенсор влажности dht11", - "num": 6, - "type": "Reading", - "subtype": "Dht1122h", - "id": "Hum3", - "widget": "anydataHum", - "page": "Сенсоры", - "descr": "Влажность", - "int": 15, - "pin": 0, - "senstype": "dht11" - } -] \ No newline at end of file diff --git a/src/modules/sensors/Dht1122/modinfo.json b/src/modules/sensors/Dht1122/modinfo.json new file mode 100644 index 00000000..b0a417b6 --- /dev/null +++ b/src/modules/sensors/Dht1122/modinfo.json @@ -0,0 +1,53 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры dht11", + "type": "Reading", + "subtype": "Dht1122t", + "id": "tmp3", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Температура", + "int": 15, + "pin": 0, + "senstype": "dht11" + }, + { + "name": "Cенсор влажности dht11", + "type": "Reading", + "subtype": "Dht1122h", + "id": "Hum3", + "widget": "anydataHum", + "page": "Сенсоры", + "descr": "Влажность", + "int": 15, + "pin": 0, + "senstype": "dht11" + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "Serghei Crasnicov @Serghei63", + "moduleName": "Dht1122", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры и влажности с dht11 или dht22.", + "propInfo": { + "senstype": "Тип сенсора dht11 или dht22.", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "beegee-tokyo/DHT sensor library for ESPx" + ], + "esp8266_4mb": [ + "beegee-tokyo/DHT sensor library for ESPx" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Dht1122/platformio.ini b/src/modules/sensors/Dht1122/platformio.ini deleted file mode 100644 index 34170b0f..00000000 --- a/src/modules/sensors/Dht1122/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - beegee-tokyo/DHT sensor library for ESPx - -[env:esp32_4mb] -lib_deps = - beegee-tokyo/DHT sensor library for ESPx diff --git a/src/modules/sensors/Ds18b20/items.json b/src/modules/sensors/Ds18b20/items.json deleted file mode 100644 index f7214366..00000000 --- a/src/modules/sensors/Ds18b20/items.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "name": "Cенсор температуры ds18b20", - "num": 2, - "type": "Reading", - "subtype": "Ds18b20", - "id": "dstmp", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "DS Температура", - "int": 15, - "pin": 2, - "index": 0, - "addr": "", - "round": 1 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Ds18b20/modinfo.json b/src/modules/sensors/Ds18b20/modinfo.json new file mode 100644 index 00000000..1da2a4ea --- /dev/null +++ b/src/modules/sensors/Ds18b20/modinfo.json @@ -0,0 +1,45 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры ds18b20", + "type": "Reading", + "subtype": "Ds18b20", + "id": "dstmp", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "DS Температура", + "int": 15, + "pin": 2, + "index": 0, + "addr": "", + "round": 1 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "Ds18b20", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры с Ds18b20.", + "propInfo": { + "pin": "GPIO номер, к которому подключена шина данных датчиков.", + "index": "Порядковый номер датчика на шине.", + "addr": "Адрес датчика на шине для точной идентификации. Можно скопировать из консоли.", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "milesburton/DallasTemperature@^3.9.1" + ], + "esp8266_4mb": [ + "milesburton/DallasTemperature@^3.9.1" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Ds18b20/platformio.ini b/src/modules/sensors/Ds18b20/platformio.ini deleted file mode 100644 index 3cedd5d7..00000000 --- a/src/modules/sensors/Ds18b20/platformio.ini +++ /dev/null @@ -1,8 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - milesburton/DallasTemperature@^3.9.1 - -[env:esp32_4mb] -lib_deps = - milesburton/DallasTemperature@^3.9.1 - diff --git a/src/modules/sensors/Emon/Emon.cpp b/src/modules/sensors/Emon/Emon.cpp new file mode 100644 index 00000000..ba196de9 --- /dev/null +++ b/src/modules/sensors/Emon/Emon.cpp @@ -0,0 +1,72 @@ +/****************************************************************** + Used Energy Monitoring Library + + https://github.com/openenergymonitor/EmonLib + + adapted for version 4 @Serghei63 + ******************************************************************/ + +#include "Global.h" +#include "classes/IoTItem.h" +#include + +extern IoTGpio IoTgpio; + +#include "EmonLib.h" // Include Emon Library + +EnergyMonitor emon1; // Create an instance + + +class Energy : public IoTItem { + + private: + unsigned int _pinI; // ток + unsigned int _calibI; // ток + + public: + Energy(String parameters): IoTItem(parameters) { + _pinI = jsonReadInt(parameters, "pin_I"); + _calibI = jsonReadInt(parameters, "calib_I"); + emon1.current(_pinI, _calibI); // Current: input pin, calibration. + } + + void doByInterval() { + value.valD = emon1.calcIrms(1480); // Calculate Irms only + regEvent(value.valD, "current"); + } + + ~Energy(){}; +}; + + +class Power : public IoTItem { + + private: + unsigned int _pinU; // напряжение + unsigned int _calibU; // напряжение + + public: + Power(String parameters): IoTItem(parameters) { + _pinU = jsonReadInt(parameters, "pin_U"); + _calibU = jsonReadInt(parameters, "calib_U"); + emon1.voltage(_pinU, _calibU, 1.7); // Voltage: input pin, calibration, phase_shift + } + + void doByInterval() { + if (emon1.Irms > 0) emon1.calcVI(10, 1000); // Calculate all. No.of half wavelengths (crossings), time-out при условии, что ток не нулевой + value.valD = emon1.Vrms; //extract Vrms into Variable; + regEvent(value.valD, "voltage"); + } + + ~Power(){}; +}; + +void* getAPI_Emon(String subtype, String param) { + if (subtype == F("I")) { + return new Energy(param); + } else if (subtype == F("U")) { + return new Power(param); + } else { + return nullptr; + } +} diff --git a/src/modules/sensors/Emon/modinfo.json b/src/modules/sensors/Emon/modinfo.json new file mode 100644 index 00000000..b102e7a1 --- /dev/null +++ b/src/modules/sensors/Emon/modinfo.json @@ -0,0 +1,60 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Датчик тока", + "type": "Reading", + "subtype": "I", + "id": "current", + "widget": "anydataAmp", + "page": "Сенсоры", + "descr": "Датчик тока", + "int": 10, + "pin_I": 34, + "calib_I": 111.1, + "plus": 0, + "multiply": 1 + }, + { + "name": "Датчик напряжения", + "type": "Reading", + "subtype": "U", + "id": "voltage", + "widget": "anydataVlt", + "page": "Сенсоры", + "descr": "Датчик напряжения", + "int": 10, + "pin_U": 35, + "calib_U": 223.1, + "plus": 0, + "multiply": 1 + }], + + "about": { + "authorName": "Serghei Crasnicov", + "authorContact": "https://t.me/Serghei63", + "authorGit": "https://github.com/Serghei63", + "specialThanks": "", + "moduleName": "Emon", + "moduleVersion": "1.0", + "moduleDesc": ".", + "propInfo": { + "pin_U": "", + "calib_U": "", + "pin_I": "", + "calib_I": "", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": false, + + "devices": { + "esp32_4mb": [ + "openenergymonitor/EmonLib@1.1.0" + ], + "esp8266_4mb": [ + "openenergymonitor/EmonLib@1.1.0" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/GY21/items.json b/src/modules/sensors/GY21/items.json deleted file mode 100644 index 4acf44a0..00000000 --- a/src/modules/sensors/GY21/items.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "name": "Cенсор температуры GY21", - "num": 16, - "type": "Reading", - "subtype": "GY21t", - "id": "tmp4", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "Температура", - "round": 1, - "int": 15 - }, - { - "name": "Cенсор влажности GY21", - "num": 17, - "type": "Reading", - "subtype": "GY21h", - "id": "Hum4", - "widget": "anydataHum", - "page": "Сенсоры", - "descr": "Влажность", - "round": 1, - "int": 15 - } -] \ No newline at end of file diff --git a/src/modules/sensors/GY21/modinfo.json b/src/modules/sensors/GY21/modinfo.json new file mode 100644 index 00000000..2955810c --- /dev/null +++ b/src/modules/sensors/GY21/modinfo.json @@ -0,0 +1,50 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры GY21", + "type": "Reading", + "subtype": "GY21t", + "id": "tmp4", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Температура", + "round": 1, + "int": 15 + }, + { + "name": "Cенсор влажности GY21", + "type": "Reading", + "subtype": "GY21h", + "id": "Hum4", + "widget": "anydataHum", + "page": "Сенсоры", + "descr": "Влажность", + "round": 1, + "int": 15 + }], + + "about": { + "authorName": "Alecs", + "authorContact": "https://t.me/Alecs", + "authorGit": "", + "specialThanks": "", + "moduleName": "GY21", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры и влажности с GY21.", + "propInfo": { + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "https://github.com/JonasGMorsch/GY-21.git" + ], + "esp8266_4mb": [ + "https://github.com/JonasGMorsch/GY-21.git" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/GY21/platformio.ini b/src/modules/sensors/GY21/platformio.ini deleted file mode 100644 index 06635eda..00000000 --- a/src/modules/sensors/GY21/platformio.ini +++ /dev/null @@ -1,8 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - https://github.com/JonasGMorsch/GY-21.git - -[env:esp32_4mb] -lib_deps = - https://github.com/JonasGMorsch/GY-21.git - \ No newline at end of file diff --git a/src/modules/sensors/Hdc1080/items.json b/src/modules/sensors/Hdc1080/items.json deleted file mode 100644 index 71a0ad41..00000000 --- a/src/modules/sensors/Hdc1080/items.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "name": "Cенсор температуры HDC1080", - "num": 14, - "type": "Reading", - "subtype": "Hdc1080t", - "id": "Temp1080", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "1080 Температура", - "int": 15, - "addr": "0x40", - "round": 1 - }, - { - "name": "Cенсор влажности HDC1080", - "num": 15, - "type": "Reading", - "subtype": "Hdc1080h", - "id": "Hum1080", - "widget": "anydataHum", - "page": "Сенсоры", - "descr": "1080 Влажность", - "int": 15, - "addr": "0x40", - "round": 1 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Hdc1080/modinfo.json b/src/modules/sensors/Hdc1080/modinfo.json new file mode 100644 index 00000000..7b1a1834 --- /dev/null +++ b/src/modules/sensors/Hdc1080/modinfo.json @@ -0,0 +1,53 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры HDC1080", + "type": "Reading", + "subtype": "Hdc1080t", + "id": "Temp1080", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "1080 Температура", + "int": 15, + "addr": "0x40", + "round": 1 + }, + { + "name": "Cенсор влажности HDC1080", + "type": "Reading", + "subtype": "Hdc1080h", + "id": "Hum1080", + "widget": "anydataHum", + "page": "Сенсоры", + "descr": "1080 Влажность", + "int": 15, + "addr": "0x40", + "round": 1 + }], + + "about": { + "authorName": "Serghei Crasnicov", + "authorContact": "https://t.me/Serghei63", + "authorGit": "https://github.com/Serghei63", + "specialThanks": "", + "moduleName": "Hdc1080", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры и влажности с Hdc1080.", + "propInfo": { + "addr": "Адрес датчика на шине данных, обычно 0x40", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "ClosedCube HDC1080" + ], + "esp8266_4mb": [ + "ClosedCube HDC1080" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Hdc1080/platformio.ini b/src/modules/sensors/Hdc1080/platformio.ini deleted file mode 100644 index 4bef7f3b..00000000 --- a/src/modules/sensors/Hdc1080/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - ClosedCube HDC1080 - -[env:esp32_4mb] -lib_deps = - ClosedCube HDC1080 diff --git a/src/modules/sensors/IoTWiegand/IoTWiegand.cpp b/src/modules/sensors/IoTWiegand/IoTWiegand.cpp new file mode 100644 index 00000000..d4cd8a0d --- /dev/null +++ b/src/modules/sensors/IoTWiegand/IoTWiegand.cpp @@ -0,0 +1,78 @@ +#include "Global.h" +#include "classes/IoTItem.h" + +#include + +#define PIN_D0 D5 +#define PIN_D1 D6 + +WiegandNG wg; + +void PrintBinary(WiegandNG &tempwg) { + volatile unsigned char *buffer=tempwg.getRawData(); + unsigned int bufferSize = tempwg.getBufferSize(); + unsigned int countedBits = tempwg.getBitCounted(); + + unsigned int countedBytes = (countedBits/8); + if ((countedBits % 8)>0) countedBytes++; + // unsigned int bitsUsed = countedBytes * 8; + + for (unsigned int i=bufferSize-countedBytes; i< bufferSize;i++) { + unsigned char bufByte=buffer[i]; + for(int x=0; x<8;x++) { + if ( (((bufferSize-i) *8)-x) <= countedBits) { + if((bufByte & 0x80)) { + Serial.print("1"); + } + else { + Serial.print("0"); + } + } + bufByte<<=1; + } + } + Serial.println(); +} + +class IoTWiegand : public IoTItem { + + public: + IoTWiegand(String parameters) : IoTItem(parameters) { + // int pinD0; + // int pinD1; + + // jsonRead(parameters, "pinD0", pinD0); + // jsonRead(parameters, "pinD1", pinD1); + + unsigned int pinD0 = D5; + unsigned int pinD1 = D6; + unsigned int wiegandbits = 48; + unsigned int packetGap = 15; // 25 ms between packet + + // if(!wg.begin(pinD0, pinD1, wiegandbits, packetGap)) { + // Serial.println("Out of memory!"); + // } + + } + + void loop() { + if(wg.available()) { + wg.pause(); // pause Wiegand pin interrupts + Serial.print("Bits="); + Serial.println(wg.getBitCounted()); // display the number of bits counted + Serial.print("RAW Binary="); + PrintBinary(wg); // display raw data in binary form, raw data inclusive of PARITY + wg.clear(); // compulsory to call clear() to enable interrupts for subsequent data + } + } + + ~IoTWiegand(){}; +}; + +void* getAPI_IoTWiegand(String subtype, String param) { + if (subtype == F("IoTWiegand")) { + return new IoTWiegand(param); + } else { + return nullptr; + } +} diff --git a/src/modules/sensors/IoTWiegand/modinfo.json b/src/modules/sensors/IoTWiegand/modinfo.json new file mode 100644 index 00000000..f0920806 --- /dev/null +++ b/src/modules/sensors/IoTWiegand/modinfo.json @@ -0,0 +1,42 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Считыватель Wiegand", + "type": "Reading", + "subtype": "IoTWiegand", + "id": "wg", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Считыватель", + "int": 0, + "pinD0": 13, + "pinD1": 12 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "IoTWiegand", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить коды доступа по протоколу Wiegand с различных считывателей. На данный момент модуль в РАЗРАБОТКЕ", + "propInfo": { + "pinD0": "GPIO шины данных", + "pinD1": "GPIO шины данных", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": false, + + "devices": { + "esp32_4mb": [ + "https://github.com/jpliew/Wiegand-NG-Multi-Bit-Wiegand-Library-for-Arduino" + ], + "esp8266_4mb": [ + "https://github.com/jpliew/Wiegand-NG-Multi-Bit-Wiegand-Library-for-Arduino" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Max6675/Max6675.cpp b/src/modules/sensors/Max6675/Max6675.cpp index 06245d13..67ece7fd 100644 --- a/src/modules/sensors/Max6675/Max6675.cpp +++ b/src/modules/sensors/Max6675/Max6675.cpp @@ -8,7 +8,7 @@ ******************************************************************/ #include "Global.h" -#include "Classes/IoTItem.h" +#include "classes/IoTItem.h" #include "max6675.h" #include diff --git a/src/modules/sensors/Max6675/items.json b/src/modules/sensors/Max6675/items.json deleted file mode 100644 index 117b477c..00000000 --- a/src/modules/sensors/Max6675/items.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "name": "Cенсор температуры MAX6675", - "num": 31, - "type": "Reading", - "subtype": "Max6675t", - "id": "maxtmp", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "MAX Температура", - "int": 15, - "DO": 12, - "CS": 13, - "CLK": 14 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Max6675/modinfo.json b/src/modules/sensors/Max6675/modinfo.json new file mode 100644 index 00000000..b4dbc3b6 --- /dev/null +++ b/src/modules/sensors/Max6675/modinfo.json @@ -0,0 +1,44 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры MAX6675", + "type": "Reading", + "subtype": "Max6675t", + "id": "maxtmp", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "MAX Температура", + "int": 15, + "DO": 12, + "CS": 13, + "CLK": 14 + }], + + "about": { + "authorName": "Serghei Crasnicov", + "authorContact": "https://t.me/Serghei63", + "authorGit": "https://github.com/Serghei63", + "specialThanks": "", + "moduleName": "Max6675", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры с Max6675.", + "propInfo": { + "DO": "GPIO шины данных", + "CS": "GPIO шины данных", + "CLK": "GPIO шины данных", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "adafruit/MAX6675 library" + ], + "esp8266_4mb": [ + "adafruit/MAX6675 library" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Max6675/platformio.ini b/src/modules/sensors/Max6675/platformio.ini deleted file mode 100644 index 9e9dec29..00000000 --- a/src/modules/sensors/Max6675/platformio.ini +++ /dev/null @@ -1,8 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - adafruit/MAX6675 library - -[env:esp32_4mb] -lib_deps = - adafruit/MAX6675 library - diff --git a/src/modules/sensors/Mhz19/items.json b/src/modules/sensors/Mhz19/modinfo.json similarity index 72% rename from src/modules/sensors/Mhz19/items.json rename to src/modules/sensors/Mhz19/modinfo.json index 327bba53..2ab47bbc 100644 --- a/src/modules/sensors/Mhz19/items.json +++ b/src/modules/sensors/Mhz19/modinfo.json @@ -1,7 +1,8 @@ -[ - { +{ + "menuSection": "Сенсоры", + + "configItem": [{ "name": "Датчик CO2 MHZ-19 UART", - "num": 20, "type": "Reading", "subtype": "Mhz19uart", "id": "co2uart", @@ -20,7 +21,6 @@ }, { "name": "Датчик CO2 MHZ-19 PWM", - "num": 21, "type": "Reading", "subtype": "Mhz19pwm", "id": "co2pwm", @@ -35,7 +35,6 @@ }, { "name": "Cенсор температуры от MHZ-19 UART", - "num": 22, "type": "Reading", "subtype": "Mhz19temp", "id": "Mhz19temp", @@ -52,7 +51,6 @@ }, { "name": "Рабочий диапазон от MHZ-19 UART", - "num": 23, "type": "Reading", "subtype": "Mhz19range", "id": "Mhz19range", @@ -70,7 +68,6 @@ }, { "name": "Автокалибровка от MHZ-19 UART", - "num": 24, "type": "Reading", "subtype": "Mhz19ABC", "id": "Mhz19ABC", @@ -82,5 +79,29 @@ "range": 5000, "ABC": 1, "int": 30 + }], + + "about": { + "authorName": "Alex K", + "authorContact": "https://t.me/cmche", + "authorGit": "", + "specialThanks": "", + "moduleName": "Mhz19", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры и CO2 с Mhz19.", + "propInfo": { + "int": "Количество секунд между опросами датчика.", + "rxPin": "", + "txPin": "", + "range": "", + "ABC": "" + } + }, + + "defActive": false, + + "devices": { + "esp32_4mb": [], + "esp8266_4mb": [] } -] \ No newline at end of file +} \ No newline at end of file diff --git a/src/modules/sensors/RCswitch/RCswitch.cpp b/src/modules/sensors/RCswitch/RCswitch.cpp new file mode 100644 index 00000000..272d5069 --- /dev/null +++ b/src/modules/sensors/RCswitch/RCswitch.cpp @@ -0,0 +1,73 @@ +#include "Global.h" +#include "classes/IoTItem.h" + +#include + +RCSwitch mySwitch = RCSwitch(); + +class RCswitch : public IoTItem { + private: + int _pinRx; // Выход радио модуля + int _pinTx; // Выход модуля передатчика + + public: + RCswitch(String parameters): IoTItem(parameters) { + jsonRead(parameters, "pinRx", _pinRx); + jsonRead(parameters, "pinTx", _pinTx); + _interval = _interval / 1000; // корректируем величину интервала int, теперь он в миллисекундах + if (_pinRx >= 0) { + Serial.printf("Protocol: %d", _pinRx); + mySwitch.enableReceive(digitalPinToInterrupt(_pinRx)); + } + if (_pinTx >= 0) + mySwitch.enableTransmit(_pinTx); + } + + void doByInterval() { + if (_pinRx >= 0 && mySwitch.available()) { + // Serial.print("Received "); + //Serial.print( mySwitch.getReceivedValue() ); + // Serial.print(" / "); + // Serial.print( mySwitch.getReceivedBitlength() ); + // Serial.print("bit "); + // Serial.print("Protocol: "); + // Serial.println( mySwitch.getReceivedProtocol() ); + value.valD = mySwitch.getReceivedValue(); + regEvent(value.valD, "RCswitch"); + + mySwitch.resetAvailable(); + } + } + + IoTValue execute(String command, std::vector ¶m) { + if (_pinTx >= 0) + if (command == "sendBitStr") { // отправляем строку вида "000000000001010100010001" + if (param.size()) { + mySwitch.send(param[0].valS.c_str()); + return {}; + } + } else if (command == "sendTriState") { // отправляем строку вида "00000FFF0F0F" + if (param.size()) { + mySwitch.sendTriState(param[0].valS.c_str()); + return {}; + } + } else if (command == "sendDecimal") { // отправляем строку вида 5393 первым параметром и количество бит чтоб заполнить нулями + if (param.size()) { + mySwitch.send(param[0].valD, param[1].valD); + return {}; + } + } + return {}; + } + + ~RCswitch() {}; +}; + +void* getAPI_RCswitch(String subtype, String param) { + if (subtype == F("RCswitch")) { + return new RCswitch(param); + } else { + return nullptr; + } +} + diff --git a/src/modules/sensors/RCswitch/modinfo.json b/src/modules/sensors/RCswitch/modinfo.json new file mode 100644 index 00000000..a4a5157d --- /dev/null +++ b/src/modules/sensors/RCswitch/modinfo.json @@ -0,0 +1,43 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Сканер кнопок 433 MHz", + "num": 31, + "type": "Reading", + "subtype": "RCswitch", + "id": "rsw", + "int": 500, + "pinRx": 12, + "pinTx": 12 + }], + + "about": { + "authorName": "Serghei Crasnicov", + "authorContact": "https://t.me/Serghei63", + "authorGit": "https://github.com/Serghei63", + "specialThanks": "Valentin Khandriga @Valiuhaaa", + "moduleName": "RCswitch", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет принимать и передавать байт-коды на частоте 433 MHz от и для простых пультов, кнопок, радиореле", + "propInfo": { + "pinRx": "GPIO номер, к которому подключен радио приемник 433 MHz. Если < 0, то приемник выключен", + "pinTx": "GPIO номер, к которому подключен радио передатчик 433 MHz. Если < 0, то передатчик выключен", + "int": "Количество миллисекунд между опросами датчика. 0 - читаем постоянно. (устранение повторений при нажатой кнопке)" + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "rc-switch @ ^2.6.4" + ], + "esp8266_1mb": [ + "rc-switch @ ^2.6.4" + ], + "esp8266_4mb": [ + "rc-switch @ ^2.6.4" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Sds011/items.json b/src/modules/sensors/Sds011/items.json deleted file mode 100644 index b0dc8d30..00000000 --- a/src/modules/sensors/Sds011/items.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "name": "Датчик пыли SDS011 PM25", - "num": 18, - "type": "Reading", - "subtype": "Sds011_25", - "id": "pmuart25", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "PM-2.5", - "plus": 0, - "multiply": 1, - "round": 10, - "rxPin": 13, - "txPin": 12, - "int": 15, - "warmUp": 30, - "period": 300 - }, - { - "name": "Датчик пыли SDS011 PM10", - "num": 19, - "type": "Reading", - "subtype": "Sds011_10", - "id": "pmuart10", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "PM-10", - "plus": 0, - "multiply": 1, - "round": 10, - "rxPin": 13, - "txPin": 12, - "int": 15, - "warmUp": 30, - "period": 300 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Sds011/modinfo.json b/src/modules/sensors/Sds011/modinfo.json new file mode 100644 index 00000000..74cb9343 --- /dev/null +++ b/src/modules/sensors/Sds011/modinfo.json @@ -0,0 +1,66 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Датчик пыли SDS011 PM25", + "type": "Reading", + "subtype": "Sds011_25", + "id": "pmuart25", + "widget": "anydataPpm", + "page": "Сенсоры", + "descr": "PM-2.5", + "plus": 0, + "multiply": 1, + "round": 10, + "rxPin": 13, + "txPin": 12, + "int": 15, + "warmUp": 30, + "period": 300 + }, + { + "name": "Датчик пыли SDS011 PM10", + "type": "Reading", + "subtype": "Sds011_10", + "id": "pmuart10", + "widget": "anydataPpm", + "page": "Сенсоры", + "descr": "PM-10", + "plus": 0, + "multiply": 1, + "round": 10, + "rxPin": 13, + "txPin": 12, + "int": 15, + "warmUp": 30, + "period": 300 + }], + + "about": { + "authorName": "Alex K", + "authorContact": "https://t.me/cmche", + "authorGit": "", + "specialThanks": "", + "moduleName": "Sds011", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения концентрации пыли в воздухе с Sds011.", + "propInfo": { + "int": "Количество секунд между опросами датчика.", + "rxPin": "", + "txPin": "", + "warmUp": "", + "period": "" + } + }, + + "defActive": false, + + "devices": { + "esp32_4mb": [ + "Nova Fitness Sds dust sensors library@1.5.1" + ], + "esp8266_4mb": [ + "Nova Fitness Sds dust sensors library@1.5.1" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Sds011/platformio.ini b/src/modules/sensors/Sds011/platformio.ini deleted file mode 100644 index 9cfb0c87..00000000 --- a/src/modules/sensors/Sds011/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - Nova Fitness Sds dust sensors library@1.5.1 - -[env:esp32_4mb] -lib_deps = - Nova Fitness Sds dust sensors library@1.5.1 diff --git a/src/modules/sensors/Sht20/items.json b/src/modules/sensors/Sht20/items.json deleted file mode 100644 index be83703c..00000000 --- a/src/modules/sensors/Sht20/items.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "name": "Cенсор температуры Sht20", - "num": 3, - "type": "Reading", - "subtype": "Sht20t", - "id": "tmp2", - "widget": "anydataTmp", - "page": "Сенсоры", - "descr": "Температура", - "int": 15, - "round": 1 - }, - { - "name": "Cенсор влажности Sht20", - "num": 4, - "type": "Reading", - "subtype": "Sht20h", - "id": "Hum2", - "widget": "anydataHum", - "page": "Сенсоры", - "descr": "Влажность", - "int": 15, - "round": 1 - } -] \ No newline at end of file diff --git a/src/modules/sensors/Sht20/modinfo.json b/src/modules/sensors/Sht20/modinfo.json new file mode 100644 index 00000000..ba5b9705 --- /dev/null +++ b/src/modules/sensors/Sht20/modinfo.json @@ -0,0 +1,50 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Cенсор температуры Sht20", + "type": "Reading", + "subtype": "Sht20t", + "id": "tmp2", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Температура", + "int": 15, + "round": 1 + }, + { + "name": "Cенсор влажности Sht20", + "type": "Reading", + "subtype": "Sht20h", + "id": "Hum2", + "widget": "anydataHum", + "page": "Сенсоры", + "descr": "Влажность", + "int": 15, + "round": 1 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "Sht20", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значения температуры и влажности с Sht20.", + "propInfo": { + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "robtillaart/SHT2x@^0.1.1" + ], + "esp8266_4mb": [ + "robtillaart/SHT2x@^0.1.1" + ] + } +} \ No newline at end of file diff --git a/src/modules/sensors/Sht20/platformio.ini b/src/modules/sensors/Sht20/platformio.ini deleted file mode 100644 index aeb22d50..00000000 --- a/src/modules/sensors/Sht20/platformio.ini +++ /dev/null @@ -1,7 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - robtillaart/SHT2x@^0.1.1 - -[env:esp32_4mb] -lib_deps = - robtillaart/SHT2x@^0.1.1 diff --git a/src/modules/sensors/Sonar/Sonar.cpp b/src/modules/sensors/Sonar/Sonar.cpp new file mode 100644 index 00000000..90f6b091 --- /dev/null +++ b/src/modules/sensors/Sonar/Sonar.cpp @@ -0,0 +1,49 @@ +#include "Global.h" +#include "classes/IoTItem.h" + +extern IoTGpio IoTgpio; + + +class Sonar : public IoTItem { + private: + unsigned int _pinTrig, _pinEcho; + + public: + Sonar(String parameters): IoTItem(parameters) { + _pinTrig = jsonReadInt(parameters, "pinTrig"); + _pinEcho = jsonReadInt(parameters, "pinEcho"); + + pinMode(_pinTrig, OUTPUT); + pinMode(_pinEcho, INPUT); + } + + void doByInterval() { + // value.valD = IoTgpio.analogRead(_pin); + // для большей точности установим значение LOW на пине Trig + digitalWrite(_pinTrig, LOW); + delayMicroseconds(2); + // Теперь установим высокий уровень на пине Trig + digitalWrite(_pinTrig, HIGH); + // Подождем 10 μs + delayMicroseconds(10); + digitalWrite(_pinTrig, LOW); + // Рассчитаем расстояние + value.valD = pulseIn(_pinEcho, HIGH) / 58; + // Выведем значение в Serial Monitor + Serial.print(value.valD); + Serial.println(" cm"); + + regEvent(value.valD, "Sonar"); + } + + ~Sonar() {}; +}; + + +void* getAPI_Sonar(String subtype, String param) { + if (subtype == F("Sonar")) { + return new Sonar(param); + } else { + return nullptr; + } +} diff --git a/src/modules/sensors/Sonar/modinfo.json b/src/modules/sensors/Sonar/modinfo.json new file mode 100644 index 00000000..ac877d83 --- /dev/null +++ b/src/modules/sensors/Sonar/modinfo.json @@ -0,0 +1,40 @@ +{ + "menuSection": "Сенсоры", + + "configItem": [{ + "name": "Сонар HC-SR04", + "num": 1, + "type": "Reading", + "subtype": "Sonar", + "id": "sonar", + "widget": "anydataTmp", + "page": "Сенсоры", + "descr": "Расстояние (см)", + + "pinTrig": 5, + "pinEcho": 4, + "int": 5 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "Sonar", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет получить значение расстояния до препятствия с использованием ультразвукового датчика (в сантиметрах).", + "propInfo": { + "pinTrig": "GPIO контакта Trig", + "pinEcho": "GPIO контакта Echo", + "int": "Количество секунд между опросами датчика." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [], + "esp8266_4mb": [] + } +} \ No newline at end of file diff --git a/src/modules/sensors/items.json b/src/modules/sensors/items.json deleted file mode 100644 index 601b4be8..00000000 --- a/src/modules/sensors/items.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "header": "Сенсоры" - } -] \ No newline at end of file diff --git a/src/modules/system/IarduinoRTC/IarduinoRTC.cpp b/src/modules/system/IarduinoRTC/IarduinoRTC.cpp new file mode 100644 index 00000000..b2cbb936 --- /dev/null +++ b/src/modules/system/IarduinoRTC/IarduinoRTC.cpp @@ -0,0 +1,112 @@ +#include "Global.h" +#include "classes/IoTItem.h" +#include "classes/IoTRTC.h" + +#include +#include "iarduino_RTC_DS1302.h" // Подключаем файл iarduino_RTC_DS1302.h +#include "iarduino_RTC_DS1307.h" // Подключаем файл iarduino_RTC_DS1307.h +#include "iarduino_RTC_DS3231.h" // Подключаем файл iarduino_RTC_DS3231.h +#include "iarduino_RTC_RX8025.h" + +extern IoTRTC *watch; + + +class IarduinoRTC : public IoTItem { + private: + int _chipNum, _rst, _clk, _dat, _ticker; + String _defFormat; + iarduino_RTC_BASE *RTCDriver; + + public: + + IarduinoRTC(String parameters): IoTItem(parameters) { + jsonRead(parameters, "chipNum", _chipNum); + jsonRead(parameters, "rst", _rst); + jsonRead(parameters, "clk", _clk); + jsonRead(parameters, "dat", _dat); + jsonRead(parameters, "defFormat", _defFormat); + jsonRead(parameters, "ticker", _ticker); + + switch (_chipNum) { + case 0: + RTCDriver = new iarduino_RTC_NTP(); + break; + case 1: + RTCDriver = new iarduino_RTC_DS1302(_rst, _clk, _dat); + break; + case 2: + RTCDriver = new iarduino_RTC_DS1307(); + break; + case 3: + RTCDriver = new iarduino_RTC_DS3231(); + break; + case 4: + RTCDriver = new iarduino_RTC_RX8025(); + break; + } + if (RTCDriver) RTCDriver->begin(); + } + + void doByInterval() { + value.isDecimal = false; + value.valS = watch->gettime(_defFormat.c_str()); + if (_ticker) regEvent(value.valS, "time ticker"); + } + + IoTValue execute(String command, std::vector ¶m) { + IoTValue tmpValue; + if (command == "getTime") { + if (param.size()) { + tmpValue.isDecimal = false; + tmpValue.valS = watch->gettime(param[0].valS.c_str()); + return tmpValue; + } + } else if (command == "saveSysTime") { + tm localTimeVar; + time_t timeNowVar; + time(&timeNowVar); + localTimeVar = *localtime(&timeNowVar); + watch->settime(localTimeVar.tm_sec, localTimeVar.tm_min, localTimeVar.tm_hour, localTimeVar.tm_mday, localTimeVar.tm_mon+1, localTimeVar.tm_year-100, localTimeVar.tm_wday); + } else if (command == "setTime") { + if (param.size()) { + watch->settime(param[0].valD, param[1].valD, param[2].valD, param[3].valD, param[4].valD, param[5].valD, param[6].valD); + } + } else if (command == "setUnixTime") { + if (param.size()) { + watch->settimeUnix(param[0].valD); + } + } else if (command == "getHours") { + tmpValue.valD = watch->Hours; // Часы 0-23 + return tmpValue; + } else if (command == "getMinutes") { + tmpValue.valD = watch->minutes; // Минуты 0-59 + return tmpValue; + } else if (command == "getSeconds") { + tmpValue.valD = watch->seconds; // Секунды 0-59 + return tmpValue; + } else if (command == "getMonth") { + tmpValue.valD = watch->month; // Месяц 1-12 + return tmpValue; + } else if (command == "getDay") { + tmpValue.valD = watch->day; // День месяца 1-31 + return tmpValue; + } + + return {}; + } + + iarduino_RTC_BASE* getRtcDriver() { + return RTCDriver; + } + + ~IarduinoRTC() {}; +}; + + +void* getAPI_IarduinoRTC(String subtype, String param) { + if (subtype == F("IarduinoRTC")) { + return new IarduinoRTC(param); + } else { + return nullptr; + } +} diff --git a/src/modules/system/IarduinoRTC/modinfo.json b/src/modules/system/IarduinoRTC/modinfo.json new file mode 100644 index 00000000..568f0ed9 --- /dev/null +++ b/src/modules/system/IarduinoRTC/modinfo.json @@ -0,0 +1,47 @@ +{ + "menuSection": "Расширения", + + "configItem": [{ + "name": "Поддержка DS1302(1), DS1307(2), DS3231(3), RX8025(4)", + "type": "Reading", + "subtype": "IarduinoRTC", + "id": "RTC", + "widget": "", + "page": "", + "descr": "", + + "int": "1", + "chipNum": 1, + "rst": 16, + "clk": 5, + "dat": 4, + "defFormat": "d-m-Y", + "ticker": 0 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "Sergey @Serghei63", + "moduleName": "IarduinoRTC", + "moduleVersion": "1.0", + "moduleDesc": "Позволяет использовать часы реального времени в виде внешнего физического модуля или виртуального с синхронизацией через сеть Интернет.", + "propInfo": { + "int": "Период времени в секундах между опросами времени с RTC", + "chipNum": "Выбор источника: 0 - время с Интернет, 1 - модуль DS1302, 2 - модуль DS1307, 3 - модуль DS3231, 4 - модуль RX38025", + "rst": "Номер пина для подключения вашего модуля часов. (не всегда используется).", + "clk": "Номер пина для SDL вашего модуля часов", + "dat": "Номер пина для SDA вашего модуля часов", + "defFormat": "Вывод информации в формате defFormat", + "ticker": "Генерировать(1) или нет(0) события при каждом тике модуля = int. Позволяет не применять модуль таймера, если нужно просто тактировать работу." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [], + "esp8266_4mb": [] + } +} \ No newline at end of file diff --git a/src/modules/system/Mcp23017/items.json b/src/modules/system/Mcp23017/items.json deleted file mode 100644 index 8c44661c..00000000 --- a/src/modules/system/Mcp23017/items.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "name": "Расширитель портов Mcp23017", - "num": 29, - "type": "Reading", - "subtype": "Mcp23017", - "id": "Mcp", - "widget": "", - "page": "", - "descr": "", - - "int": "0", - "addr": "0x20", - "index": 1 - } -] \ No newline at end of file diff --git a/src/modules/system/Mcp23017/modinfo.json b/src/modules/system/Mcp23017/modinfo.json new file mode 100644 index 00000000..0d3df2c1 --- /dev/null +++ b/src/modules/system/Mcp23017/modinfo.json @@ -0,0 +1,45 @@ +{ + "menuSection": "Расширения", + + "configItem": [{ + "name": "Расширитель портов Mcp23017", + "type": "Reading", + "subtype": "Mcp23017", + "id": "Mcp", + "widget": "", + "page": "", + "descr": "", + + "int": "0", + "addr": "0x20", + "index": 1 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "Mcp23017", + "moduleVersion": "1.0", + "moduleDesc": "Добавляет в систему дополнительные GPIO для элементов, которые поддерживают такую функцию.", + "propInfo": { + "int": "Не используется", + "addr": "Адрес устройства на шине, обычно 0x20", + "index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д." + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [ + "adafruit/Adafruit MCP23017 Arduino Library@^2.0.2", + "adafruit/Adafruit BusIO @ ^1.13.0" + ], + "esp8266_4mb": [ + "adafruit/Adafruit MCP23017 Arduino Library@^2.0.2", + "adafruit/Adafruit BusIO @ ^1.13.0" + ] + } +} \ No newline at end of file diff --git a/src/modules/system/Mcp23017/platformio.ini b/src/modules/system/Mcp23017/platformio.ini deleted file mode 100644 index 77357a41..00000000 --- a/src/modules/system/Mcp23017/platformio.ini +++ /dev/null @@ -1,8 +0,0 @@ -[env:esp8266_4mb] -lib_deps = - adafruit/Adafruit MCP23017 Arduino Library@^2.0.2 - -[env:esp32_4mb] -lib_deps = - adafruit/Adafruit MCP23017 Arduino Library@^2.0.2 - diff --git a/src/modules/system/SysExt/SysExt.cpp b/src/modules/system/SysExt/SysExt.cpp index 6686ebaa..9c233202 100644 --- a/src/modules/system/SysExt/SysExt.cpp +++ b/src/modules/system/SysExt/SysExt.cpp @@ -1,5 +1,7 @@ #include "Global.h" #include "classes/IoTItem.h" +#include "classes/IoTRTC.h" +extern IoTRTC *watch; // Пример модуля расширения возможностей системы на примере добавления новых команд в сценарии // При комбинации использования doByInterval() и execute() можно обеспечить интеграцию с внешними сервисами, такими как Telegram, например. @@ -37,6 +39,12 @@ class SysExt : public IoTItem { value.valD = IoTgpio.digitalRead(param[0].valD); return value; } + } else if (command == "analogRead") { + if (param.size()) { + IoTgpio.pinMode(param[0].valD, INPUT); + value.valD = IoTgpio.analogRead(param[0].valD); + return value; + } } else if (command == "digitalWrite") { if (param.size() == 2) { IoTgpio.pinMode(param[0].valD, OUTPUT); @@ -49,7 +57,72 @@ class SysExt : public IoTItem { IoTgpio.digitalInvert(param[0].valD); return {}; } + } else if (command == "getTime") { + if (param.size()) { + value.isDecimal = false; + value.valS = watch->gettime(param[0].valS.c_str()); + return value; + } + } else if (command == "getHours") { + value.valD = watch->Hours; // Часы 0-23 + value.isDecimal = true; + return value; + } else if (command == "getMinutes") { + value.valD = watch->minutes; // Минуты 0-59 + value.isDecimal = true; + return value; + } else if (command == "getSeconds") { + value.valD = watch->seconds; // Секунды 0-59 + value.isDecimal = true; + return value; + } else if (command == "getMonth") { + value.valD = watch->month; // Месяц 1-12 + value.isDecimal = true; + return value; + } else if (command == "getDay") { + value.valD = watch->day; // День месяца 1-31 + value.isDecimal = true; + return value; + } else if (command == "deepSleep") { + if (param.size()) { + Serial.printf("Ушел спать на %d сек...", (int)param[0].valD); + #ifdef ESP32 + esp_sleep_enable_timer_wakeup(param[0].valD * 1000000); + delay(1000); + esp_deep_sleep_start(); + #else + ESP.deepSleep(param[0].valD * 1000000); + #endif + } + return {}; } + // } else if (command == "ModemSleep") { + // Serial.printf("Выключил все радио..."); + // #ifdef ESP32 + // WiFi.setSleep(true); + // if (!setCpuFrequencyMhz(80)){ + // Serial2.println("Not valid frequency!"); + // } + // #else + // //WiFi.disconnect(); + // adc_power_off(); + // WiFi.disconnect(true); // Disconnect from the network + // WiFi.mode(WIFI_OFF); // Switch WiFi off + // #endif + // return {}; + // } else if (command == "ModemWakeup") { + // Serial.printf("Включил все радио..."); + // #ifdef ESP32 + // setCpuFrequencyMhz(240); + // #else + // WiFi.forceSleepWake(); + // delay(1); + // // восстанавливаем коннект тут + + // wifi_set_sleep_type(NONE_SLEEP_T); + // #endif + // return {}; + // } return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки } diff --git a/src/modules/system/SysExt/items.json b/src/modules/system/SysExt/items.json deleted file mode 100644 index 9ee6a261..00000000 --- a/src/modules/system/SysExt/items.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "name": "Доп. функции системы", - "num": 27, - "type": "Reading", - "subtype": "SysExt", - "id": "SysExt", - "widget": "", - "page": "", - "descr": "", - "int": 15 - } -] \ No newline at end of file diff --git a/src/modules/system/SysExt/modinfo.json b/src/modules/system/SysExt/modinfo.json new file mode 100644 index 00000000..53166d97 --- /dev/null +++ b/src/modules/system/SysExt/modinfo.json @@ -0,0 +1,34 @@ +{ + "menuSection": "Расширения", + + "configItem": [{ + "name": "Доп. функции системы", + "type": "Reading", + "subtype": "SysExt", + "id": "SysExt", + "widget": "", + "page": "", + "descr": "", + "int": 15 + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "SysExt", + "moduleVersion": "1.0", + "moduleDesc": "Добавляет в систему дополнительные функции. Например, возможность прямого управления GPIO из сценариев.", + "propInfo": { + "int": "Не используется" + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [], + "esp8266_4mb": [] + } +} \ No newline at end of file diff --git a/src/modules/system/Variable/Variable.cpp b/src/modules/system/Variable/Variable.cpp index e0d8b111..4b97b22e 100644 --- a/src/modules/system/Variable/Variable.cpp +++ b/src/modules/system/Variable/Variable.cpp @@ -3,13 +3,21 @@ class Variable : public IoTItem { + private: + public: - Variable(String parameters): IoTItem(parameters) { } + Variable(String parameters): IoTItem(parameters) { + + } // особенность данного модуля - просто хранение значения для сценария, нет событий // void setValue(IoTValue Value) { // value = Value; // } + + void doByInterval() { + + } }; void* getAPI_Variable(String subtype, String param) { diff --git a/src/modules/system/Variable/items.json b/src/modules/system/Variable/items.json deleted file mode 100644 index d86f6d58..00000000 --- a/src/modules/system/Variable/items.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "name": "Переменная", - "num": 30, - "type": "Reading", - "subtype": "Variable", - "id": "var", - "widget": "", - "page": "", - "descr": "", - - "int": "0", - "val": "0" - } -] \ No newline at end of file diff --git a/src/modules/system/Variable/modinfo.json b/src/modules/system/Variable/modinfo.json new file mode 100644 index 00000000..2a2bfb47 --- /dev/null +++ b/src/modules/system/Variable/modinfo.json @@ -0,0 +1,37 @@ +{ + "menuSection": "Расширения", + + "configItem": [{ + "name": "Переменная", + "type": "Reading", + "subtype": "Variable", + "id": "var", + "widget": "", + "page": "", + "descr": "", + + "int": "0", + "val": "0" + }], + + "about": { + "authorName": "Ilya Belyakov", + "authorContact": "https://t.me/Biveraxe", + "authorGit": "https://github.com/biveraxe", + "specialThanks": "", + "moduleName": "Variable", + "moduleVersion": "1.0", + "moduleDesc": "Специальный системный модуль для использования переменных в процессе автоматизации как элементов конфигурации.", + "propInfo": { + "int": "Не используется", + "val": "Не используется" + } + }, + + "defActive": true, + + "devices": { + "esp32_4mb": [], + "esp8266_4mb": [] + } +} \ No newline at end of file diff --git a/src/modules/system/items.json b/src/modules/system/items.json deleted file mode 100644 index 18bf3b6a..00000000 --- a/src/modules/system/items.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "header": "Расширения" - } -] \ No newline at end of file diff --git a/src/utils/I2CUtils.cpp b/src/utils/I2CUtils.cpp new file mode 100644 index 00000000..9d3f9032 --- /dev/null +++ b/src/utils/I2CUtils.cpp @@ -0,0 +1,35 @@ +#include +#include "utils/SerialPrint.h" + +void scanI2C() { + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 8; address < 127; address++ ){ + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0){ + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.print(address,HEX); + Serial.println(" !"); + + nDevices++; + } + else if (error==4) { + Serial.print("Unknow error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + else + Serial.println("done\n"); +} \ No newline at end of file diff --git a/src/utils/SerialPrint.cpp b/src/utils/SerialPrint.cpp index 7a2e9b40..ed4c7cbc 100644 --- a/src/utils/SerialPrint.cpp +++ b/src/utils/SerialPrint.cpp @@ -1,8 +1,15 @@ #include "utils/SerialPrint.h" +#include "classes/IoTRTC.h" + +extern IoTRTC *watch; void SerialPrint(String errorLevel, String module, String msg) { - String tosend = prettyMillis(millis()) + " [" + errorLevel + "] [" + module + "] " + msg; + String tosend; + if (watch) tosend = watch->gettime("d.m.y H:i:s"); + else tosend = prettyMillis(millis()); + + tosend = tosend + " [" + errorLevel + "] [" + module + "] " + msg; Serial.println(tosend); if (isNetworkActive()) { diff --git a/src/utils/WiFiUtils.cpp b/src/utils/WiFiUtils.cpp index 787618b8..99daaacd 100644 --- a/src/utils/WiFiUtils.cpp +++ b/src/utils/WiFiUtils.cpp @@ -63,7 +63,7 @@ bool startAPMode() { if (jsonReadInt(errorsHeapJson, "passer") != 1) { ts.add( - WIFI_SCAN, 10 * 1000, [&](void*) { + WIFI_SCAN, 30 * 1000, [&](void*) { String sta_ssid = jsonReadStr(settingsFlashJson, "routerssid"); SerialPrint("i", "WIFI", "scanning for " + sta_ssid); diff --git a/training/QueueFromChar.cpp b/training/QueueFromChar.cpp deleted file mode 100644 index 3d7a4bc3..00000000 --- a/training/QueueFromChar.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifdef QUEUE_FROM_CHAR -#include "classes/QueueFromChar.h" - -QueueFromChar::QueueFromChar() { - commandList = NULL; - commandCount = 0; -} -QueueFromChar::~QueueFromChar() {} - -//добавление команды в буфер -void QueueFromChar::addCommand(const char* command) { - commandList = (CharBufferStruct*)realloc(commandList, (commandCount + 1) * sizeof(CharBufferStruct)); - strncpy(commandList[commandCount].command, command, MAX_COMMAND_LENGTH); - Serial.println("command added: " + String(command) + " " + String(commandCount)); - commandCount++; -} - -//распечатаем все добавленные команды -void QueueFromChar::printCommands() { - if (commandCount > 0 && commandList != NULL) { - for (int i = 0; i < commandCount; i++) { - Serial.println(commandList[i].command); - } - } -} - -//заберем последнюю из положенных в буфер команд -String QueueFromChar::getLastCommand() { - String ret = "empty"; - if (commandList != NULL) { - int cnt = commandCount - 1; - ret = commandList[cnt].command; - if (cnt > 0) { - delete commandList[cnt].command; - } else if (cnt == 0) { - commandList = NULL; - } - Serial.println("command deleted: " + ret + " " + String(cnt)); - commandCount--; - } - return ret; -} - -// QueueFromChar* myBuf; - -#endif diff --git a/training/QueueFromChar.h b/training/QueueFromChar.h deleted file mode 100644 index c16b799e..00000000 --- a/training/QueueFromChar.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "Global.h" -#ifdef QUEUE_FROM_CHAR - -#define MAX_COMMAND_LENGTH 16 -#define BUFFER 128 - -class QueueFromChar; - -class QueueFromChar { - public: - QueueFromChar(); - ~QueueFromChar(); - - void addCommand(const char* command); - - void printCommands(); - - String getLastCommand(); - - private: - struct CharBufferStruct { - char command[MAX_COMMAND_LENGTH + 1]; - }; - CharBufferStruct* commandList; - int commandCount = 0; -}; - -// extern QueueFromChar* myBuf; - -//========проверка очереди===================== -// myBuf = new QueueFromChar; -// myBuf->addCommand("zero"); -// myBuf->addCommand("one"); -// myBuf->addCommand("two"); -// myBuf->printCommands(); -// myBuf->getLastCommand(); -// myBuf->getLastCommand(); -// myBuf->getLastCommand(); -// myBuf->printCommands(); - -#endif diff --git a/training/QueueFromInstance.cpp b/training/QueueFromInstance.cpp deleted file mode 100644 index 69321913..00000000 --- a/training/QueueFromInstance.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifdef QUEUE_FROM_INST -#include "classes/QueueFromInstance.h" - -QueueFromInstance::QueueFromInstance() {} -QueueFromInstance::~QueueFromInstance() {} - -//добавим элемент в конец очереди -void QueueFromInstance::push(QueueInstance instance) { - queue1.push(instance); -} - -//удалим элемент из начала очереди -void QueueFromInstance::pop() { - if (!queue1.empty()) { - queue1.pop(); - } -} - -//вернуть элемент из начала очереди и удалить его -QueueInstance QueueFromInstance::front() { - QueueInstance instance(""); - if (!queue1.empty()) { - instance = queue1.front(); - queue1.pop(); - } - return instance; -} - -// QueueFromInstance* myQueue; -#endif diff --git a/training/QueueFromInstance.h b/training/QueueFromInstance.h deleted file mode 100644 index 0a509bf8..00000000 --- a/training/QueueFromInstance.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "Global.h" -#ifdef QUEUE_FROM_INST -#include "classes/QueueInst.h" -#include -#include - -using namespace std; - -class QueueFromInstance; - -class QueueFromInstance { - public: - QueueFromInstance(); - ~QueueFromInstance(); - - void push(QueueInstance instance); - void pop(); - QueueInstance front(); - - private: - queue queue1; -}; - -// extern QueueFromInstance* myQueue; -#endif \ No newline at end of file diff --git a/training/QueueFromStruct.cpp b/training/QueueFromStruct.cpp deleted file mode 100644 index 52c5fb4c..00000000 --- a/training/QueueFromStruct.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "classes/QueueFromStruct.h" -#ifdef QUEUE_FROM_STR -QueueFromStruct::QueueFromStruct() {} -QueueFromStruct::~QueueFromStruct() {} - -//добавим элемент в конец очереди -void QueueFromStruct::push(QueueItems word) { - queue1.push(word); -} - -//удалим элемент из начала очереди -void QueueFromStruct::pop() { - if (!queue1.empty()) { - queue1.pop(); - } -} - -//вернуть элемент из начала очереди и удалить его -QueueItems QueueFromStruct::front() { - if (!queue1.empty()) { - tmpItem = queue1.front(); - queue1.pop(); - } - return tmpItem; -} - -bool QueueFromStruct::empty() { - return queue1.empty(); -} - -QueueFromStruct* filesQueue; -#endif diff --git a/training/QueueFromStruct.h b/training/QueueFromStruct.h deleted file mode 100644 index d51de82f..00000000 --- a/training/QueueFromStruct.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include "Global.h" -#ifdef QUEUE_FROM_STR -#include -//#include долбанный стрим сука - -using namespace std; - -struct QueueItems { - String myword; - uint8_t num; -}; - -class QueueFromStruct; - -class QueueFromStruct { - public: - QueueFromStruct(); - ~QueueFromStruct(); - - void push(QueueItems word); - void pop(); - QueueItems front(); - bool empty(); - - private: - queue queue1; - QueueItems tmpItem; -}; - -extern QueueFromStruct* filesQueue; - -//=======проверка очереди из структур================= -// myQueueStruct = new QueueFromStruct; -// QueueItems myItem; -// myItem.myword = "word1"; -// myQueueStruct->push(myItem); -// myItem.myword = "word2"; -// myQueueStruct->push(myItem); -// myItem.myword = "word3"; -// myQueueStruct->push(myItem); -// Serial.println(myQueueStruct->front().myword); -// Serial.println(myQueueStruct->front().myword); -// Serial.println(myQueueStruct->front().myword); - -#endif diff --git a/training/QueueInst.cpp b/training/QueueInst.cpp deleted file mode 100644 index 7439f3a5..00000000 --- a/training/QueueInst.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifdef QUEUE_FROM_INST -#include "queue/QueueInst.h" - -QueueInstance::QueueInstance(String text) { - _text = text; -} -QueueInstance::~QueueInstance() {} - -String QueueInstance::get() { - return _text; -} - -//========проверка очереди из экземпляров====== - -// myQueue = new QueueFromInstance; - -// myQueue->push(QueueInstance("text1")); -// myQueue->push(QueueInstance("text2")); -// myQueue->push(QueueInstance("text3")); - -// Serial.println(myQueue->front().get()); -// Serial.println(myQueue->front().get()); -// Serial.println(myQueue->front().get()); -#endif \ No newline at end of file diff --git a/training/QueueInst.h b/training/QueueInst.h deleted file mode 100644 index 9731980c..00000000 --- a/training/QueueInst.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "Global.h" -#ifdef QUEUE_FROM_INST -#include -#include - -using namespace std; - -class QueueInstance; - -class QueueInstance { - public: - QueueInstance(String text); - ~QueueInstance(); - - String get(); - - private: - String _text; -}; -#endif diff --git a/training/SendJson.cpp b/training/SendJson.cpp deleted file mode 100644 index 9a7af2fb..00000000 --- a/training/SendJson.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "classes/SendJson.h" -#ifdef QUEUE_FROM_STR - -SendJson::SendJson() { - filesQueue = new QueueFromStruct; -} -SendJson::~SendJson() {} - -void SendJson::addFileToQueue(String path, uint8_t num) { - myItem.myword = path; - myItem.num = num; - filesQueue->push(myItem); - SerialPrint(F("i"), F("WS"), "file added to Queue " + path); -} - -//опсылает массив json по объектно в сокеты -void SendJson::loop() { - if (!filesQueue->empty() && !sendingInProgress) { - Serial.println("Queue not empty"); - myItem = filesQueue->front(); - _path = myItem.myword; - _num = myItem.num; - file = seekFile(_path); - SerialPrint(F("i"), F("WS"), "seek File to WS " + _path); - sendingInProgress = true; - } - if (file.available()) { - String jsonArrayElement = _path + file.readStringUntil('}') + "}"; - sendWs(jsonArrayElement); - } else { - sendingInProgress = false; - } -} - -void SendJson::sendWs(String& jsonArrayElement) { - standWebSocket.sendTXT(_num, jsonArrayElement); -} - -void SendJson::sendMqtt(String& jsonArrayElement) { - // mqtt send to do -} - -SendJson* sendJsonFiles; -#endif \ No newline at end of file diff --git a/training/SendJson.h b/training/SendJson.h deleted file mode 100644 index 0fabea32..00000000 --- a/training/SendJson.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "Global.h" -#ifdef QUEUE_FROM_STR -#include "classes/QueueFromStruct.h" - -class SendJson; - -class SendJson { - public: - SendJson(); - ~SendJson(); - - void addFileToQueue(String path, uint8_t num); - - void loop(); - - void sendWs(String& jsonArrayElement); - - void sendMqtt(String& jsonArrayElement); - - QueueItems myItem; - - private: - File file; - String _path; - uint8_t _num; - bool sendingInProgress = false; -}; - -extern SendJson* sendJsonFiles; -#endif diff --git a/training/info.txt b/training/info.txt deleted file mode 100644 index b7cb2d9e..00000000 --- a/training/info.txt +++ /dev/null @@ -1,8 +0,0 @@ -здесь пишу статистику по остатку оперативной памяти после глобальных изменений - -22.12.21 пустой код без wifi остаток = 50.28 kB -22.12.21 запустил wifi остаток = 48.59 kB -22.12.21 добавил асинхронный веб сервер = 38.36 kB -22.12.21 добавил web sockets = 37.63 kB - -20.01.22 стандартный сервер mqtt в работе = 41.00 kb \ No newline at end of file