Merge pull request #290 from IoTManagerProject/ver4dev

Updating of stable branch
This commit is contained in:
IoT Manager
2023-09-02 20:28:33 +02:00
committed by GitHub
105 changed files with 9224 additions and 331 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,2 @@
.pio
.vscode
/myProfile_wm.json

View File

@@ -16,6 +16,7 @@
# поддерживаемые контроллеры (профили):
# esp8266_4mb
# esp32_4mb
# esp32s2_4mb
# esp8266_1mb
# esp8266_1mb_ota
# esp8285_1mb
@@ -23,6 +24,7 @@
# esp8266_2mb
# esp8266_2mb_ota
import configparser
import os, json, sys, getopt
from pathlib import Path

Binary file not shown.

Binary file not shown.

View File

@@ -4,12 +4,12 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>IoT Manager 4.4.4</title>
<title>IoT Manager 4.5.0</title>
<link rel="icon" type="image/png" href="/favicon.ico" />
<link rel="stylesheet" href="/build/bundle.css?444" />
<link rel="stylesheet" href="/build/bundle.css?450" />
<script defer src="/build/bundle.js?444"></script>
<script defer src="/build/bundle.js?450"></script>
</head>
<body></body>

View File

@@ -819,14 +819,15 @@
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"widget": "inputTxt",
"page": "Экраны",
"descr": "LCD Экран",
"addr": "0x27",
"size": "20,4",
"coord": "0,0",
"id2show": "id датчика",
"id2show": "",
"prefix": "",
"postfix": "",
"num": 54
},
{
@@ -834,14 +835,15 @@
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"widget": "inputTxt",
"page": "Экраны",
"descr": "LCD Экран",
"addr": "0x27",
"size": "16,2",
"coord": "0,0",
"id2show": "id датчика",
"id2show": "",
"prefix": "",
"postfix": "",
"num": 55
}
]

View File

@@ -3,7 +3,7 @@
"name": "IoTmanagerVer4",
"apssid": "IoTmanager",
"appass": "",
"routerssid": "rise",
"routerssid": "iot",
"routerpass": "hostel3333",
"timezone": 2,
"ntp": "pool.ntp.org",
@@ -25,7 +25,7 @@
"projectProp": {
"platformio": {
"default_envs": "esp8266_4mb",
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota"
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota"
}
},
"modules": {
@@ -34,6 +34,10 @@
"path": "src/modules/virtual/Cron",
"active": true
},
{
"path": "src/modules/virtual/GoogleSheet",
"active": false
},
{
"path": "src/modules/virtual/Loging",
"active": true
@@ -112,6 +116,10 @@
"path": "src/modules/sensors/DS2401",
"active": false
},
{
"path": "src/modules/sensors/Ds2423",
"active": false
},
{
"path": "src/modules/sensors/Emon",
"active": false
@@ -152,6 +160,10 @@
"path": "src/modules/sensors/IoTWiegand",
"active": false
},
{
"path": "src/modules/sensors/ld2410",
"active": false
},
{
"path": "src/modules/sensors/Max6675",
"active": false
@@ -160,6 +172,10 @@
"path": "src/modules/sensors/Mhz19",
"active": false
},
{
"path": "src/modules/sensors/Ntc",
"active": false
},
{
"path": "src/modules/sensors/Pzem004t",
"active": true
@@ -176,6 +192,10 @@
"path": "src/modules/sensors/S8",
"active": true
},
{
"path": "src/modules/sensors/Scd40",
"active": false
},
{
"path": "src/modules/sensors/Sds011",
"active": false
@@ -222,6 +242,10 @@
"path": "src/modules/exec/EspCam",
"active": false
},
{
"path": "src/modules/exec/Ftp",
"active": false
},
{
"path": "src/modules/exec/HttpGet",
"active": false
@@ -296,6 +320,10 @@
"path": "src/modules/display/NextionUpload",
"active": false
},
{
"path": "src/modules/display/Smi2_m",
"active": true
},
{
"path": "src/modules/display/Ws2812b",
"active": false

View File

@@ -2,7 +2,7 @@
"name": "IoTmanagerVer4",
"apssid": "IoTmanager",
"appass": "",
"routerssid": "rise",
"routerssid": "iot",
"routerpass": "hostel3333",
"timezone": 2,
"ntp": "pool.ntp.org",
@@ -21,5 +21,6 @@
"pinSDA": 0,
"i2cFreq": 100000,
"wg": "group1",
"udps": 1,
"settings_": ""
}

View File

@@ -245,6 +245,17 @@
"max": 100,
"debounce": 500
},
{
"name": "range",
"label": "Ползунок (Servo)",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 1,
"min": 0,
"max": 180,
"debounce": 500
},
{
"name": "select",
"label": "Выпадающий",

View File

@@ -8,14 +8,14 @@
<link rel="icon" type="image/png" href="/favicon.ico" />
<link
rel="stylesheet"
href="https://iotmanager.org/esp01ota/build/bundle.css?443"
href="https://iotmanager.org/esp01ota/build/bundle.css?450"
/>
</head>
<body>
<script>
let script = document.createElement("script");
script.src = "https://iotmanager.org/esp01ota/build/bundle.js?443";
script.src = "https://iotmanager.org/esp01ota/build/bundle.js?450";
script.onload = execute;
document.head.append(script);
script.onerror = error;

View File

@@ -20,5 +20,6 @@
"pinSDA": 0,
"i2cFreq": 100000,
"settings_": "",
"wg": "group1"
"wg": "group1",
"udps": 1
}

View File

@@ -0,0 +1,308 @@
[
{
"name": "anydataRed",
"label": "Сообщение1",
"widget": "anydata",
"icon": "body",
"color": "red",
"descrColor": "red"
},
{
"name": "anydataDgr",
"label": "Сообщение2",
"widget": "anydata",
"after": "",
"color": "red",
"icon": "walk"
},
{
"name": "anydataDef",
"label": "Текст",
"widget": "anydata",
"after": "",
"icon": ""
},
{
"name": "anydataVlt",
"label": "Вольты",
"widget": "anydata",
"after": "V",
"icon": "speedometer"
},
{
"name": "anydataAmp",
"label": "Амперы",
"widget": "anydata",
"after": "A",
"icon": "speedometer"
},
{
"name": "anydataWt",
"label": "Ватты",
"widget": "anydata",
"after": "Wt",
"icon": "speedometer",
"color": [
{
"level": 0,
"value": ""
},
{
"level": 200,
"value": "#009933"
},
{
"level": 2000,
"value": "#FF9900"
},
{
"level": 4000,
"value": "red"
}
]
},
{
"name": "anydataWth",
"label": "Энергия",
"widget": "anydata",
"after": "kWh",
"icon": "speedometer"
},
{
"name": "anydataHtz",
"label": "Герцы",
"widget": "anydata",
"after": "Hz",
"icon": "speedometer"
},
{
"name": "anydataTmp",
"label": "Температура",
"widget": "anydata",
"after": "°С",
"icon": "thermometer",
"font": "OCR A Std",
"color": [
{
"level": -20,
"value": "#0000CC"
},
{
"level": -10,
"value": "#0000CC"
},
{
"level": 0,
"value": "#0000CC"
},
{
"level": 12,
"value": "#3366FF"
},
{
"level": 16,
"value": "#33CCFF"
},
{
"level": 18,
"value": "#009933"
},
{
"level": 30,
"value": "#FF9900"
},
{
"level": 40,
"value": "red"
}
]
},
{
"name": "anydataMm",
"label": "Давление",
"widget": "anydata",
"after": "mm",
"icon": "speedometer"
},
{
"name": "anydataHum",
"label": "Влажность",
"widget": "anydata",
"after": "%",
"icon": "water",
"color": "#88AADF"
},
{
"name": "anydataTm",
"label": "Время",
"widget": "anydata",
"after": "",
"icon": "speedometer"
},
{
"name": "button",
"label": "Кнопка",
"widget": "btn",
"size": "large",
"color": "green",
"send": "test"
},
{
"name": "toggle",
"label": "Переключатель",
"widget": "toggle",
"icon": "",
"iconOff": ""
},
{
"name": "chart1",
"label": "График без точек",
"widget": "chart",
"dateFormat": "HH:mm",
"maxCount": 86400,
"pointRadius": 0
},
{
"name": "chart2",
"label": "График с точками",
"widget": "chart",
"maxCount": 86400,
"dateFormat": "HH:mm"
},
{
"name": "chart3",
"label": "График Дневной",
"widget": "chart",
"dateFormat": "DD.MM.YYYY",
"maxCount": 86400,
"type": "bar"
},
{
"name": "fillgauge",
"label": "Бочка",
"widget": "fillgauge",
"circleColor": "#00FFFF",
"textColor": "#FFFFFF",
"waveTextColor": "#000000",
"waveColor": "#00FFFF"
},
{
"name": "inputDate",
"label": "Ввод даты",
"widget": "input",
"size": "small",
"color": "orange",
"type": "date"
},
{
"name": "inputDgt",
"label": "Ввод числа",
"widget": "input",
"color": "blue",
"type": "number"
},
{
"name": "inputTxt",
"label": "Ввод текста",
"widget": "input",
"size": "small",
"color": "orange",
"type": "text"
},
{
"name": "inputTm",
"label": "Ввод времени",
"widget": "input",
"color": "blue",
"type": "time"
},
{
"name": "progressLine",
"label": "Статус линия",
"widget": "progress-line",
"icon": "sunny",
"max": "100",
"stroke": "10"
},
{
"name": "progressRound",
"label": "Статус круг",
"widget": "progress-round",
"max": "100",
"stroke": "20",
"color": "#45ccce",
"background": "#777",
"semicircle": "1"
},
{
"name": "range",
"label": "Ползунок",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 0.0977,
"min": 0,
"max": 100,
"debounce": 500
},
{
"name": "range",
"label": "Ползунок (Servo)",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 1,
"min": 0,
"max": 180,
"debounce": 500
},
{
"name": "select",
"label": "Выпадающий",
"widget": "select",
"options": [
"Выключен",
"Включен"
],
"status": 0
},
{
"name": "anydataPpm",
"label": "PPM",
"widget": "anydata",
"after": "ppm",
"icon": "speedometer"
},
{
"name": "anydatamAmp",
"label": "миллиАмперы",
"widget": "anydata",
"after": "mAmp",
"icon": "speedometer"
},
{
"name": "anydatamVlt",
"label": "миллиВольты",
"widget": "anydata",
"after": "mVlt",
"icon": "speedometer"
},
{
"name": "anydatamWt",
"label": "миллиВатты",
"widget": "anydata",
"after": "mWt",
"icon": "speedometer"
},
{
"name": "anydataCm",
"label": "Сантиметры",
"widget": "anydata",
"after": "cm",
"icon": "speedometer"
},
{
"name": "nil",
"label": "Без виджета"
}
]

View File

@@ -41,13 +41,31 @@
"label": "Ватты",
"widget": "anydata",
"after": "Wt",
"icon": "speedometer"
"icon": "speedometer",
"color": [
{
"level": 0,
"value": ""
},
{
"level": 200,
"value": "#009933"
},
{
"level": 2000,
"value": "#FF9900"
},
{
"level": 4000,
"value": "red"
}
]
},
{
"name": "anydataWth",
"label": "Энергия",
"widget": "anydata",
"after": "kWt/Hr",
"after": "kWh",
"icon": "speedometer"
},
{
@@ -62,7 +80,42 @@
"label": "Температура",
"widget": "anydata",
"after": "°С",
"icon": "thermometer"
"icon": "thermometer",
"font": "OCR A Std",
"color": [
{
"level": -20,
"value": "#0000CC"
},
{
"level": -10,
"value": "#0000CC"
},
{
"level": 0,
"value": "#0000CC"
},
{
"level": 12,
"value": "#3366FF"
},
{
"level": 16,
"value": "#33CCFF"
},
{
"level": 18,
"value": "#009933"
},
{
"level": 30,
"value": "#FF9900"
},
{
"level": 40,
"value": "red"
}
]
},
{
"name": "anydataMm",
@@ -192,6 +245,17 @@
"max": 100,
"debounce": 500
},
{
"name": "range",
"label": "Ползунок (Servo)",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 1,
"min": 0,
"max": 180,
"debounce": 500
},
{
"name": "select",
"label": "Выпадающий",
@@ -209,6 +273,34 @@
"after": "ppm",
"icon": "speedometer"
},
{
"name": "anydatamAmp",
"label": "миллиАмперы",
"widget": "anydata",
"after": "mAmp",
"icon": "speedometer"
},
{
"name": "anydatamVlt",
"label": "миллиВольты",
"widget": "anydata",
"after": "mVlt",
"icon": "speedometer"
},
{
"name": "anydatamWt",
"label": "миллиВатты",
"widget": "anydata",
"after": "mWt",
"icon": "speedometer"
},
{
"name": "anydataCm",
"label": "Сантиметры",
"widget": "anydata",
"after": "cm",
"icon": "speedometer"
},
{
"name": "nil",
"label": "Без виджета"

80
include/BuildTime.h Normal file
View File

@@ -0,0 +1,80 @@
/*
Парсинг и получение даты и времени компиляции из __DATE__ и __TIME__
Документация:
GitHub: https://github.com/GyverLibs/buildTime
Константы времени компиляции:
BUILD_YEAR - год
BUILD_MONTH - месяц
BUILD_DAY - день
BUILD_HOUR - час
BUILD_MIN - минута
BUILD_SEC - секунда
Исходник http://qaru.site/questions/186859/how-to-use-date-and-time-predefined-macros-in-as-two-integers-then-stringify
AlexGyver, alex@alexgyver.ru
https://alexgyver.ru/
MIT License
Версии:
v1.0 - релиз
*/
#ifndef buildTime_h
#define buildTime_h
// Example of __DATE__ string: "Jul 27 2012"
// 01234567890
#define BUILD_YEAR_CH0 (__DATE__[7] - '0')
#define BUILD_YEAR_CH1 (__DATE__[8] - '0')
#define BUILD_YEAR_CH2 (__DATE__[9] - '0')
#define BUILD_YEAR_CH3 (__DATE__[10] - '0')
#define BUILD_YEAR (BUILD_YEAR_CH0 * 1000 + BUILD_YEAR_CH1 * 100 + BUILD_YEAR_CH2 * 10 + BUILD_YEAR_CH3)
#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')
#define BUILD_MONTH \
( \
(BUILD_MONTH_IS_JAN) ? 1 : (BUILD_MONTH_IS_FEB) ? 2 \
: (BUILD_MONTH_IS_MAR) ? 3 \
: (BUILD_MONTH_IS_APR) ? 4 \
: (BUILD_MONTH_IS_MAY) ? 5 \
: (BUILD_MONTH_IS_JUN) ? 6 \
: (BUILD_MONTH_IS_JUL) ? 7 \
: (BUILD_MONTH_IS_AUG) ? 8 \
: (BUILD_MONTH_IS_SEP) ? 9 \
: (BUILD_MONTH_IS_OCT) ? 10 \
: (BUILD_MONTH_IS_NOV) ? 11 \
: (BUILD_MONTH_IS_DEC) ? 12 \
: /* error default */ '?')
#define BUILD_DAY_CH0 (((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') - '0')
#define BUILD_DAY_CH1 (__DATE__[5] - '0')
#define BUILD_DAY (BUILD_DAY_CH0 * 10 + BUILD_DAY_CH1)
// Example of __TIME__ string: "21:06:19"
// 01234567
#define BUILD_HOUR_CH0 (__TIME__[0] - '0')
#define BUILD_HOUR_CH1 (__TIME__[1] - '0')
#define BUILD_HOUR (BUILD_HOUR_CH0 * 10 + BUILD_HOUR_CH1)
#define BUILD_MIN_CH0 (__TIME__[3] - '0')
#define BUILD_MIN_CH1 (__TIME__[4] - '0')
#define BUILD_MIN (BUILD_MIN_CH0 * 10 + BUILD_MIN_CH1)
#define BUILD_SEC_CH0 (__TIME__[6] - '0')
#define BUILD_SEC_CH1 (__TIME__[7] - '0')
#define BUILD_SEC (BUILD_SEC_CH0 * 10 + BUILD_SEC_CH1)
#endif

View File

@@ -1,7 +1,8 @@
#pragma once
#include "BuildTime.h"
//Версия прошивки
#define FIRMWARE_VERSION 435
// Версия прошивки
#define FIRMWARE_VERSION 450
#ifdef esp8266_1mb_ota
#define FIRMWARE_NAME "esp8266_1mb_ota"
@@ -27,21 +28,33 @@
#define FIRMWARE_NAME "esp32_4mb"
#endif
//Размер буфера json
#define JSON_BUFFER_SIZE 2048 //держим 2 кб не меняем
#define WEB_SOCKETS_FRAME_SIZE 2048
#ifdef esp32s2_4mb
#define FIRMWARE_NAME "esp32s2_4mb"
#endif
//#define LOOP_DEBUG
// Размер буфера json
#define JSON_BUFFER_SIZE 4096 // держим 2 кб не меняем
//выбор сервера
//#define ASYNC_WEB_SERVER
//#define ASYNC_WEB_SOCKETS
/*
WEB_SOCKETS_FRAME_SIZE создан для того что бы не загружать оперативку.
Эта технология передаёт в сокеты большие файлы по частям.
Чем меньше этот фрейм тем теоретически лучше.
Но и сильно малый он тоже быть не должен.
Я опытным путём установил что размер 1024 является оптимальным. Можно так же поставить 2048
*/
#define WEB_SOCKETS_FRAME_SIZE 1024
// #define LOOP_DEBUG
// выбор сервера
// #define ASYNC_WEB_SERVER
// #define ASYNC_WEB_SOCKETS
#define STANDARD_WEB_SERVER
#define STANDARD_WEB_SOCKETS
#define UDP_ENABLED
//#define REST_FILE_OPERATIONS
// #define REST_FILE_OPERATIONS
#define MQTT_RECONNECT_INTERVAL 20000
@@ -54,7 +67,7 @@
#define MIN_DATETIME 1575158400
#define LEAP_YEAR(Y) (((1970 + Y) > 0) && !((1970 + Y) % 4) && (((1970 + Y) % 100) || !((1970 + Y) % 400)))
//задачи таскера
// задачи таскера
enum TimerTask_t { WIFI_SCAN,
WIFI_MQTT_CONNECTION_CHECK,
TIME,
@@ -66,14 +79,14 @@ enum TimerTask_t { WIFI_SCAN,
ST,
END };
//задачи которые надо протащить через loop
// задачи которые надо протащить через loop
enum NotAsyncActions {
do_ZERO,
do_MQTTPARAMSCHANGED,
do_LAST,
};
//состояния обновления
// состояния обновления
enum UpdateStates { NOT_STARTED,
UPDATE_FS_IN_PROGRESS,
UPDATE_FS_COMPLETED,
@@ -90,4 +103,4 @@ enum distination {
TO_MQTT_WS,
};
#define WS_BROADCAST -1
#define WS_BROADCAST -1

View File

@@ -2,7 +2,7 @@
#include "Global.h"
#ifdef ESP8266
//эта библиотека встроена в ядро
// эта библиотека встроена в ядро
#include "ESPAsyncUDP.h"
#else
#include "AsyncUDP.h"
@@ -11,7 +11,8 @@ extern AsyncUDP asyncUdp;
extern const String getThisDevice();
extern void addThisDeviceToList();
extern void asyncUdpInit();
extern void udpListningInit();
extern void udpBroadcastInit();
extern String uint8tToString(uint8_t* data, size_t len);
extern void udpPacketParse(String& data);
extern void jsonMergeArrays(String& existJson, String& incJson);

View File

@@ -1,6 +1,7 @@
#pragma once
#include "Global.h"
#ifdef ESP32
#include <rom/spi_flash.h>
#if USE_LITTLEFS
#include <LittleFS.h>
#define FileFS LittleFS
@@ -35,7 +36,7 @@ extern FS* filesystem;
extern bool fileSystemInit();
extern void globalVarsSync();
//extern String getParamsJson();
// extern String getParamsJson();
extern void syncSettingsFlashJson();
extern void syncValuesFlashJson();
@@ -47,3 +48,4 @@ extern uint32_t ESP_getChipId(void);
extern uint32_t ESP_getFlashChipId(void);
extern const String getMacAddress();
extern const String getWebVersion();
extern uint32_t getFlashChipIdNew();

View File

@@ -1,8 +1,8 @@
#pragma once
//константы
// константы
#include "Const.h"
//внешние глобальные директории
// внешние глобальные директории
#include <Arduino.h>
#include <ArduinoJson.h>
#include <TickerScheduler.h>
@@ -43,7 +43,7 @@
#include <FS.h>
//внутренние глобальные директории проекта
// внутренние глобальные директории проекта
#include "utils/FileUtils.h"
#include "utils/JsonUtils.h"
#include "utils/SerialPrint.h"

View File

@@ -18,4 +18,6 @@ void publishJsonWs(const String& topic, String& json);
void periodicWsSend();
void sendFileToWsByFrames(const String& filename, const String& header, const String& json, int client_id, size_t frameSize);
void sendStringToWs(const String& header, String& payload, int client_id);
void sendStringToWs(const String& header, String& payload, int client_id);
void sendDeviceList(uint8_t num);

View File

@@ -87,6 +87,7 @@ class IoTItem {
int _map3 = 0;
int _map4 = 0;
int _round = 1; // 1, 10, 100, 1000, 10000
int _numDigits = 1; // количество целых значений, не значимые позиции заменяются нулем в строковом формате
bool _global = false; // характеристика айтема, что ему нужно слать и принимать события из внешнего мира
};

View File

@@ -18,6 +18,7 @@ extern bool jsonRead(const String& json, String key, int& value, bool e = true);
extern String jsonReadStr(const String& json, String name, bool e = true);
extern int jsonReadInt(const String& json, String name, bool e = true);
long int jsonReadLInt(const String& json, String name, bool e=true);
extern boolean jsonReadBool(const String& json, String name, bool e = true);
extern bool jsonWriteStr_(String& json, const String& name, const String& value, bool e = true);

View File

@@ -45,3 +45,7 @@ String uint64ToString(uint64_t input, uint8_t base = 10);
void cleanString(String& str);
unsigned char ChartoHex(char ch);
std::vector<String> splitStr(const String& str, const String& delimiter);
bool strInVector(const String& str, const std::vector<String>& vec);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

5
iotm/ver.json Normal file
View File

@@ -0,0 +1,5 @@
{
"esp32_4mb": {
"0": "400"
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SimpleFTPServer</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,758 @@
/*
* FtpServer Arduino, esp8266 and esp32 library for Ftp Server
* Derived form Jean-Michel Gallego version
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
/*******************************************************************************
** **
** DEFINITIONS FOR FTP SERVER **
** **
*******************************************************************************/
#include <FtpServerKey.h>
#ifndef FTP_SERVER_H
#define FTP_SERVER_H
#define FTP_SERVER_VERSION "2.1.6 (2023-02-02)"
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
//
//#if(NETWORK_ESP8266_SD == DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266)
// #define ESP8266_GT_2_4_2_SD_STORAGE_SELECTED
// #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266 NETWORK_ESP8266
//#endif
#if !defined(FTP_SERVER_NETWORK_TYPE)
// select Network type based
#if defined(ESP8266) || defined(ESP31B)
#if(NETWORK_ESP8266_242 == DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266)
#define ARDUINO_ESP8266_RELEASE_2_4_2
#define FTP_SERVER_NETWORK_TYPE_SELECTED NETWORK_ESP8266_242
#define FTP_SERVER_NETWORK_TYPE NETWORK_ESP8266
#else
#define FTP_SERVER_NETWORK_TYPE DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266
#endif
#define STORAGE_TYPE DEFAULT_STORAGE_TYPE_ESP8266
#elif defined(ESP32)
#define FTP_SERVER_NETWORK_TYPE DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32
#define STORAGE_TYPE DEFAULT_STORAGE_TYPE_ESP32
#elif defined(ARDUINO_ARCH_STM32)
#define FTP_SERVER_NETWORK_TYPE DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32
#define STORAGE_TYPE DEFAULT_STORAGE_TYPE_STM32
#elif defined(ARDUINO_ARCH_RP2040)
#define FTP_SERVER_NETWORK_TYPE DEFAULT_FTP_SERVER_NETWORK_TYPE_RP2040
#define STORAGE_TYPE DEFAULT_STORAGE_TYPE_RP2040
#elif defined(ARDUINO_ARCH_SAMD)
#define FTP_SERVER_NETWORK_TYPE DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD
#define STORAGE_TYPE DEFAULT_STORAGE_TYPE_SAMD
#else
#define FTP_SERVER_NETWORK_TYPE DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO
#define STORAGE_TYPE DEFAULT_STORAGE_TYPE_ARDUINO
// #define STORAGE_SD_ENABLED
#endif
#endif
#ifndef FTP_SERVER_NETWORK_TYPE_SELECTED
#define FTP_SERVER_NETWORK_TYPE_SELECTED FTP_SERVER_NETWORK_TYPE
#endif
#if defined(ESP8266) || defined(ESP31B)
#ifndef STORAGE_SD_FORCE_DISABLE
#define STORAGE_SD_ENABLED
#endif
#ifndef STORAGE_SPIFFS_FORCE_DISABLE
#define STORAGE_SPIFFS_ENABLED
#endif
#elif defined(ESP32)
#ifndef STORAGE_SD_FORCE_DISABLE
#define STORAGE_SD_ENABLED
#endif
#ifndef STORAGE_SPIFFS_FORCE_DISABLE
#define STORAGE_SPIFFS_ENABLED
#endif
#else
#ifndef STORAGE_SD_FORCE_DISABLE
#define STORAGE_SD_ENABLED
#endif
#endif
// Includes and defined based on Network Type
#if(FTP_SERVER_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
// Note:
// No SSL/WSS support for client in Async mode
// TLS lib need a sync interface!
#if defined(ESP8266)
#include <ESP8266WiFi.h>
//#include <WiFiClientSecure.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiClientSecure
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#elif defined(ESP32)
#include <WiFi.h>
//#include <WiFiClientSecure.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiClientSecure
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#elif defined(ESP31B)
#include <ESP31BWiFi.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiClientSecure
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#else
#error "network type ESP8266 ASYNC only possible on the ESP mcu!"
#endif
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ESP8266 || FTP_SERVER_NETWORK_TYPE == NETWORK_ESP8266_242)
#if !defined(ESP8266) && !defined(ESP31B)
#error "network type ESP8266 only possible on the ESP mcu!"
#endif
#ifdef ESP8266
#include <ESP8266WiFi.h>
#else
#include <ESP31BWiFi.h>
#endif
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiClientSecure
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#define NET_CLASS WiFi
// #define CommandIs( a ) (command != NULL && ! strcmp_P( command, PSTR( a )))
// #define ParameterIs( a ) ( parameter != NULL && ! strcmp_P( parameter, PSTR( a )))
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ETHERNET_GENERIC)
#include <Ethernet_Generic.h>
#include <SPI.h>
#define FTP_CLIENT_NETWORK_CLASS EthernetClient
#define FTP_SERVER_NETWORK_SERVER_CLASS EthernetServer
#define NET_CLASS Ethernet
// #if defined(ESP8266) || defined(ESP32)
// #define CommandIs( a ) (command != NULL && ! strcmp_P( command, PSTR( a )))
// #define ParameterIs( a ) ( parameter != NULL && ! strcmp_P( parameter, PSTR( a )))
// #else
// #define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
// #define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
// #endif
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_W5100 || FTP_SERVER_NETWORK_TYPE == NETWORK_ETHERNET_ENC)
#include <Ethernet.h>
#include <SPI.h>
#define FTP_CLIENT_NETWORK_CLASS EthernetClient
#define FTP_SERVER_NETWORK_SERVER_CLASS EthernetServer
#define NET_CLASS Ethernet
// #if defined(ESP8266) || defined(ESP32)
// #define CommandIs( a ) (command != NULL && ! strcmp_P( command, PSTR( a )))
// #define ParameterIs( a ) ( parameter != NULL && ! strcmp_P( parameter, PSTR( a )))
// #else
// #define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
// #define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
// #endif
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ENC28J60 || FTP_SERVER_NETWORK_TYPE == NETWORK_UIPETHERNET)
#include <UIPEthernet.h>
#define FTP_CLIENT_NETWORK_CLASS UIPClient
#define FTP_SERVER_NETWORK_SERVER_CLASS UIPServer
#define NET_CLASS Ethernet
// #if define(ESP8266) || define(ESP32)
// #define CommandIs( a ) (command != NULL && ! strcmp_P( command, PSTR( a )))
// #define ParameterIs( a ) ( parameter != NULL && ! strcmp_P( parameter, PSTR( a )))
// #else
// #define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
// #define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
// #endif
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ETHERNET_LARGE)
#include <EthernetLarge.h>
#include <SPI.h>
#define FTP_CLIENT_NETWORK_CLASS EthernetClient
#define FTP_SERVER_NETWORK_SERVER_CLASS EthernetServer
#define NET_CLASS Ethernet
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ETHERNET_STM)
#include <Ethernet_STM.h>
#include <SPI.h>
#define FTP_CLIENT_NETWORK_CLASS EthernetClient
#define FTP_SERVER_NETWORK_SERVER_CLASS EthernetServer
#define NET_CLASS Ethernet
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ESP32)
#include <WiFi.h>
//#include <WiFiClientSecure.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiClientSecure
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#define NET_CLASS WiFi
// #define CommandIs( a ) (command != NULL && ! strcmp_P( command, PSTR( a )))
// #define ParameterIs( a ) ( parameter != NULL && ! strcmp_P( parameter, PSTR( a )))
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_ESP32_ETH)
#include <ETH.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#define NET_CLASS Ethernet
// #define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
// #define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_WiFiNINA)
#include <WiFiNINA.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiSSLClient
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#define NET_CLASS WiFi
// #define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
// #define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
#elif(FTP_SERVER_NETWORK_TYPE == NETWORK_SEEED_RTL8720DN)
#include <rpcWiFi.h>
#define FTP_CLIENT_NETWORK_CLASS WiFiClient
//#define FTP_CLIENT_NETWORK_SSL_CLASS WiFiSSLClient
#define FTP_SERVER_NETWORK_SERVER_CLASS WiFiServer
#define NET_CLASS WiFi
// #define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
// #define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
#else
#error "no network type selected!"
#endif
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_RP2040)
#define CommandIs( a ) (command != NULL && ! strcmp_P( command, PSTR( a )))
#define ParameterIs( a ) ( parameter != NULL && ! strcmp_P( parameter, PSTR( a )))
#else
#define CommandIs( a ) ( ! strcmp_PF( command, PSTR( a )))
#define ParameterIs( a ) ( ! strcmp_PF( parameter, PSTR( a )))
#endif
#if(STORAGE_TYPE == STORAGE_SPIFFS)
#if defined(ESP32)
// #define FS_NO_GLOBALS
#include <SPIFFS.h>
#define FTP_FILE File
#define FTP_DIR File
#else
#ifdef ARDUINO_ESP8266_RELEASE_2_4_2
#define FS_NO_GLOBALS
#include "FS.h"
#define FTP_FILE fs::File
#define FTP_DIR fs::Dir
#else
#include "FS.h"
#define FTP_FILE File
#define FTP_DIR Dir
#endif
#endif
#if ESP8266
#define FTP_FILE_READ "r"
#define FTP_FILE_READ_ONLY "r"
#define FTP_FILE_READ_WRITE "w+"
#define FTP_FILE_WRITE_APPEND "a+"
#define FTP_FILE_WRITE_CREATE "w+"
#else
#define FTP_FILE_READ "r"
#define FTP_FILE_READ_ONLY "r"
#define FTP_FILE_READ_WRITE "w"
#define FTP_FILE_WRITE_APPEND "a"
#define FTP_FILE_WRITE_CREATE "w"
#endif
#define STORAGE_MANAGER SPIFFS
#define FILENAME_LENGTH 32
#elif(STORAGE_TYPE == STORAGE_FFAT)
#include "FS.h"
#include "FFat.h"
#define STORAGE_MANAGER FFat
#define FTP_FILE File
#define FTP_DIR File
#define FTP_FILE_READ "r"
#define FTP_FILE_READ_ONLY "r"
#define FTP_FILE_READ_WRITE "w"
#define FTP_FILE_WRITE_APPEND "a"
#define FTP_FILE_WRITE_CREATE "w"
#define FILENAME_LENGTH 255
#elif(STORAGE_TYPE == STORAGE_LITTLEFS)
#if ESP8266 || ARDUINO_ARCH_RP2040
#include "LittleFS.h"
#define STORAGE_MANAGER LittleFS
#define FTP_FILE File
#define FTP_DIR Dir
#define FTP_FILE_READ "r"
#define FTP_FILE_READ_ONLY "r"
#define FTP_FILE_READ_WRITE "w+"
#define FTP_FILE_WRITE_APPEND "a+"
#define FTP_FILE_WRITE_CREATE "w+"
#else
#ifdef ESP32
#if ESP_ARDUINO_VERSION_MAJOR >= 2
#include "FS.h"
#include "LittleFS.h"
#define STORAGE_MANAGER LittleFS
#else
#include "LITTLEFS.h"
#define STORAGE_MANAGER LITTLEFS
#endif
#else
#include "LittleFS.h"
#define STORAGE_MANAGER LittleFS
#endif
#define FTP_FILE File
#define FTP_DIR File
#define FTP_FILE_READ "r"
#define FTP_FILE_READ_ONLY "r"
#define FTP_FILE_READ_WRITE "w"
#define FTP_FILE_WRITE_APPEND "a"
#define FTP_FILE_WRITE_CREATE "w"
#endif
#define FILENAME_LENGTH 32
#elif(STORAGE_TYPE == STORAGE_SD)
#include <SPI.h>
#include <SD.h>
#define STORAGE_MANAGER SD
#define FTP_FILE File
#define FTP_DIR File
#define FTP_FILE_READ FILE_READ
#define FTP_FILE_READ_ONLY FILE_READ
#ifdef ESP32
#define FTP_FILE_READ_WRITE FILE_WRITE
#define FTP_FILE_WRITE_APPEND FILE_APPEND
#else
#define FTP_FILE_READ_WRITE FILE_WRITE
#define FTP_FILE_WRITE_APPEND FILE_WRITE
#endif
#define FTP_FILE_WRITE_CREATE FILE_WRITE
#define FILENAME_LENGTH 255
#elif(STORAGE_TYPE == STORAGE_SD_MMC)
#include <SPI.h>
#include <SD_MMC.h>
#define STORAGE_MANAGER SD_MMC
#define FTP_FILE File
#define FTP_DIR File
#define FTP_FILE_READ FILE_READ
#define FTP_FILE_READ_ONLY FILE_READ
#define FTP_FILE_READ_WRITE FILE_WRITE
#ifdef ESP32
#define FTP_FILE_READ_WRITE FILE_WRITE
#define FTP_FILE_WRITE_APPEND FILE_APPEND
#else
#define FTP_FILE_READ_WRITE FILE_WRITE
#define FTP_FILE_WRITE_APPEND FILE_WRITE
#endif
#define FTP_FILE_WRITE_CREATE FILE_WRITE
#define FILENAME_LENGTH 255
#elif(STORAGE_TYPE == STORAGE_SEEED_SD)
#include <Seeed_FS.h>
#define STORAGE_MANAGER SD
#include "SD/Seeed_SD.h"
// #define STORAGE_MANAGER SPIFLASH
// #include "SFUD/Seeed_SFUD.h"
#define FTP_FILE File
#define FTP_DIR File
#define FTP_FILE_READ FILE_READ
#define FTP_FILE_READ_ONLY FILE_READ
#define FTP_FILE_READ_WRITE FILE_WRITE
#define FTP_FILE_WRITE_APPEND FILE_APPEND
#define FTP_FILE_WRITE_CREATE FILE_WRITE
#define FILENAME_LENGTH 255
#elif (STORAGE_TYPE == STORAGE_SDFAT1)
#include <SdFat.h>
#include <sdios.h>
#define STORAGE_MANAGER sd
#define FTP_FILE SdFile
#define FTP_DIR SdFile
extern SdFat STORAGE_MANAGER;
#define FTP_FILE_READ O_READ
#define FTP_FILE_READ_ONLY O_RDONLY
#define FTP_FILE_READ_WRITE O_RDWR
#define FTP_FILE_WRITE_APPEND O_WRITE | O_APPEND
#define FTP_FILE_WRITE_CREATE O_WRITE | O_CREAT
#define FILENAME_LENGTH 255
#elif (STORAGE_TYPE == STORAGE_SDFAT2)
#include <SdFat.h>
#include <sdios.h>
#define STORAGE_MANAGER sd
#define FTP_FILE FsFile
#define FTP_DIR FsFile
extern SdFat STORAGE_MANAGER;
#define FTP_FILE_READ O_READ
#define FTP_FILE_READ_ONLY O_RDONLY
#define FTP_FILE_READ_WRITE O_RDWR
#define FTP_FILE_WRITE_APPEND O_WRITE | O_APPEND
#define FTP_FILE_WRITE_CREATE O_WRITE | O_CREAT
#define FILENAME_LENGTH 255
#elif (STORAGE_TYPE == STORAGE_SPIFM)
#include <SdFat.h>
#include <Adafruit_SPIFlash.h>
#include <sdios.h>
#define STORAGE_MANAGER fatfs
#define FTP_FILE File
#define FTP_DIR File
extern FatFileSystem STORAGE_MANAGER;
extern Adafruit_SPIFlash flash;
#define FTP_FILE_READ FILE_READ
#define FTP_FILE_READ_ONLY FILE_READ
#define FTP_FILE_READ_WRITE FILE_WRITE
#define FTP_FILE_WRITE_APPEND FILE_WRITE
#define FTP_FILE_WRITE_CREATE FILE_WRITE
#define FILENAME_LENGTH 255
#elif (STORAGE_TYPE == STORAGE_FATFS)
#include <FatFs.h>
#include <sdios.h>
#define STORAGE_MANAGER sdff
#define FTP_FILE FileFs
#define FTP_DIR DirFs
extern FatFsClass STORAGE_MANAGER;
#define O_READ FA_READ
#define O_WRITE FA_WRITE
#define O_RDWR FA_READ | FA_WRITE
#define O_CREAT FA_CREATE_ALWAYS
#define O_APPEND FA_OPEN_APPEND
#define FTP_FILE_READ O_READ
#define FTP_FILE_READ_ONLY O_RDONLY
#define FTP_FILE_READ_WRITE O_RDWR
#define FTP_FILE_WRITE_APPEND O_WRITE | O_APPEND
#define FTP_FILE_WRITE_CREATE O_WRITE | O_CREAT
#define FILENAME_LENGTH 255
#endif
//#ifdef FTP_CLIENT_NETWORK_SSL_CLASS
//#define FTP_CLIENT_NETWORK_CLASS FTP_CLIENT_NETWORK_SSL_CLASS
//#endif
#define OPEN_CLOSE_SPIFFS
#define OPEN_CLOSE_SD
// Setup debug printing macros.
#ifdef FTP_SERVER_DEBUG
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
#else
#define DEBUG_PRINT(...) {}
#define DEBUG_PRINTLN(...) {}
#endif
#define FTP_CMD_PORT 21 // Command port on wich server is listening
#define FTP_DATA_PORT_DFLT 20 // Default data port in active mode
#define FTP_DATA_PORT_PASV 50009 // Data port in passive mode
#define FF_MAX_LFN 255 // max size of a long file name
#define FTP_CMD_SIZE FF_MAX_LFN+8 // max size of a command
#define FTP_CWD_SIZE FF_MAX_LFN+8 // max size of a directory name
#define FTP_FIL_SIZE FF_MAX_LFN // max size of a file name
#define FTP_CRED_SIZE 16 // max size of username and password
#define FTP_NULLIP() IPAddress(0,0,0,0)
enum ftpCmd { FTP_Stop = 0, // In this stage, stop any connection
FTP_Init, // initialize some variables
FTP_Client, // wait for client connection
FTP_User, // wait for user name
FTP_Pass, // wait for user password
FTP_Cmd }; // answers to commands
enum ftpTransfer { FTP_Close = 0, // In this stage, close data channel
FTP_Retrieve, // retrieve file
FTP_Store, // store file
FTP_List, // list of files
FTP_Nlst, // list of name of files
FTP_Mlsd }; // listing for machine processing
enum ftpDataConn { FTP_NoConn = 0,// No data connexion
FTP_Pasive, // Pasive type
FTP_Active }; // Active type
enum FtpOperation {
FTP_CONNECT,
FTP_DISCONNECT,
FTP_FREE_SPACE_CHANGE
};
enum FtpTransferOperation {
FTP_UPLOAD_START = 0,
FTP_UPLOAD = 1,
FTP_DOWNLOAD_START = 2,
FTP_DOWNLOAD = 3,
FTP_TRANSFER_STOP = 4,
FTP_DOWNLOAD_STOP = 4,
FTP_UPLOAD_STOP = 4,
FTP_TRANSFER_ERROR = 5,
FTP_DOWNLOAD_ERROR = 5,
FTP_UPLOAD_ERROR = 5
};
class FtpServer
{
public:
FtpServer( uint16_t _cmdPort = FTP_CMD_PORT, uint16_t _pasvPort = FTP_DATA_PORT_PASV );
void begin( const char * _user, const char * _pass, const char * welcomeMessage = "Welcome to Simply FTP server" );
void begin( const char * welcomeMessage = "Welcome to Simply FTP server" );
void end();
void setLocalIp(IPAddress localIp);
void credentials( const char * _user, const char * _pass );
uint8_t handleFTP();
void setCallback(void (*_callbackParam)(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace) )
{
_callback = _callbackParam;
}
void setTransferCallback(void (*_transferCallbackParam)(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize) )
{
_transferCallback = _transferCallbackParam;
}
private:
void (*_callback)(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){};
void (*_transferCallback)(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){};
void iniVariables();
void clientConnected();
void disconnectClient();
bool processCommand();
bool haveParameter();
int dataConnect( bool out150 = true );
bool dataConnected();
bool doRetrieve();
bool doStore();
bool doList();
bool doMlsd();
void closeTransfer();
void abortTransfer();
bool makePath( char * fullName, char * param = NULL );
bool makeExistsPath( char * path, char * param = NULL );
bool openDir( FTP_DIR * pdir );
bool isDir( char * path );
uint8_t getDateTime( char * dt, uint16_t * pyear, uint8_t * pmonth, uint8_t * pday,
uint8_t * phour, uint8_t * pminute, uint8_t * second );
char * makeDateTimeStr( char * tstr, uint16_t date, uint16_t time );
bool timeStamp( char * path, uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second );
bool getFileModTime( char * path, uint16_t * pdate, uint16_t * ptime );
#if STORAGE_TYPE != STORAGE_FATFS
bool getFileModTime( uint16_t * pdate, uint16_t * ptime );
#endif
int8_t readChar();
const char* getFileName(FTP_FILE *file){
#if STORAGE_TYPE <= STORAGE_SDFAT2
int max_characters = 100;
char f_name[max_characters];
file->getName(f_name, max_characters);
String filename = String(f_name);
return filename.c_str();
#elif STORAGE_TYPE == STORAGE_FATFS
return file->fileName();
#else
return file->name();
#endif
}
bool exists( const char * path ) {
#if STORAGE_TYPE == STORAGE_SPIFFS || (STORAGE_TYPE == STORAGE_SD && FTP_SERVER_NETWORK_TYPE == NETWORK_ESP8266_242)
if (strcmp(path, "/") == 0) return true;
#endif
#if STORAGE_TYPE == STORAGE_FFAT || (STORAGE_TYPE == STORAGE_LITTLEFS && defined(ESP32))
FTP_DIR f = STORAGE_MANAGER.open(path, "r");
return (f == true);
#else
return STORAGE_MANAGER.exists( path );
#endif
};
bool remove( const char * path ) { return STORAGE_MANAGER.remove( path ); };
#if STORAGE_TYPE == STORAGE_SPIFFS
bool makeDir( const char * path ) { return false; };
bool removeDir( const char * path ) { return false; };
#else
bool makeDir( const char * path ) { return STORAGE_MANAGER.mkdir( path ); };
bool removeDir( const char * path ) { return STORAGE_MANAGER.rmdir( path ); };
#endif
#if STORAGE_TYPE == STORAGE_SD || STORAGE_TYPE == STORAGE_SD_MMC
bool rename( const char * path, const char * newpath );
#else
bool rename( const char * path, const char * newpath ) { return STORAGE_MANAGER.rename( path, newpath ); };
#endif
#if (STORAGE_TYPE == STORAGE_SEEED_SD)
bool openFile( char path[ FTP_CWD_SIZE ], int readTypeInt );
#elif (STORAGE_TYPE == STORAGE_SD && defined(ESP8266))// FTP_SERVER_NETWORK_TYPE_SELECTED == NETWORK_ESP8266_242)
bool openFile( char path[ FTP_CWD_SIZE ], int readTypeInt );
#elif (STORAGE_TYPE == STORAGE_SPIFFS || STORAGE_TYPE == STORAGE_LITTLEFS || STORAGE_TYPE == STORAGE_FFAT )
bool openFile( const char * path, const char * readType );
// bool openFile( char path[ FTP_CWD_SIZE ], int readTypeInt );
#elif STORAGE_TYPE <= STORAGE_SDFAT2 || STORAGE_TYPE == STORAGE_SPIFM || (STORAGE_TYPE == STORAGE_SD && ARDUINO_ARCH_SAMD)
bool openFile( char path[ FTP_CWD_SIZE ], int readTypeInt );
#else
bool openFile( char path[ FTP_CWD_SIZE ], const char * readType );
bool openFile( const char * path, const char * readType );
// bool openFile( char path[ FTP_CWD_SIZE ], int readTypeInt );
#endif
// bool openFile( char path[ FTP_CWD_SIZE ], const char * readType );
// bool openFile( const char * path, const char * readType );
uint32_t fileSize( FTP_FILE file );
#if STORAGE_TYPE == STORAGE_SPIFFS || STORAGE_TYPE == STORAGE_LITTLEFS
#if ESP8266 || ARDUINO_ARCH_RP2040
uint32_t capacity() {
FSInfo fi;
STORAGE_MANAGER.info(fi);
return fi.totalBytes >> 1;
};
uint32_t free() {
FSInfo fi;
STORAGE_MANAGER.info(fi);
return (fi.totalBytes - fi.usedBytes) >> 1;
};
#else
uint32_t capacity() {
return STORAGE_MANAGER.totalBytes() >> 1;
};
uint32_t free() {
return (STORAGE_MANAGER.totalBytes() -
STORAGE_MANAGER.usedBytes()) >> 1;
};
#endif
#elif STORAGE_TYPE == STORAGE_SD || STORAGE_TYPE == STORAGE_SD_MMC
uint32_t capacity() { return true; };
uint32_t free() { return true; };
#elif STORAGE_TYPE == STORAGE_SEEED_SD
uint32_t capacity() {
return STORAGE_MANAGER.totalBytes() >> 1;
};
uint32_t free() {
return (STORAGE_MANAGER.totalBytes() -
STORAGE_MANAGER.usedBytes()) >> 1;
};
#elif STORAGE_TYPE == STORAGE_SDFAT1
uint32_t capacity() { return STORAGE_MANAGER.card()->cardSize() >> 1; };
uint32_t free() { return STORAGE_MANAGER.vol()->freeClusterCount() *
STORAGE_MANAGER.vol()->sectorsPerCluster() >> 1; };
#elif STORAGE_TYPE == STORAGE_SDFAT2
uint32_t capacity() { return STORAGE_MANAGER.card()->sectorCount() >> 1; };
uint32_t free() { return STORAGE_MANAGER.vol()->freeClusterCount() *
STORAGE_MANAGER.vol()->sectorsPerCluster() >> 1; };
#elif STORAGE_TYPE == STORAGE_SPIFM
uint32_t capacity() { return flash.size() >> 10; };
uint32_t free() { return 0; }; // TODO //
#elif STORAGE_TYPE == STORAGE_FATFS
uint32_t capacity() { return STORAGE_MANAGER.capacity(); };
uint32_t free() { return STORAGE_MANAGER.free(); };
#elif STORAGE_TYPE == STORAGE_FFAT
uint32_t capacity() { return STORAGE_MANAGER.totalBytes(); };
uint32_t free() { return STORAGE_MANAGER.freeBytes(); };
#endif
bool legalChar( char c ) // Return true if char c is allowed in a long file name
{
if( c == '"' || c == '*' || c == '?' || c == ':' ||
c == '<' || c == '>' || c == '|' )
return false;
#if STORAGE_TYPE == STORAGE_FATFS
return 0x1f < c && c < 0xff;
#else
return 0x1f < c && c < 0x7f;
#endif
}
IPAddress localIp; // IP address of server as seen by clients
IPAddress dataIp; // IP address of client for data
FTP_SERVER_NETWORK_SERVER_CLASS ftpServer;
FTP_SERVER_NETWORK_SERVER_CLASS dataServer;
FTP_CLIENT_NETWORK_CLASS client;
FTP_CLIENT_NETWORK_CLASS data;
FTP_FILE file;
FTP_DIR dir;
ftpCmd cmdStage; // stage of ftp command connexion
ftpTransfer transferStage; // stage of data connexion
ftpDataConn dataConn; // type of data connexion
bool anonymousConnection = false;
uint8_t __attribute__((aligned(4))) // need to be aligned to 32bit for Esp8266 SPIClass::transferBytes()
buf[ FTP_BUF_SIZE ]; // data buffer for transfers
char cmdLine[ FTP_CMD_SIZE ]; // where to store incoming char from client
char cwdName[ FTP_CWD_SIZE ]; // name of current directory
char rnfrName[ FTP_CWD_SIZE ]; // name of file for RNFR command
const char * user; // user name
const char * pass; // password
char command[ 5 ]; // command sent by client
bool rnfrCmd; // previous command was RNFR
char * parameter; // point to begin of parameters sent by client
const char * welcomeMessage;
uint16_t cmdPort,
pasvPort,
dataPort;
uint16_t iCL; // pointer to cmdLine next incoming char
uint16_t nbMatch;
uint32_t millisDelay, //
millisEndConnection, //
millisBeginTrans, // store time of beginning of a transaction
bytesTransfered; //
};
#endif // FTP_SERVER_H

View File

@@ -0,0 +1,128 @@
/*
* FtpServer Arduino, esp8266 and esp32 library for Ftp Server
* Derived form Jean-Michel Gallego version
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
/*******************************************************************************
** **
** SETTINGS FOR FTP SERVER **
** **
*******************************************************************************/
#ifndef FTP_SERVER_CONFIG_H
#define FTP_SERVER_CONFIG_H
// Uncomment to enable printing out nice debug messages.
// #define FTP_SERVER_DEBUG
// #define FTP_ADDITIONAL_DEBUG
// Define where debug output will be printed.
#define DEBUG_PRINTER Serial
#define STORAGE_SDFAT1 1 // Library SdFat version 1.4.x
#define STORAGE_SDFAT2 2 // Library SdFat version >= 2.0.2
#define STORAGE_SPIFM 3 // Libraries Adafruit_SPIFlash and SdFat-Adafruit-Fork
#define STORAGE_FATFS 4 // Library FatFs
#define STORAGE_SD 5 // Standard SD library (suitable for Arduino esp8266 and esp32
#define STORAGE_SPIFFS 6 // SPIFFS
#define STORAGE_LITTLEFS 7 // LITTLEFS
#define STORAGE_SEEED_SD 8 // Seeed_SD library
#define STORAGE_FFAT 9 // ESP32 FFAT
#define STORAGE_SD_MMC 10 // SD_MMC library
#define NETWORK_ESP8266_ASYNC (1)
#define NETWORK_ESP8266 (2) // Standard ESP8266WiFi
#define NETWORK_ESP8266_242 (3) // ESP8266WiFi before 2.4.2 core
#define NETWORK_W5100 (4) // Standard Arduino Ethernet library
#define NETWORK_ETHERNET (4) // Standard Arduino Ethernet library
#define NETWORK_ENC28J60 (5) // UIPEthernet library
#define NETWORK_ESP32 (6) // Standard WiFi library
#define NETWORK_RP2040_WIFI (6) // Raspberry Pi Pico W standard WiFi library
#define NETWORK_ESP32_ETH (7) // Standard ETH library
#define NETWORK_WiFiNINA (8) // Standard WiFiNINA library
#define NETWORK_SEEED_RTL8720DN (9) // Standard SEED WiFi library
#define NETWORK_ETHERNET_LARGE (10)
#define NETWORK_ETHERNET_ENC (11) // EthernetENC library (evolution of UIPEthernet
#define NETWORK_ETHERNET_STM (12)
#define NETWORK_UIPETHERNET (13) // UIPEthernet library same of NETWORK_ENC28J60
#define NETWORK_ETHERNET_GENERIC (14) // Ethernet generic
// esp8266 configuration
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP8266 NETWORK_ESP8266
#define DEFAULT_STORAGE_TYPE_ESP8266 STORAGE_LITTLEFS
#endif
// esp32 configuration
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 NETWORK_ESP32
#define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_LITTLEFS
/**
To use Ethernet.h with esp32 fix would be to change in Ethernet.h the line
class EthernetServer : public Server {
to
class EthernetServer : public Stream {
or
in \esp32\2.0.6\cores\esp32\Server.h
A workaround is to change line 28 of the ESP32 core's Server.h from:
virtual void begin(uint16_t port=0) =0;
to
virtual void begin() =0;
However, the last one, that will break anything that uses the ESP32 WiFi library's WebServer class.
https://github.com/arduino-libraries/Ethernet/issues/193
https://github.com/arduino-libraries/Ethernet/issues/88
*
*/
#endif
// Standard AVR Arduino configuration
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO NETWORK_W5100
#define DEFAULT_STORAGE_TYPE_ARDUINO STORAGE_SD
#endif
// STM32 configuration
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32 NETWORK_W5100
#define DEFAULT_STORAGE_TYPE_STM32 STORAGE_SDFAT2
#endif
// Raspberry Pi Pico (rp2040) configuration
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_RP2040
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_RP2040 NETWORK_RP2040_WIFI
#define DEFAULT_STORAGE_TYPE_RP2040 STORAGE_LITTLEFS
#endif
// Arduino SAMD21 like Arduino MKR Nano 33 IoT or Wio Terminal
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO_SAMD
// Wio Terminal
// #define DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD NETWORK_SEEED_RTL8720DN
// #define DEFAULT_STORAGE_TYPE_SAMD STORAGE_SEEED_SD
// Arduino SAMD
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD NETWORK_WiFiNINA
#define DEFAULT_STORAGE_TYPE_SAMD STORAGE_SD
#endif
#define UTF8_SUPPORT
//#define SD_CS_PIN 4
// Disconnect client after 5 minutes of inactivity (expressed in seconds)
#define FTP_TIME_OUT 5 * 60
// Wait for authentication for 10 seconds (expressed in seconds)
#define FTP_AUTH_TIME_OUT 10
// Size of file buffer for read/write
// Transfer speed depends of this value
// Best value depends on many factors: SD card, client side OS, ...
// But it can be reduced to 512 if memory usage is critical.
#define FTP_BUF_SIZE 1024 //2048 //1024 // 512
#endif // FTP_SERVER_CONFIG_H

View File

@@ -0,0 +1,24 @@
The MIT License (MIT)
Copyright (c) 2017 Renzo Mischianti www.mischianti.org All right reserved.
You may copy, alter and reuse this code in any way you like, but please leave
reference to www.mischianti.org in your comments if you redistribute this code.
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.

View File

@@ -0,0 +1,108 @@
# SimpleFTPServer
[Instruction on FTP server on esp8266 and esp32](https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32)
[Simple FTP Server library now with support for Wio Terminal and SD](https://www.mischianti.org/2021/07/01/simple-ftp-server-library-now-with-support-for-wio-terminal-and-sd/)
#### Simple FTP Server for
- Raspberry Pi Pico W (Flash: LittleFS) (To test SD and SdFat)
- esp8266 (Flash: SPIFFs, LittleFS. SD: SD, SdFat 2)
- esp32 (SPIFFS, LITTLEFS, FFAT, SD: SD, SdFat)
- stm32 (SdFat, SPI flash)
- Arduino (SD with 8.3 file format, SD: SD, SdFat 2)
- Wio Terminal (SdFat 2, Seed SD, and native FAT)
#### Changelog
- 2022-02-02 2.1.6 Fix esp8266 Ethernet (w5x00) issue and explain solution for ESP32 Ethernet (w5x00), add new Networks management
- 2022-01-13 2.1.5 Fix SPIFM external SPI Flash date management (add SPIFM esp32 example)
- 2022-09-21 2.1.4 Add support for Raspberry Pi Pico W and rp2040 boards, Fix SD card config
- 2022-09-20 2.1.3 Soft AP IP management, more disconnect event and SD_MCC
- 2022-05-21 2.1.2 Fix SD path (#19)
- 2022-05-21 2.1.1 Minor fix
- 2022-03-30 2.1.0 Add UTF8 support and enabled It by default (Thanks to @plaber)
- 2022-03-30 2.0.0 Complete support for STM32 with SD and SPI Flash minor bux fix and HELP command support
- 2022-03-17 1.3.0 Fix enc28j60 and w5500 support and restructuring for local settings
- 2022-02-25 1.2.1 Fix anonymous user begin and fix SPIFFS wrong display
- 2022-02-22 1.2.0 Add anonymous user and implement correct RFC (#9 now work correctly with File Explorer)
- 2022-02-01 1.1.1 Add workaround to start FTP server before connection, add end and setLocalIP method.
<!-- wp:paragraph -->
<p>When I develop a new solution I'd like to divide the application in layer, and so I'd like focus my attention in only one aspect at time. </p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p> In detail I separate the REST layer (written inside the microcontroller) and the Front-End (written in Angular, React/Redux or vanilla JS), so I'd like to upload new web interface directly to the microcontroller via FTP. </p>
<!-- /wp:paragraph -->
<!-- wp:image {"align":"center","id":2155} -->
<div class="wp-block-image"><figure class="aligncenter"><img width="450px" src="https://www.mischianti.org/wp-content/uploads/2019/06/FTPTransferEsp8266-1024x662.jpg" alt="" class="wp-image-2155"/><figcaption></figcaption></figure></div>
<!-- /wp:image -->
<!-- wp:paragraph -->
<p>For static information (Web pages for examples), that not change frequently, esp8266 or esp32 have internal SPIFFS (SPI Flash File System) and you can upload data via Arduino IDE as explained in the article "<a href="https://www.mischianti.org/2019/08/30/wemos-d1-mini-esp8266-integrated-spiffs-filesistem-part-2/">WeMos D1 mini (esp8266), integrated SPIFFS Filesystem</a>" for esp8266 or "<a rel="noreferrer noopener" href="https://www.mischianti.org/2020/06/04/esp32-integrated-spiffs-filesystem-part-2/" target="_blank">ESP32: integrated SPIFFS FileSystem</a>" for esp32 or with LittleFS "<a href="https://www.mischianti.org/2020/06/22/wemos-d1-mini-esp8266-integrated-littlefs-filesystem-part-5/">WeMos D1 mini (esp8266), integrated LittleFS Filesystem</a>" but for fast operation and future support It's usefully use FTP.</p>
<!-- /wp:paragraph -->
```cpp
/*
* FtpServer esp8266 and esp32 with SPIFFS
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#elif defined ESP32
#include <WiFi.h>
#include "SPIFFS.h"
#endif
#include <SimpleFTPServer.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void setup(void){
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
#ifdef ESP32 //esp32 we send true to format spiffs if cannot mount
if (SPIFFS.begin(true)) {
#elif defined ESP8266
if (SPIFFS.begin()) {
#endif
Serial.println("SPIFFS opened!");
ftpSrv.begin("esp8266","esp8266"); //username, password for ftp. set ports in ESP8266FtpServer.h (default 21, 50009 for PASV)
}
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
// server.handleClient(); //example if running a webserver you still need to call .handleClient();
}
```
https://downloads.arduino.cc/libraries/logs/github.com/xreef/SimpleFTPServer/

View File

@@ -0,0 +1,18 @@
/*
* FtpServer Arduino, esp8266 and esp32 library for Ftp Server
* Derived form https://github.com/nailbuster/esp8266FTPServer
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#ifndef SIMPLE_FTP_SERVER_H
#define SIMPLE_FTP_SERVER_H
#include <FtpServer.h>
#endif
#pragma once

View File

@@ -0,0 +1,62 @@
/*
* FtpServer Arduino with Ethernet library and w5100 shield
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include <SPI.h>
#include <Ethernet.h>
#include "SD.h"
#include <SimpleFtpServer.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE1 };
// Set the static IP address to use if the DHCP fails to assign
byte macAddr[] = {0x5e, 0xa4, 0x18, 0xf0, 0x8a, 0xf2};
IPAddress arduinoIP(192, 168, 1, 177);
IPAddress dnsIP(192, 168, 1, 1);
IPAddress gatewayIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);
FtpServer ftpSrv;
void setup(void){
Serial.begin(115200);
delay(2000);
// If other chips are connected to SPI bus, set to high the pin connected
// to their CS before initializing Flash memory
pinMode( 4, OUTPUT );
digitalWrite( 4, HIGH );
pinMode( 10, OUTPUT );
digitalWrite( 10, HIGH );
Serial.print("Starting SD.");
while (!SD.begin(4)) {
Serial.print(".");
}
Serial.println("finish!");
// start the Ethernet connection:
Serial.print("Starting ethernet.");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
Ethernet.begin(macAddr, arduinoIP, dnsIP, gatewayIP, subnetIP);
}else{
Serial.println("ok to configure Ethernet using DHCP");
}
Serial.print("IP address ");
Serial.println(Ethernet.localIP());
Serial.println("SPIFFS opened!");
ftpSrv.begin("esp8266","esp8266"); //username, password for ftp.
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,133 @@
/*
* FtpServer Arduino with Ethernet library and w5100 shield
* With SdFat version > 2 (full name and more size)
*
* #ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO
* #define DEFAULT_FTP_SERVER_NETWORK_TYPE_ARDUINO NETWORK_W5100
* #define DEFAULT_STORAGE_TYPE_ARDUINO STORAGE_SDFAT2
* #endif
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include <SdFat.h>
#include <sdios.h>
#include <FtpServer.h>
#include <FreeStack.h>
// Define Chip Select for your SD card according to hardware
// #define CS_SDCARD 4 // SD card reader of Ehernet shield
#define CS_SDCARD 4 // Chip Select for SD card reader on Due
// Define Reset pin for W5200 or W5500
// set to -1 for other ethernet chip or if Arduino reset board is used
#define W5x00_RESET -1
//#define W5x00_RESET 8 // on Due
// #define W5x00_RESET 3 // on MKR
// Object for File system
SdFat sd;
// Object for FtpServer
// Command port and Data port in passive mode can be defined here
// FtpServer ftpSrv( 221, 25000 );
// FtpServer ftpSrv( 421 ); // Default data port in passive mode is 55600
FtpServer ftpSrv; // Default command port is 21 ( !! without parenthesis !! )
// Mac address of ethernet adapter
// byte mac[] = { 0x90, 0xa2, 0xda, 0x00, 0x00, 0x00 };
byte mac[] = { 0x00, 0xaa, 0xbb, 0xcc, 0xde, 0xef };
// IP address of FTP server
// if set to 0, use DHCP for the routeur to assign IP
// IPAddress serverIp( 192, 168, 1, 40 );
IPAddress serverIp( 0, 0, 0, 0 );
// External IP address of FTP server
// In passive mode, when accessing the serveur from outside his subnet, it can be
// necessary with some clients to reply them with the server's external ip address
// IPAddress externalIp( 192, 168, 1, 2 );
ArduinoOutStream cout( Serial );
void setup()
{
Serial.begin( 115200 );
cout << F("=== Test of FTP Server with SdFat ") << SD_FAT_VERSION << F(" file system ===") << endl;
// If other chips are connected to SPI bus, set to high the pin connected
// to their CS before initializing Flash memory
pinMode( 4, OUTPUT );
digitalWrite( 4, HIGH );
pinMode( 10, OUTPUT );
digitalWrite( 10, HIGH );
// Mount the SD card memory
cout << F("Mount the SD card memory... ");
if( ! sd.begin( CS_SDCARD, SD_SCK_MHZ( 50 )))
{
cout << F("Unable to mount SD card") << endl;
while( true ) ;
}
pinMode( CS_SDCARD, OUTPUT );
digitalWrite( CS_SDCARD, HIGH );
cout << F("ok") << endl;
// Show capacity and free space of SD card
cout << F("Capacity of card: ") << long( sd.card()->sectorCount() >> 1 )
<< F(" kBytes") << endl;
cout << F("Free space on card: ")
<< long( sd.vol()->freeClusterCount() * sd.vol()->sectorsPerCluster() >> 1 )
<< F(" kBytes") << endl;
// Send reset to Ethernet module
if( W5x00_RESET > -1 )
{
pinMode( W5x00_RESET, OUTPUT );
digitalWrite( W5x00_RESET, LOW );
delay( 200 );
digitalWrite( W5x00_RESET, HIGH );
delay( 200 );
}
// Initialize the network
cout << F("Initialize ethernet module ... ");
if( serverIp[0] != 0 )
Ethernet.begin( mac, serverIp );
else if( Ethernet.begin( mac ) == 0 )
{
cout << F("failed!") << endl;
while( true ) ;
}
uint16_t wizModule[] = { 0, 5100, 5200, 5500 };
cout << F("W") << wizModule[ Ethernet.hardwareStatus()] << F(" ok") << endl;
serverIp = Ethernet.localIP();
cout << F("IP address of server: ")
<< int( serverIp[0]) << "." << int( serverIp[1]) << "."
<< int( serverIp[2]) << "." << int( serverIp[3]) << endl;
// Initialize the FTP server
ftpSrv.begin("user","password");
// ftpSrv.init( externalIp );
// ftpSrv.init( IPAddress( 11, 22, 33, 44 ));
// Default username and password are set to 'arduino' and 'test'
// but can then be changed by calling ftpSrv.credentials()
// ftpSrv.credentials( "myname", "123" );
cout << F("Free stack: ") << FreeStack() << endl;
cout << "Viaaa!";
}
void loop()
{
ftpSrv.handleFTP();
// more processes...
}

View File

@@ -0,0 +1,96 @@
/*
* FtpServer esp8266 and esp32 with SD
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include <WiFi.h>
#include "SD.h"
#include <SimpleFTPServer.h>
const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
Serial.print(">>>>>>>>>>>>>>> _callback " );
Serial.print(ftpOperation);
/* FTP_CONNECT,
* FTP_DISCONNECT,
* FTP_FREE_SPACE_CHANGE
*/
Serial.print(" ");
Serial.print(freeSpace);
Serial.print(" ");
Serial.println(totalSpace);
// freeSpace : totalSpace = x : 360
if (ftpOperation == FTP_CONNECT) Serial.println(F("CONNECTED"));
if (ftpOperation == FTP_DISCONNECT) Serial.println(F("DISCONNECTED"));
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
Serial.print(">>>>>>>>>>>>>>> _transferCallback " );
Serial.print(ftpOperation);
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
Serial.print(" ");
Serial.print(name);
Serial.print(" ");
Serial.println(transferredSize);
};
void setup(void){
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
SPI.begin(14, 12, 15, 13); //SCK, MISO, MOSI,SS
if (SD.begin(13, SPI)) {
Serial.println("SD opened!");
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
ftpSrv.begin("esp8266","esp8266"); //username, password for ftp. (default 21, 50009 for PASV)
}
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
// server.handleClient(); //example if running a webserver you still need to call .handleClient();
}

View File

@@ -0,0 +1,124 @@
/*
* FtpServer esp32 with FFat FS
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include "Arduino.h"
#include "FS.h"
#include "FFat.h"
#include <SimpleFTPServer.h>
#ifdef STA_MODE
const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";
#endif
const char* ssid_AP = "ESP32";
const char* password_AP = "aabbccdd77";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.printf("FTP: Free space change, free %u of %u!\n", freeSpace, totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.printf("FTP: Upload of file %s byte %u\n", name, transferredSize);
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup(void){
Serial.begin(115200);
//AP mode
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid_AP, password_AP);
delay(1000);
//IPAddress IP = IPAddress (10, 10, 10, 1);
//IPAddress NMask = IPAddress (255, 255, 255, 0);
//WiFi.softAPConfig(IP, IP, NMask);
Serial.print("Set AP named:");
Serial.println(ssid_AP);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
#ifdef STA_MODE
// STA mode
WiFi.begin(ssid, password);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
#endif
/////FTP Setup, ensure FFAT is started before ftp; /////////
Serial.print(F("Inizializing FS..."));
if (FFat.begin(true)){
Serial.println(F("done."));
}else{
Serial.println(F("fail."));
while (true) { delay(1000); };
}
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.println("Start FTP with user: user and passwd: password!");
ftpSrv.begin("user","password"); //username, password for ftp. (default 21, 50009 for PASV)
ftpSrv.setLocalIp(myIP);
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,105 @@
/*
* FtpServer esp32 with FFat FS
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include "Arduino.h"
#include "FS.h"
#include "FFat.h"
#include <SimpleFTPServer.h>
const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.printf("FTP: Free space change, free %u of %u!\n", freeSpace, totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.printf("FTP: Upload of file %s byte %u\n", name, transferredSize);
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup(void){
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/////FTP Setup, ensure FFAT is started before ftp; /////////
Serial.print(F("Inizializing FS..."));
if (FFat.begin(true)){
Serial.println(F("done."));
}else{
Serial.println(F("fail."));
while (true) { delay(1000); };
}
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.println("Start FTP with user: user and passwd: password!");
ftpSrv.begin("user","password"); //username, password for ftp. (default 21, 50009 for PASV)
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,130 @@
/*
* FtpServer esp32 with FFat and EthernetENC (or UIPEthernet)
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include "Arduino.h"
#include <SPI.h>
#include <EthernetENC.h>
#include "FS.h"
#include "FFat.h"
#include <SimpleFTPServer.h>
#define MACADDRESS 0x00,0x01,0x02,0x03,0x04,0x05
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1
uint8_t macaddress[6] = {MACADDRESS};
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
Serial.print(">>>>>>>>>>>>>>> _callback " );
Serial.print(ftpOperation);
/* FTP_CONNECT,
* FTP_DISCONNECT,
* FTP_FREE_SPACE_CHANGE
*/
Serial.print(" ");
Serial.print(freeSpace);
Serial.print(" ");
Serial.println(totalSpace);
// freeSpace : totalSpace = x : 360
if (ftpOperation == FTP_CONNECT) Serial.println(F("CONNECTED"));
if (ftpOperation == FTP_DISCONNECT) Serial.println(F("DISCONNECTED"));
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
Serial.print(">>>>>>>>>>>>>>> _transferCallback " );
Serial.print(ftpOperation);
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
Serial.print(" ");
Serial.print(name);
Serial.print(" ");
Serial.println(transferredSize);
};
void setup(void){
Serial.begin(115200);
Serial.println("Begin Ethernet");
Ethernet.init(5);
if (Ethernet.begin(macaddress)) { // Dynamic IP setup
Serial.println("DHCP OK!");
}else{
Serial.println("Failed to configure Ethernet using DHCP");
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
IPAddress ip(MYIPADDR);
IPAddress dns(MYDNS);
IPAddress gw(MYGW);
IPAddress sn(MYIPMASK);
Ethernet.begin(macaddress, ip, dns, gw, sn);
Serial.println("STATIC OK!");
}
delay(5000);
Serial.print("Local IP : ");
Serial.println(Ethernet.localIP());
Serial.print("Subnet Mask : ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP : ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS Server : ");
Serial.println(Ethernet.dnsServerIP());
Serial.println("Ethernet Successfully Initialized");
/////FTP Setup, ensure FFat is started before ftp; /////////
if (FFat.begin(true)) {
Serial.println("FFat opened!");
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
ftpSrv.begin("user","password"); //username, password for ftp. set ports in ESP8266FtpServer.h (default 21, 50009 for PASV)
Serial.println("FTP server started!");
} else {
Serial.println("FFat opened FAIL!!!!!");
}
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
// server.handleClient(); //example if running a webserver you still need to call .handleClient();
}

View File

@@ -0,0 +1,148 @@
/**
* ESP32 and external SPI Flash FTP server
*
*
// esp32 configuration
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_ESP32 NETWORK_ESP32
#define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_SPIFM
#endif
*
*/
#include <Arduino.h>
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include <WiFi.h>
#include <SimpleFTPServer.h>
Adafruit_FlashTransport_SPI flashTransport(SS, SPI); // Set CS and SPI interface
Adafruit_SPIFlash flash(&flashTransport);
// file system object from SdFat
FatFileSystem fatfs;
const char* ssid = "<YOUR_SSID>";
const char* password = "<YOUR_PASSWD>";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.print(F("FTP: Free space change, free "));
Serial.print(freeSpace);
Serial.print(F(" of "));
Serial.println(totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.print(F("FTP: Upload of file "));
Serial.print(name);
Serial.print(F(" "));
Serial.print(transferredSize);
Serial.println(F("bytes"));
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup()
{
// Initialize serial port and wait for it to open before continuing.
Serial.begin(115200);
while (!Serial) {
delay(100);
}
Serial.println("FTP with external SPIFlash");
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("SN address: ");
Serial.println(WiFi.subnetMask());
if (flash.begin()) {
Serial.println(F("Device finded and supported!"));
} else {
Serial.println(F("Problem to discover and configure device, check wiring also!"));
while(1) yield();
}
// Set 4Mhz SPI speed
flashTransport.setClockSpeed(4000000, 4000000); // added to prevent speed problem
Serial.print("JEDEC ID: "); Serial.println(flash.getJEDECID(), HEX);
Serial.print("Flash size: "); Serial.println(flash.size());
Serial.flush();
// First call begin to mount the filesystem. Check that it returns true
// to make sure the filesystem was mounted.
if (!fatfs.begin(&flash)) {
Serial.println("Error, failed to mount newly formatted filesystem!");
Serial.println("Was the flash chip formatted with the SdFat_format example?");
while(1) yield();
}
Serial.println("Mounted filesystem!");
Serial.println();
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.println("Starting FTP Server!");
ftpSrv.begin("user","password"); //username, password for ftp. (default 21, 50009 for PASV)
// ftpSrv.beginAnonymous();
}
// The loop function is called in an endless loop
void loop()
{
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,103 @@
/*
* FtpServer Raspberry Pi Pico W with LittleFS
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#include <WiFi.h>
#include <LittleFS.h>
#include <SimpleFTPServer.h>
const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.printf("FTP: Free space change, free %u of %u!\n", freeSpace, totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.printf("FTP: Upload of file %s byte %u\n", name, transferredSize);
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup(void){
Serial.begin(115200);
while (!Serial) {delay(100);};
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
if (LittleFS.begin()) {
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.println("LittleFS opened!");
ftpSrv.begin("user","password"); //username, password for ftp. (default 21, 50009 for PASV)
}
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,136 @@
/**
* SimpleFTPServer ^1.3.0 on STM32 (need FLASH > 64K)
* and ethernet w5500
* SPI Flash with Adafruit_SPIFlash and SdFat-Adafruit-Fork library
*
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32 NETWORK_ETHERNET_ENC
#define DEFAULT_STORAGE_TYPE_STM32 STORAGE_SPIFM
#endif
*
* @author Renzo Mischianti <www.mischianti.org>
* @details https://www.mischianti.org/category/my-libraries/simple-ftp-server/
* @version 0.1
* @date 2022-03-22
*
* @copyright Copyright (c) 2022
*
*/
#include <Arduino.h>
#include <EthernetEnc.h>
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include <SimpleFTPServer.h>
Adafruit_FlashTransport_SPI flashTransport(SS, SPI); // Set CS and SPI interface
Adafruit_SPIFlash flash(&flashTransport);
// file system object from SdFat
FatFileSystem fatfs;
#define ETHERNET_CS_PIN PA3
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// Set the static IP address to use if the DHCP fails to assign
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Initialize serial port and wait for it to open before continuing.
Serial.begin(115200);
while (!Serial) {
delay(100);
}
Serial.println("Adafruit SPI Flash FatFs Full Usage Example");
// Initialize flash library and check its chip ID.
if (!flash.begin()) {
Serial.println("Error, failed to initialize flash chip!");
while(1) yield();
}
Serial.print("JEDEC ID: "); Serial.println(flash.getJEDECID(), HEX);
Serial.print("Flash size: "); Serial.println(flash.size());
Serial.flush();
// First call begin to mount the filesystem. Check that it returns true
// to make sure the filesystem was mounted.
if (!fatfs.begin(&flash)) {
Serial.println("Error, failed to mount newly formatted filesystem!");
Serial.println("Was the flash chip formatted with the SdFat_format example?");
while(1) yield();
}
Serial.println("Mounted filesystem!");
Serial.println();
// You can use Ethernet.init(pin) to configure the CS pin
Ethernet.init(ETHERNET_CS_PIN);
if (Ethernet.begin(mac)) { // Dynamic IP setup
Serial.println(F("DHCP OK!"));
}else{
Serial.println(F("Failed to configure Ethernet using DHCP"));
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("Ethernet shield was not found. Sorry, can't run without hardware. :("));
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet cable is not connected."));
}
IPAddress ip(MYIPADDR);
IPAddress dns(MYDNS);
IPAddress gw(MYGW);
IPAddress sn(MYIPMASK);
Ethernet.begin(mac, ip, dns, gw, sn);
Serial.println("STATIC OK!");
}
delay(5000);
Serial.print("Local IP : ");
Serial.println(Ethernet.localIP());
Serial.print("Subnet Mask : ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP : ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS Server : ");
Serial.println(Ethernet.dnsServerIP());
Serial.println("Ethernet Successfully Initialized");
Serial.println();
// Initialize the FTP server
ftpSrv.begin("user","password");
Serial.println("Ftp server started!");
}
void loop()
{
ftpSrv.handleFTP();
// more processes...
}

View File

@@ -0,0 +1,135 @@
/**
* SimpleFTPServer ^1.3.0 on STM32 (need FLASH > 64K)
* and ethernet w5500
* SD connected on secondary SPI or primary
*
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32 NETWORK_W5100
#define DEFAULT_STORAGE_TYPE_STM32 STORAGE_SDFAT2
#endif
*
* @author Renzo Mischianti <www.mischianti.org>
* @details https://www.mischianti.org/category/my-libraries/simple-ftp-server/
* @version 0.1
* @date 2022-03-22
*
* @copyright Copyright (c) 2022
*
*/
#include <SdFat.h>
#include <sdios.h>
#include <SimpleFtpServer.h>
#include <EthernetEnc.h>
// Ethernet CS
#define ETHERNET_CS_PIN PA3
// To use SD with primary SPI
#define SD_CS_PIN PA2
// To use SD with secondary SPI
// #define SD_CS_PIN PB12
// static SPIClass mySPI2(PB15, PB14, PB13, SD_CS_PIN);
// #define SD2_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(18), &mySPI2)
SdFat sd;
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// Set the static IP address to use if the DHCP fails to assign
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
Serial.begin( 115200 );
while (!Serial) { delay(100); }
pinMode( SD_CS_PIN, OUTPUT );
digitalWrite( SD_CS_PIN, HIGH );
pinMode( ETHERNET_CS_PIN, OUTPUT );
digitalWrite( ETHERNET_CS_PIN, HIGH );
Serial.print("\nInitializing SD card...");
// To use SD with secondary SPI
// if (!sd.begin(SD2_CONFIG)) {
// To use SD with primary SPI
if (!sd.begin(SD_CS_PIN)) {
Serial.println(F("initialization failed. Things to check:"));
Serial.println(F("* is a card inserted?"));
Serial.println(F("* is your wiring correct?"));
Serial.println(F("* did you change the chipSelect pin to match your shield or module?"));
while (1);
} else {
Serial.println(F("Wiring is correct and a card is present."));
}
// Show capacity and free space of SD card
Serial.print(F("Capacity of card: ")); Serial.print(long( sd.card()->sectorCount() >> 1 )); Serial.println(F(" kBytes"));
// You can use Ethernet.init(pin) to configure the CS pin
Ethernet.init(ETHERNET_CS_PIN);
if (Ethernet.begin(mac)) { // Dynamic IP setup
Serial.println(F("DHCP OK!"));
}else{
Serial.println(F("Failed to configure Ethernet using DHCP"));
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("Ethernet shield was not found. Sorry, can't run without hardware. :("));
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet cable is not connected."));
}
IPAddress ip(MYIPADDR);
IPAddress dns(MYDNS);
IPAddress gw(MYGW);
IPAddress sn(MYIPMASK);
Ethernet.begin(mac, ip, dns, gw, sn);
Serial.println("STATIC OK!");
}
delay(5000);
Serial.print("Local IP : ");
Serial.println(Ethernet.localIP());
Serial.print("Subnet Mask : ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP : ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS Server : ");
Serial.println(Ethernet.dnsServerIP());
Serial.println("Ethernet Successfully Initialized");
Serial.println();
// Initialize the FTP server
ftpSrv.begin("user","password");
Serial.println("Ftp server started!");
}
void loop()
{
ftpSrv.handleFTP();
// more processes...
}

View File

@@ -0,0 +1,128 @@
/**
* SimpleFTPServer ^1.3.0 on STM32 (need FLASH > 64K)
* and ethernet w5500
* SD connected on secondary SPI or primary
*
#ifndef DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32
#define DEFAULT_FTP_SERVER_NETWORK_TYPE_STM32 NETWORK_W5100
#define DEFAULT_STORAGE_TYPE_STM32 STORAGE_SDFAT2
#endif
*
* @author Renzo Mischianti <www.mischianti.org>
* @details https://www.mischianti.org/category/my-libraries/simple-ftp-server/
* @version 0.1
* @date 2022-03-22
*
* @copyright Copyright (c) 2022
*
*/
#include <SdFat.h>
#include <sdios.h>
#include <Ethernet.h>
#include <SimpleFtpServer.h>
// To use SD with primary SPI
// #define SD_CS_PIN PA4
// To use SD with secondary SPI
#define SD_CS_PIN PB12
static SPIClass mySPI2(PB15, PB14, PB13, SD_CS_PIN);
#define SD2_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(18), &mySPI2)
SdFat sd;
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// Set the static IP address to use if the DHCP fails to assign
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
Serial.begin( 115200 );
while (!Serial) { delay(100); }
Serial.print("\nInitializing SD card...");
// Secondary SPI for SD
if (!sd.begin(SD2_CONFIG)) {
// Primary SPI for SD
// if (!SD.begin(SD_CS_PIN)) {
Serial.println(F("initialization failed. Things to check:"));
Serial.println(F("* is a card inserted?"));
Serial.println(F("* is your wiring correct?"));
Serial.println(F("* did you change the chipSelect pin to match your shield or module?"));
while (1);
} else {
Serial.println(F("Wiring is correct and a card is present."));
}
// Show capacity and free space of SD card
Serial.print(F("Capacity of card: ")); Serial.print(long( sd.card()->sectorCount() >> 1 )); Serial.println(F(" kBytes"));
// You can use Ethernet.init(pin) to configure the CS pin
Ethernet.init(PA4);
if (Ethernet.begin(mac)) { // Dynamic IP setup
Serial.println(F("DHCP OK!"));
}else{
Serial.println(F("Failed to configure Ethernet using DHCP"));
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println(F("Ethernet shield was not found. Sorry, can't run without hardware. :("));
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println(F("Ethernet cable is not connected."));
}
IPAddress ip(MYIPADDR);
IPAddress dns(MYDNS);
IPAddress gw(MYGW);
IPAddress sn(MYIPMASK);
Ethernet.begin(mac, ip, dns, gw, sn);
Serial.println("STATIC OK!");
}
delay(5000);
Serial.print("Local IP : ");
Serial.println(Ethernet.localIP());
Serial.print("Subnet Mask : ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP : ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS Server : ");
Serial.println(Ethernet.dnsServerIP());
Serial.println("Ethernet Successfully Initialized");
Serial.println();
// Initialize the FTP server
ftpSrv.begin("user","password");
Serial.println("Ftp server started!");
}
void loop()
{
ftpSrv.handleFTP();
// more processes...
}

View File

@@ -0,0 +1,106 @@
/*
* FtpServer Wio Terminal
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/category/my-libraries/simple-ftp-server/
*/
#include <Seeed_FS.h>
#include "SD/Seeed_SD.h"
// #define DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD NETWORK_SEEED_RTL8720DN
// #define DEFAULT_STORAGE_TYPE_SAMD STORAGE_SEEED_SD
#include <rpcWiFi.h>
#include <FtpServer.h>
FtpServer ftpSrv;
const char *ssid = "<YOUR-SSID>";
const char *password = "<YOUR-PASSWD>";
void listDir(const char* dirname, uint8_t levels) {
Serial.print("Listing directory: ");
Serial.println(dirname);
File root = SD.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels) {
listDir(file.name(), levels - 1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void setup()
{
Serial.begin(115200);
delay(1000);
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);
while (!SD.begin(SDCARD_SS_PIN,SDCARD_SPI,4000000UL)) {
Serial.println("Card Mount Failed");
return;
}
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(1000);
Serial.print("Starting SD.");
Serial.println("finish!");
listDir("/", 0);
ftpSrv.begin("esp8266","esp8266"); //username, password for ftp.
}
void loop(void) {
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,104 @@
/*
* FtpServer Wio Terminal with SdFat library
* and with callbacks to the main actions of FTP server
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/category/my-libraries/simple-ftp-server/
*
*/
#include "SdFat.h"
#include <rpcWiFi.h>
#include <FtpServer.h>
// #define DEFAULT_FTP_SERVER_NETWORK_TYPE_SAMD NETWORK_SEEED_RTL8720DN
// #define DEFAULT_STORAGE_TYPE_SAMD STORAGE_SDFAT2
#define SD_CONFIG SdSpiConfig(SDCARD_SS_PIN, 2)
SdFs sd;
FtpServer ftpSrv;
const char *ssid = "<YOUR-SSID>";
const char *password = "<YOUR-PASSWD>";
void setup()
{
Serial.begin(115200);
delay(1000);
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);
// Initialize the SD.
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
FsFile dir;
FsFile file;
// Open root directory
if (!dir.open("/")){
Serial.println("dir.open failed");
}
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(1000);
Serial.print("Starting SD.");
Serial.println("finish!");
while (file.openNext(&dir, O_RDONLY)) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printModifyDateTime(&Serial);
Serial.write(' ');
file.printName(&Serial);
if (file.isDir()) {
// Indicate a directory.
Serial.write('/');
}
Serial.println();
file.close();
}
if (dir.getError()) {
Serial.println("openNext failed");
} else {
Serial.println("Done!");
}
ftpSrv.begin("esp8266","esp8266"); //username, password for ftp.
}
void loop(void) {
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,367 @@
/*
* FtpServer Wio Terminal with SdFat library
* and with callbacks to the main actions of FTP server
* and a monitor on TFT
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/category/my-libraries/simple-ftp-server/
*
*/
#include "SdFat.h"
#include <rpcWiFi.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
#include <FtpServer.h>
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define DEG2RAD 0.0174532925
byte inc = 0;
unsigned int col = 0;
#define SD_CONFIG SdSpiConfig(SDCARD_SS_PIN, 2)
SdFs sd;
FtpServer ftpSrv;
const char *ssid = "reef-casa-sopra";
const char *password = "aabbccdd77";
#define MAIN_TOP 110
#define FREE_SPACE_PIE_X 80
#define FREE_SPACE_PIE_Y MAIN_TOP+40
#define FREE_SPACE_PIE_RADIUS 50
void freeSpacePieData(unsigned int freeSpace, unsigned int totalSpace) {
int pieFree = 360 - (freeSpace * 360 / totalSpace);
fillSegment(FREE_SPACE_PIE_X, FREE_SPACE_PIE_Y, 0, pieFree, FREE_SPACE_PIE_RADIUS, TFT_RED);
fillSegment(FREE_SPACE_PIE_X, FREE_SPACE_PIE_Y, pieFree, 360 - pieFree, FREE_SPACE_PIE_RADIUS, TFT_BLUE);
// Set "cursor" at top left corner of display (0,0) and select font 2
// (cursor will move to next line automatically during printing with 'tft.println'
// or stay on the line is there is room for the text with tft.print)
tft.setCursor(FREE_SPACE_PIE_X + 80, MAIN_TOP, 2);
// Set the font colour to be white with a black background, set text size multiplier to 1
tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextSize(1);
// We can now plot text on screen using the "print" class
Serial.print(freeSpace/1000);Serial.print("Mb/");Serial.print(String(totalSpace/1000));Serial.println("Mb");
tft.print(freeSpace/1000);tft.print("Mb/");tft.print(String(totalSpace/1000));tft.println("Mb");
}
void connectedDisconnected(bool connected) {
tft.fillCircle(FREE_SPACE_PIE_X + 80 + 10, MAIN_TOP+25+7, 10, (connected)?TFT_GREEN:TFT_RED);
tft.setCursor(FREE_SPACE_PIE_X + 80 + 25, MAIN_TOP+25, 2);
tft.println(" ");
tft.setCursor(FREE_SPACE_PIE_X + 80 + 25, MAIN_TOP+25, 2);
(connected)?tft.println("Connected!"):tft.println("Disconnected!");
}
void transfer(bool transfer, bool upload) {
tft.fillCircle(FREE_SPACE_PIE_X + 80 + 10, MAIN_TOP+25+25+7, 10, (transfer)?(upload)?TFT_GREEN:TFT_BLUE:TFT_RED);
tft.setCursor(FREE_SPACE_PIE_X + 80 + 25, MAIN_TOP+25+25, 2);
tft.println(" ");
tft.setCursor(FREE_SPACE_PIE_X + 80 + 25, MAIN_TOP+25+25, 2);
(transfer)?tft.println((upload)?"Upload!":"Download!"):tft.println("Idle!");
}
//index - starting at, n- how many chars
char* subString(const char *s, int index, int n){
char* b = (char*) malloc((strlen(s) + 1) * sizeof(char));
strcpy(b,s);
Serial.println("--------------------------------------");
Serial.println(s);
Serial.println(index);
Serial.println(n);
char *res = new char[n + 1];
Serial.println(res);
sprintf(res, "%.*s", n, b + index);
Serial.println(res);
free(b);
return res;
}
void fileTransfer(FtpTransferOperation ftpOperation, const char* filename, unsigned int transferredSize) {
int yoffset = 2;
tft.setCursor(20, MAIN_TOP+(FREE_SPACE_PIE_RADIUS*2)+yoffset, 2);
tft.println(F(" "));
tft.setCursor(20, MAIN_TOP+(FREE_SPACE_PIE_RADIUS*2)+yoffset, 2);
int lenfile = strlen(filename);
Serial.println(lenfile);
if (lenfile>22) {
tft.print(subString(filename, 0, 16));tft.print(F("~"));
tft.print( subString(filename, (lenfile-4), 4) );
} else {
tft.print(filename);
}
tft.setCursor(20+160, MAIN_TOP+(FREE_SPACE_PIE_RADIUS*2)+yoffset, 2);
tft.print(F(" "));
tft.setCursor(20+160, MAIN_TOP+(FREE_SPACE_PIE_RADIUS*2)+yoffset, 2);
tft.print(transferredSize);tft.print("Kb");
tft.setCursor(320-55, MAIN_TOP+(FREE_SPACE_PIE_RADIUS*2)+yoffset, 2);
switch (ftpOperation) {
case FTP_UPLOAD:
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.print(F("Upload"));
tft.setTextColor(TFT_WHITE, TFT_BLACK);
break;
case FTP_DOWNLOAD:
tft.setTextColor(TFT_BLUE, TFT_BLACK);
tft.print(F("Down"));
tft.setTextColor(TFT_WHITE, TFT_BLACK);
break;
case FTP_TRANSFER_STOP:
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.print(F("OK"));
tft.setTextColor(TFT_WHITE, TFT_BLACK);
break;
case FTP_TRANSFER_ERROR:
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.print(F("Error"));
tft.setTextColor(TFT_WHITE, TFT_BLACK);
break;
default:
break;
}
}
void wifiStrenght (int8_t RSSI, bool connection = false) {
Serial.print("RSSI --> ");Serial.println(RSSI);
int marginX = 30;
int startX = 90;
int widthW = 320-(startX+marginX);
int startY = 60;
int heightY = 10;
tft.setCursor(marginX, startY - 5, 2);
tft.print(F(" "));
tft.setCursor(marginX, startY - 5, 2);
if (connection) {
tft.print(F("Connectint to: "));
tft.print(ssid);
}else{
tft.println("WiFi str: ");
// 120 : 120-RSSI = 300 : x
tft.drawRoundRect(startX, startY, widthW, heightY, 5, TFT_WHITE);
uint32_t colorRSSI = TFT_GREEN;
if (abs(RSSI)<55) {
colorRSSI = TFT_GREEN;
} else if (abs(RSSI)<75) {
colorRSSI = TFT_YELLOW;
} else if (abs(RSSI)<75) {
colorRSSI = TFT_RED;
}
tft.fillRoundRect(startX+1, startY+1, (120+RSSI)*widthW/120, heightY-2, 5, colorRSSI);
tft.setCursor(marginX, startY + 15, 2);
tft.print("IP: ");
tft.println(WiFi.localIP());
}
}
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
Serial.print(">>>>>>>>>>>>>>> _callback " );
Serial.print(ftpOperation);
/* FTP_CONNECT,
* FTP_DISCONNECT,
* FTP_FREE_SPACE_CHANGE
*/
Serial.print(" ");
Serial.print(freeSpace);
Serial.print(" ");
Serial.println(totalSpace);
// freeSpace : totalSpace = x : 360
freeSpacePieData(freeSpace, totalSpace);
if (ftpOperation == FTP_CONNECT) connectedDisconnected(true);
if (ftpOperation == FTP_DISCONNECT) connectedDisconnected(false);
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
Serial.print(">>>>>>>>>>>>>>> _transferCallback " );
Serial.print(ftpOperation);
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
Serial.print(" ");
Serial.print(name);
Serial.print(" ");
Serial.println(transferredSize);
(ftpOperation==FTP_UPLOAD || ftpOperation==FTP_DOWNLOAD)?transfer(true, ftpOperation==FTP_UPLOAD):transfer(false, false);
fileTransfer(ftpOperation, name, transferredSize);
};
void setup()
{
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.begin(115200);
delay(1000);
tft.init();
tft.begin();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(TFT_BLACK, TFT_WHITE); tft.setTextSize(2);
tft.fillRoundRect(3, 3, 320-6, 40, 5, TFT_WHITE);
tft.drawCentreString("www.mischianti.org", 160, 14,1);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
freeSpacePieData(0, 0);
connectedDisconnected(false);
transfer(false, false);
wifiStrenght(0, true);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
WiFi.begin(ssid, password);
Serial.print(".");
tft.print(F("."));
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
wifiStrenght(WiFi.RSSI());
delay(1000);
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
FsFile dir;
FsFile file;
// Open root directory
if (!dir.open("/")){
Serial.println("dir.open failed");
}
ftpSrv.begin("wioterminal","wioterminal"); //username, password for ftp.
}
void loop() {
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}
// #########################################################################
// Draw circle segments
// #########################################################################
// x,y == coords of centre of circle
// start_angle = 0 - 359
// sub_angle = 0 - 360 = subtended angle
// r = radius
// colour = 16 bit colour value
int fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned int colour) {
// Calculate first pair of coordinates for segment start
float sx = cos((start_angle - 90) * DEG2RAD);
float sy = sin((start_angle - 90) * DEG2RAD);
uint16_t x1 = sx * r + x;
uint16_t y1 = sy * r + y;
// Draw colour blocks every inc degrees
for (int i = start_angle; i < start_angle + sub_angle; i++) {
// Calculate pair of coordinates for segment end
int x2 = cos((i + 1 - 90) * DEG2RAD) * r + x;
int y2 = sin((i + 1 - 90) * DEG2RAD) * r + y;
tft.fillTriangle(x1, y1, x2, y2, x, y, colour);
// Copy segment end to sgement start for next segment
x1 = x2;
y1 = y2;
}
}
// #########################################################################
// Return the 16 bit colour with brightness 0-100%
// #########################################################################
unsigned int brightness(unsigned int colour, int brightness) {
byte red = colour >> 11;
byte green = (colour & 0x7E0) >> 5;
byte blue = colour & 0x1F;
blue = (blue * brightness) / 100;
green = (green * brightness) / 100;
red = (red * brightness) / 100;
return (red << 11) + (green << 5) + blue;
}

View File

@@ -0,0 +1,110 @@
/*
* FtpServer esp8266 and esp32 with LittleFS
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <LittleFS.h>
#elif defined ESP32
#include <WiFi.h>
#include <FS.h>
#include <LittleFS.h>
#endif
#include <SimpleFTPServer.h>
const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.printf("FTP: Free space change, free %u of %u!\n", freeSpace, totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.printf("FTP: Upload of file %s byte %u\n", name, transferredSize);
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup(void){
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
#ifdef ESP32 //esp32 we send true to format spiffs if cannot mount
if (LittleFS.begin(true)) {
#elif defined ESP8266
if (LittleFS.begin()) {
#endif
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.println("LittleFS opened!");
ftpSrv.begin("user","password"); //username, password for ftp. (default 21, 50009 for PASV)
}
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
}

View File

@@ -0,0 +1,110 @@
/*
* FtpServer esp8266 and esp32 with SPIFFS
*
* AUTHOR: Renzo Mischianti
*
* https://www.mischianti.org/2020/02/08/ftp-server-on-esp8266-and-esp32
*
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#elif defined ESP32
#include <WiFi.h>
#include "SPIFFS.h"
#endif
#include <SimpleFTPServer.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
FtpServer ftpSrv; //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace){
switch (ftpOperation) {
case FTP_CONNECT:
Serial.println(F("FTP: Connected!"));
break;
case FTP_DISCONNECT:
Serial.println(F("FTP: Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
Serial.printf("FTP: Free space change, free %u of %u!\n", freeSpace, totalSpace);
break;
default:
break;
}
};
void _transferCallback(FtpTransferOperation ftpOperation, const char* name, unsigned int transferredSize){
switch (ftpOperation) {
case FTP_UPLOAD_START:
Serial.println(F("FTP: Upload start!"));
break;
case FTP_UPLOAD:
Serial.printf("FTP: Upload of file %s byte %u\n", name, transferredSize);
break;
case FTP_TRANSFER_STOP:
Serial.println(F("FTP: Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
Serial.println(F("FTP: Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
};
void setup(void){
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
/////FTP Setup, ensure SPIFFS is started before ftp; /////////
#ifdef ESP32 //esp32 we send true to format spiffs if cannot mount
if (SPIFFS.begin(true)) {
#elif defined ESP8266
if (SPIFFS.begin()) {
#endif
ftpSrv.setCallback(_callback);
ftpSrv.setTransferCallback(_transferCallback);
Serial.println("SPIFFS opened!");
ftpSrv.begin("esp8266","esp8266"); //username, password for ftp. (default 21, 50009 for PASV)
}
}
void loop(void){
ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
// server.handleClient(); //example if running a webserver you still need to call .handleClient();
}

View File

@@ -0,0 +1,17 @@
#######################################
# Datatypes (KEYWORD1)
#######################################
SimpleFtpServer KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
setLocalIp KEYWORD2
credentials KEYWORD2
setCallback KEYWORD2
setTransferCallback KEYWORD2
handleFTP KEYWORD2

View File

@@ -0,0 +1,21 @@
{
"name": "SimpleFTPServer",
"description": "Simple FTP Server for using esp8266, esp32, STM32, Arduino",
"keywords": "arduino, esp8266, esp32, stm32, rp2040, Raspberry Pi, ftp, FtpServer, spiffs, Fat, LittleFS, Ethernet, WiFi, WiFiNINA",
"homepage": "https://www.mischianti.org/category/my-libraries/simple-ftp-server/",
"authors":
{
"name": "Renzo Mischianti",
"email": "renzo.mischianti@gmail.com",
"url": "https://www.mischianti.org"
},
"repository":
{
"type": "git",
"url": "https://github.com/xreef/SimpleFTPServer"
},
"url": "https://www.mischianti.org",
"frameworks": "Arduino",
"version": "2.1.6",
"platforms": "*"
}

View File

@@ -0,0 +1,11 @@
name=SimpleFTPServer
version=2.1.6
author=Renzo Mischianti <renzo.mischianti@gmail.com>
maintainer=Renzo Mischianti <renzo.mischianti@gmail.com>
sentence=Simple FTP server for esp8266, esp32, STM32, Raspberry Pi Pico and Arduino
paragraph=Simple FTP server for Raspberry Pi Pico W (LittleFS), esp8266 (SPIFFS and LittleFS or SD, SdFat 2.x), esp32 (SPIFFS, LittleFS and FFAT or SD, SdFat 2.x) and Arduino (SdFat, SD basic lib with 8.3 file format), Wio Terminal (Seed_SD, SdFat 2.x), Arduino MKR (SdFat 2), STM32 (Flash >64K SdFat 2.x and SPI Flash). Support w5500, w5100 and enc28j60. With internal callback to chck the phase of communication.
category=Communication
url=https://www.mischianti.org/category/my-libraries/simple-ftp-server/
repository=https://github.com/xreef/SimpleFTPServer.git
architectures=*
includes=SimpleFTPServer.h

View File

@@ -3,7 +3,7 @@
"name": "IoTmanagerVer4",
"apssid": "IoTmanager",
"appass": "",
"routerssid": "rise",
"routerssid": "iot",
"routerpass": "hostel3333",
"timezone": 2,
"ntp": "pool.ntp.org",
@@ -25,7 +25,7 @@
"projectProp": {
"platformio": {
"default_envs": "esp8266_4mb",
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota"
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota"
}
},
"modules": {
@@ -34,6 +34,10 @@
"path": "src/modules/virtual/Cron",
"active": true
},
{
"path": "src/modules/virtual/GoogleSheet",
"active": false
},
{
"path": "src/modules/virtual/Loging",
"active": true
@@ -112,6 +116,10 @@
"path": "src/modules/sensors/DS2401",
"active": false
},
{
"path": "src/modules/sensors/Ds2423",
"active": false
},
{
"path": "src/modules/sensors/Emon",
"active": false
@@ -152,6 +160,10 @@
"path": "src/modules/sensors/IoTWiegand",
"active": false
},
{
"path": "src/modules/sensors/ld2410",
"active": false
},
{
"path": "src/modules/sensors/Max6675",
"active": false
@@ -160,6 +172,10 @@
"path": "src/modules/sensors/Mhz19",
"active": false
},
{
"path": "src/modules/sensors/Ntc",
"active": false
},
{
"path": "src/modules/sensors/Pzem004t",
"active": true
@@ -176,6 +192,10 @@
"path": "src/modules/sensors/S8",
"active": true
},
{
"path": "src/modules/sensors/Scd40",
"active": false
},
{
"path": "src/modules/sensors/Sds011",
"active": false
@@ -222,6 +242,10 @@
"path": "src/modules/exec/EspCam",
"active": false
},
{
"path": "src/modules/exec/Ftp",
"active": false
},
{
"path": "src/modules/exec/HttpGet",
"active": false
@@ -296,6 +320,10 @@
"path": "src/modules/display/NextionUpload",
"active": false
},
{
"path": "src/modules/display/Smi2_m",
"active": true
},
{
"path": "src/modules/display/Ws2812b",
"active": false

View File

@@ -7,6 +7,9 @@ lib_deps_external =
bblanchon/ArduinoJson @6.18.0
knolleary/PubSubClient
[env]
extra_scripts = pre:prebuildscript.py
[env:esp8266_1mb_ota]
lib_deps =
${common_env_data.lib_deps_external}
@@ -79,7 +82,7 @@ build_flags = -Desp8266_2mb="esp8266_2mb"
framework = arduino
board = d1_wroom_02
board_build.ldscript = eagle.flash.2m1m.ld
platform = espressif8266
platform = espressif8266 @4.2.0
monitor_filters = esp8266_exception_decoder
upload_speed = 921600
monitor_speed = 115200
@@ -100,7 +103,7 @@ build_flags = -Desp8266_2mb_ota="esp8266_2mb_ota"
framework = arduino
board = d1_wroom_02
board_build.ldscript = eagle.flash.2m256.ld
platform = espressif8266
platform = espressif8266 @4.2.0
monitor_filters = esp8266_exception_decoder
upload_speed = 921600
monitor_speed = 115200
@@ -174,6 +177,29 @@ build_src_filter =
+<modules/*.cpp>
${env:esp32_4mb_fromitems.build_src_filter}
[env:esp32s2_4mb]
lib_deps =
${common_env_data.lib_deps_external}
${env:esp32s2_4mb_fromitems.lib_deps}
build_flags =
-Desp32s2_4mb="esp32s2_4mb"
-DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MODE=0
framework = arduino
board = lolin_s2_mini
platform = espressif32 @6.3.1
monitor_filters = esp32_exception_decoder
upload_speed = 921600
monitor_speed = 115200
debug_tool = esp-prog
board_build.filesystem = littlefs
build_src_filter =
+<*.cpp>
+<classes/*.cpp>
+<utils/*.cpp>
+<modules/*.cpp>
${env:esp32s2_4mb_fromitems.build_src_filter}
[env:esp8266_1mb_ota_fromitems]
lib_deps =
adafruit/Adafruit BME280 Library
@@ -222,11 +248,11 @@ lib_deps =
adafruit/Adafruit BME280 Library
adafruit/Adafruit BMP280 Library
https://github.com/milesburton/Arduino-Temperature-Control-Library
IRremote @ ^4.1.2
https://github.com/tremaru/iarduino_RTC
robtillaart/SHT2x@^0.1.1
WEMOS SHT3x@1.0.0
plerup/EspSoftwareSerial
gyverlibs/EncButton @ ^2.0
adafruit/Adafruit MCP23017 Arduino Library@^2.1.0
adafruit/Adafruit BusIO @ ^1.13.2
adafruit/Adafruit BusIO @ ^1.13.2
@@ -247,7 +273,7 @@ build_src_filter =
+<modules/sensors/Bmp280>
+<modules/sensors/Ds18b20>
+<modules/sensors/Impulse>
+<modules/sensors/IRswitch>
+<modules/sensors/Ntc>
+<modules/sensors/Pzem004t>
+<modules/sensors/RTC>
+<modules/sensors/Sht20>
@@ -256,6 +282,8 @@ build_src_filter =
+<modules/sensors/UART>
+<modules/exec/ButtonIn>
+<modules/exec/ButtonOut>
+<modules/exec/Buzzer>
+<modules/exec/Enconder>
+<modules/exec/Mcp23017>
+<modules/exec/Multitouch>
+<modules/exec/Pcf8574>
@@ -348,6 +376,7 @@ build_src_filter =
+<modules/sensors/Bmp280>
+<modules/sensors/Ds18b20>
+<modules/sensors/Impulse>
+<modules/sensors/Ntc>
+<modules/sensors/Pzem004t>
+<modules/sensors/RTC>
+<modules/sensors/Sht20>
@@ -356,6 +385,7 @@ build_src_filter =
+<modules/sensors/UART>
+<modules/exec/ButtonIn>
+<modules/exec/ButtonOut>
+<modules/exec/Buzzer>
+<modules/exec/Enconder>
+<modules/exec/Mcp23017>
+<modules/exec/Multitouch>
@@ -430,6 +460,7 @@ lib_deps =
robtillaart/SHT2x@^0.1.1
WEMOS SHT3x@1.0.0
plerup/EspSoftwareSerial
gyverlibs/EncButton @ ^2.0
https://github.com/RoboticsBrno/ServoESP32
adafruit/Adafruit MCP23017 Arduino Library@^2.1.0
adafruit/Adafruit BusIO @ ^1.13.2
@@ -462,6 +493,8 @@ build_src_filter =
+<modules/sensors/UART>
+<modules/exec/ButtonIn>
+<modules/exec/ButtonOut>
+<modules/exec/Buzzer>
+<modules/exec/Enconder>
+<modules/exec/IoTServo>
+<modules/exec/Mcp23017>
+<modules/exec/Mp3>
@@ -470,4 +503,18 @@ build_src_filter =
+<modules/exec/Pwm32>
+<modules/exec/TelegramLT>
+<modules/display/Lcd2004>
+<modules/display/Smi2_m>
[env:esp32s2_4mb_fromitems]
lib_deps =
build_src_filter =
+<modules/virtual/Cron>
+<modules/virtual/Loging>
+<modules/virtual/LogingDaily>
+<modules/virtual/Timer>
+<modules/virtual/Variable>
+<modules/virtual/VariableColor>
+<modules/virtual/VButton>
+<modules/sensors/Acs712>
+<modules/exec/TelegramLT>

13
prebuildscript.py Normal file
View File

@@ -0,0 +1,13 @@
import os
import configparser
config = configparser.ConfigParser() # создаём объекта парсера INI
config.read("platformio.ini")
deviceName = config["platformio"]["default_envs"]
# удаляем объектный файл где используется время сборки, для обновления
try:
os.remove("./.pio/build/"+deviceName+"/src/Main.cpp.o")
except OSError as e:
# If it fails, inform the user.
print("Error: %s - %s." % (e.filename, e.strerror))

View File

@@ -2,64 +2,94 @@
const String getThisDevice() {
String thisDevice = "{}";
jsonWriteStr_(thisDevice, F("devicelist_"), ""); //метка для парсинга
jsonWriteStr_(thisDevice, F("wg"), jsonReadStr(settingsFlashJson, F("wg"))); //рабочая группа
// jsonWriteStr_(thisDevice, F("devicelist_"), ""); // метка для парсинга - она не нужна теперь
jsonWriteStr_(thisDevice, F("wg"), jsonReadStr(settingsFlashJson, F("wg"))); // рабочая группа
jsonWriteStr_(thisDevice, F("ip"), jsonReadStr(settingsFlashJson, F("ip")));
jsonWriteStr_(thisDevice, F("id"), jsonReadStr(settingsFlashJson, F("id")));
jsonWriteStr_(thisDevice, F("name"), jsonReadStr(settingsFlashJson, F("name")));
// приложение svelte хранит свой список и в нем поддерживает корректные статусы, а при получении этого списка
// лишь изменяет в своем те элементы массива которые добавились новые, не трогая остальные
jsonWriteBool_(thisDevice, F("status"), false);
jsonWriteInt_(thisDevice, F("fv"), FIRMWARE_VERSION);
thisDevice = "[" + thisDevice + "]";
return thisDevice;
}
void addThisDeviceToList() {
devListHeapJson = getThisDevice();
SerialPrint("i", "List", "Add this dev to list");
if (jsonReadInt(settingsFlashJson, F("udps")) != 0) {
// если включен автопоиск то записываем это устройство в оперативную память
devListHeapJson = getThisDevice();
} else {
// если выключен автопоиск то записываем это устройство в флешь память
// если файла не было никогда
String list = readFile("/devlist.json", 2048);
if (list == "failed") {
writeFile("/devlist.json", getThisDevice());
} else {
// если файл был то перепишем в нем первое устройство - to do
}
}
SerialPrint("i", F("List"), F("This dev added to list"));
}
#ifdef UDP_ENABLED
AsyncUDP asyncUdp;
void asyncUdpInit() {
void udpListningInit() {
if (asyncUdp.listenMulticast(IPAddress(239, 255, 255, 255), 4210)) {
asyncUdp.onPacket([](AsyncUDPPacket packet) {
// Serial.print("UDP Packet Type: ");
// Serial.println(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast");
// Serial.print("From: ");
// Serial.print(packet.remoteIP());
// Serial.print(":");
// Serial.println(packet.remotePort());
// Serial.print("To: ");
// Serial.print(packet.localIP());
// Serial.print(":");
// Serial.println(packet.localPort());
// Serial.print(", Length: ");
// Serial.print(packet.length());
// Serial.print(", Data: ");
// Serial.write(packet.data(), packet.length());
//String data = {packet.data(), packet.length()}; // для ESP32 подходит как замена uint8tToString, но 8266 не переваривает
String data = uint8tToString(packet.data(), packet.length());
String remoteWorkgroup = "";
data.replace("[", "");
data.replace("]", "");
if (jsonRead(data, F("wg"), remoteWorkgroup)) { // проверяем чтоб полученный формат был Json и заодно вытягиваем имя группы
String loacalWorkgroup = "";
jsonRead(settingsFlashJson, F("wg"), loacalWorkgroup);
if (remoteWorkgroup == loacalWorkgroup) {
SerialPrint("i", F("UDP"), "IP: " + packet.remoteIP().toString() + ":" + String(packet.remotePort()));
jsonMergeArrays(devListHeapJson, data);
// если был включен автоматический поиск устройств то начнем запись в оперативную память
if (jsonReadInt(settingsFlashJson, F("udps")) != 0) {
// Serial.print("UDP Packet Type: ");
// Serial.println(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast");
// Serial.print("From: ");
// Serial.print(packet.remoteIP());
// Serial.print(":");
// Serial.println(packet.remotePort());
// Serial.print("To: ");
// Serial.print(packet.localIP());
// Serial.print(":");
// Serial.println(packet.localPort());
// Serial.print(", Length: ");
// Serial.print(packet.length());
// Serial.print(", Data: ");
// Serial.write(packet.data(), packet.length());
// String data = {packet.data(), packet.length()}; // для ESP32 подходит как замена uint8tToString, но 8266 не переваривает
String data = uint8tToString(packet.data(), packet.length());
String remoteWorkgroup = "";
data.replace("[", "");
data.replace("]", "");
if (jsonRead(data, F("wg"), remoteWorkgroup)) { // проверяем чтоб полученный формат был Json и заодно вытягиваем имя группы
String loacalWorkgroup = "";
jsonRead(settingsFlashJson, F("wg"), loacalWorkgroup);
if (remoteWorkgroup == loacalWorkgroup) {
SerialPrint("i", F("UDP"), "IP: " + packet.remoteIP().toString() + ":" + String(packet.remotePort()));
jsonMergeArrays(devListHeapJson, data);
// эксперементальный вариант отправки нового списка сразу по приходу
// sendStringToWs("devlis", devListHeapJson, -1);
}
} else {
SerialPrint("E", F("UDP"), F("Udp packet invalid"));
}
// reply to the client
// String ip = WiFi.localIP().toString();
// asyncUdp.broadcastTo(ip.c_str(), packet.remotePort());
// packet.printf(ip.c_str(), packet.length());
} else {
SerialPrint("E", F("UDP"), F("Udp packet invalid"));
devListHeapJson = "";
}
// reply to the client
// String ip = WiFi.localIP().toString();
// asyncUdp.broadcastTo(ip.c_str(), packet.remotePort());
// packet.printf(ip.c_str(), packet.length());
});
}
//будем отправлять каждые 60 секунд презентацию данного устройства
SerialPrint("i", F("UDP"), F("Udp listning inited"));
}
void udpBroadcastInit() {
// будем отправлять каждые 60 секунд презентацию данного устройства
ts.add(
UDP, 60000, [&](void*) { // UDPP
if (isNetworkActive()) {
@@ -71,11 +101,11 @@ void asyncUdpInit() {
},
nullptr, true);
SerialPrint("i", F("UDP"), F("Udp Init"));
SerialPrint("i", F("UDP"), F("Udp broadcast inited"));
}
void jsonMergeArrays(String& existJson, String& incJson) {
DynamicJsonDocument incJsonDoc(1024);
DynamicJsonDocument incJsonDoc(4096);
DeserializationError incJsonError = deserializeJson(incJsonDoc, incJson);
// if (incJsonError) { // upd: devlist заведомо верный, зачем проверять еще раз?
// SerialPrint("E", F("UDP"), "Invailed json in incomming udp packet " + String(incJsonError.f_str()));
@@ -83,7 +113,7 @@ void jsonMergeArrays(String& existJson, String& incJson) {
// return;
// }
DynamicJsonDocument existJsonDoc(1024);
DynamicJsonDocument existJsonDoc(4096);
DeserializationError existJsonError = deserializeJson(existJsonDoc, existJson);
// if (existJsonError) { // upd: полученный json уже проверен на целостность
// SerialPrint("E", F("UDP"), "Invailed json in existing udp dev list " + String(incJsonError.f_str()));

View File

@@ -26,13 +26,13 @@ void globalVarsSync() {
// jsonWriteStr_(ssidListHeapJson, "ssids_", ""); //метка для парсинга удалить
}
//к удалению. не используется
// String getParamsJson() {
// String json;
// serializeJson(*getLocalItemsAsJSON(), json);
// jsonWriteStr_(json, "params", "");
// return json;
// }
// к удалению. не используется
// String getParamsJson() {
// String json;
// serializeJson(*getLocalItemsAsJSON(), json);
// jsonWriteStr_(json, "params", "");
// return json;
// }
void syncSettingsFlashJson() {
writeFile(F("settings.json"), settingsFlashJson);
@@ -43,7 +43,7 @@ void syncValuesFlashJson() {
}
const String getChipId() {
return String(ESP_getChipId()) + "-" + String(ESP_getFlashChipId());
return String(ESP_getChipId()) + "-" + String(getFlashChipIdNew()); // + "v" + String(FIRMWARE_VERSION);
}
void setChipId() {
@@ -76,6 +76,8 @@ uint32_t ESP_getChipId(void) {
#endif
}
// устарела используем новую функцию ниже
#ifndef esp32s2_4mb
uint32_t ESP_getFlashChipId(void) {
#ifdef ESP32
// Нет аналогичной (без доп.кода) функций в 32
@@ -85,6 +87,32 @@ uint32_t ESP_getFlashChipId(void) {
return ESP.getFlashChipId();
#endif
}
#endif
// https://github.com/espressif/arduino-esp32/issues/6945#issuecomment-1199900892
// получение flash ch id из проекта esp easy
uint32_t getFlashChipIdNew() {
// Cache since size does not change
static uint32_t flashChipId = 0;
if (flashChipId == 0) {
#ifdef ESP32
uint32_t tmp = g_rom_flashchip.device_id;
for (int i = 0; i < 3; ++i) {
flashChipId = flashChipId << 8;
flashChipId |= (tmp & 0xFF);
tmp = tmp >> 8;
}
// esp_flash_read_id(nullptr, &flashChipId);
#elif defined(ESP8266)
flashChipId = ESP.getFlashChipId();
#endif // ifdef ESP32
}
return flashChipId;
}
const String getMacAddress() {
uint8_t mac[6];

View File

@@ -3,6 +3,9 @@
#include "classes/IoTDB.h"
#include "utils/Statistic.h"
#include <Wire.h>
#ifdef esp32s2_4mb
#include <USB.h>
#endif
IoTScenario iotScen; // объект управления сценарием
@@ -10,8 +13,6 @@ String volStrForSave = "";
unsigned long currentMillis;
unsigned long prevMillis;
void elementsLoop() {
// передаем управление каждому элементу конфигурации для выполнения своих функций
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
@@ -29,69 +30,65 @@ void elementsLoop() {
handleEvent();
}
#define SETUPBASE_ERRORMARKER 0
#define SETUPCONF_ERRORMARKER 1
#define SETUPSCEN_ERRORMARKER 2
#define SETUPINET_ERRORMARKER 3
#define SETUPLAST_ERRORMARKER 4
#define TICKER_ERRORMARKER 5
#define HTTP_ERRORMARKER 6
#define SOCKETS_ERRORMARKER 7
#define MQTT_ERRORMARKER 8
#define MODULES_ERRORMARKER 9
#define SETUPBASE_ERRORMARKER 0
#define SETUPCONF_ERRORMARKER 1
#define SETUPSCEN_ERRORMARKER 2
#define SETUPINET_ERRORMARKER 3
#define SETUPLAST_ERRORMARKER 4
#define TICKER_ERRORMARKER 5
#define HTTP_ERRORMARKER 6
#define SOCKETS_ERRORMARKER 7
#define MQTT_ERRORMARKER 8
#define MODULES_ERRORMARKER 9
#define COUNTER_ERRORMARKER 4 // количество шагов счетчика
#define STEPPER_ERRORMARKER 100000 // размер шага счетчика интервала доверия выполнения блока кода мкс
#define COUNTER_ERRORMARKER 4 // количество шагов счетчика
#define STEPPER_ERRORMARKER 100000 // размер шага счетчика интервала доверия выполнения блока кода мкс
#ifdef esp32_4mb
static int IRAM_ATTR initErrorMarkerId = 0; // ИД маркера
static int IRAM_ATTR initErrorMarkerId = 0; // ИД маркера
static int IRAM_ATTR errorMarkerId = 0;
static int IRAM_ATTR errorMarkerCounter = 0;
hw_timer_t *My_timer = NULL;
void IRAM_ATTR onTimer(){
void IRAM_ATTR onTimer() {
if (errorMarkerCounter >= 0) {
if (errorMarkerCounter >= COUNTER_ERRORMARKER) {
errorMarkerId = initErrorMarkerId;
errorMarkerCounter = -1;
} else
} else
errorMarkerCounter++;
}
}
}
#endif
void initErrorMarker(int id) {
#ifdef esp32_4mb
#ifdef esp32_4mb
initErrorMarkerId = id;
errorMarkerCounter = 0;
#endif
}
void stopErrorMarker(int id) {
#ifdef esp32_4mb
#ifdef esp32_4mb
errorMarkerCounter = -1;
if (errorMarkerId)
SerialPrint("I", "WARNING!", "A lazy (freezing loop more than " + (String)(COUNTER_ERRORMARKER * STEPPER_ERRORMARKER / 1000) + " ms) section has been found! With ID=" + (String)errorMarkerId);
if (errorMarkerId)
SerialPrint("I", "WARNING!", "A lazy (freezing loop more than " + (String)(COUNTER_ERRORMARKER * STEPPER_ERRORMARKER / 1000) + " ms) section has been found! With ID=" + (String)errorMarkerId);
errorMarkerId = 0;
initErrorMarkerId = 0;
#endif
}
void setup() {
#ifdef esp32_4mb
#ifdef esp32s2_4mb
USB.begin();
#endif
#ifdef esp32_4mb
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, STEPPER_ERRORMARKER, true);
timerAlarmEnable(My_timer);
//timerAlarmDisable(My_timer);
// timerAlarmDisable(My_timer);
initErrorMarker(SETUPBASE_ERRORMARKER);
#endif
@@ -102,7 +99,7 @@ void setup() {
Serial.println(F("--------------started----------------"));
// создание экземпляров классов
// myNotAsyncActions = new NotAsync(do_LAST);
// myNotAsyncActions = new NotAsync(do_LAST);
// инициализация файловой системы
fileSystemInit();
@@ -110,6 +107,9 @@ void setup() {
Serial.println("FIRMWARE NAME " + String(FIRMWARE_NAME));
Serial.println("FIRMWARE VERSION " + String(FIRMWARE_VERSION));
Serial.println("WEB VERSION " + getWebVersion());
const String buildTime = String(BUILD_DAY) + "." + String(BUILD_MONTH) + "." + String(BUILD_YEAR) + " " + String(BUILD_HOUR) + ":" + String(BUILD_MIN) + ":" + String(BUILD_SEC);
Serial.println("BUILD TIME " + buildTime);
jsonWriteStr_(errorsHeapJson, F("bt"), buildTime);
Serial.println(F("------------------------"));
// получение chip id
@@ -129,7 +129,7 @@ void setup() {
jsonRead(settingsFlashJson, "i2cFreq", i2cFreq, false);
jsonRead(settingsFlashJson, "i2c", i2c, false);
if (i2c != 0) {
#ifdef esp32_4mb
#ifdef ESP32
Wire.end();
Wire.begin(pinSDA, pinSCL, (uint32_t)i2cFreq);
#else
@@ -141,23 +141,19 @@ void setup() {
// настраиваем микроконтроллер
configure("/config.json");
stopErrorMarker(SETUPCONF_ERRORMARKER);
initErrorMarker(SETUPSCEN_ERRORMARKER);
// подготавливаем сценарии
iotScen.loadScenario("/scenario.txt");
// создаем событие завершения инициализации основных моментов для возможности выполнения блока кода при загрузке
createItemFromNet("onInit", "1", 1);
elementsLoop();
stopErrorMarker(SETUPSCEN_ERRORMARKER);
stopErrorMarker(SETUPSCEN_ERRORMARKER);
initErrorMarker(SETUPINET_ERRORMARKER);
// подключаемся к роутеру
@@ -181,8 +177,6 @@ void setup() {
stopErrorMarker(SETUPINET_ERRORMARKER);
initErrorMarker(SETUPLAST_ERRORMARKER);
// NTP
@@ -191,11 +185,10 @@ void setup() {
// инициализация задач переодического выполнения
periodicTasksInit();
// синхронизация списка устройств
addThisDeviceToList();
// запуск работы udp
asyncUdpInit();
addThisDeviceToList();
udpListningInit();
udpBroadcastInit();
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
createItemFromNet("onStart", "1", 1);
@@ -227,8 +220,6 @@ void setup() {
stopErrorMarker(SETUPLAST_ERRORMARKER);
}
void loop() {
#ifdef LOOP_DEBUG
unsigned long st = millis();
@@ -253,7 +244,7 @@ void loop() {
initErrorMarker(MQTT_ERRORMARKER);
mqttLoop();
stopErrorMarker(MQTT_ERRORMARKER);
initErrorMarker(MODULES_ERRORMARKER);
elementsLoop();
stopErrorMarker(MODULES_ERRORMARKER);

View File

@@ -6,7 +6,7 @@ void mqttInit() {
WIFI_MQTT_CONNECTION_CHECK, MQTT_RECONNECT_INTERVAL,
[&](void*) {
if (WiFi.status() == WL_CONNECTED) {
SerialPrint("i", F("WIFI"), "OK: " + jsonReadStr(settingsFlashJson, F("ip")));
SerialPrint("i", F("WIFI"), "http://" + jsonReadStr(settingsFlashJson, F("ip")));
wifiUptimeCalc();
if (mqtt.connected()) {
SerialPrint("i", F("MQTT"), "OK");
@@ -133,10 +133,10 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
if (payloadStr.startsWith("HELLO")) {
SerialPrint("i", F("MQTT"), F("Full update"));
//публикация всех виджетов
// публикация всех виджетов
publishWidgets();
//публикация всех статус сообщений при подключении приложения и генерация события подключения приложения в модулях
// публикация всех статус сообщений при подключении приложения и генерация события подключения приложения в модулях
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
if ((*it)->iAmLocal) {
publishStatusMqtt((*it)->getID(), (*it)->getValue());
@@ -144,7 +144,7 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
}
}
//отправка данных графиков - данный код будет оптимизирован после завершения написания приложения с новыми графиками
// отправка данных графиков - данный код будет оптимизирован после завершения написания приложения с новыми графиками
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
if ((*it)->getSubtype() == "Loging" || "LogingDaily") {
(*it)->setPublishDestination(TO_MQTT);
@@ -162,16 +162,17 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
else if (topicStr.indexOf(F("control")) != -1) {
String key = selectFromMarkerToMarker(topicStr, "/", 3);
String valueIfJson = ""; // проверяем формат, если json то берем статус, иначе - как есть
String valueIfJson = ""; // проверяем формат, если json то берем статус, иначе - как есть
if (!jsonRead(payloadStr, F("status"), valueIfJson, false))
generateOrder(key, payloadStr);
else generateOrder(key, valueIfJson);
else
generateOrder(key, valueIfJson);
SerialPrint("i", F("=>MQTT"), "Msg from iotmanager app: " + key + " " + payloadStr);
}
//здесь мы получаем события с других устройств, которые потом проверяются в сценариях этого устройства
// здесь мы получаем события с других устройств, которые потом проверяются в сценариях этого устройства
else if (topicStr.indexOf("event") != -1) {
if (!jsonReadBool(settingsFlashJson, "mqttin")) {
return;
@@ -251,7 +252,7 @@ void publishWidgets() {
DeserializationError error = deserializeJson(doc, file);
if (error) {
SerialPrint("E", F("MQTT"), error.f_str());
jsonWriteInt(errorsHeapJson, F("jse3"), 1); //Ошибка чтения json файла с виджетами при отправки в mqtt
jsonWriteInt(errorsHeapJson, F("jse3"), 1); // Ошибка чтения json файла с виджетами при отправки в mqtt
}
JsonArray arr = doc.as<JsonArray>();
for (JsonVariant value : arr) {
@@ -292,43 +293,43 @@ void handleMqttStatus(bool send, int state) {
const String getStateStr(int e) {
switch (e) {
case -4: //Нет ответа от сервера
case -4: // Нет ответа от сервера
return F("e1");
break;
case -3: //Соединение было разорвано
case -3: // Соединение было разорвано
return F("e2");
break;
case -2: //Ошибка соединения. Обычно возникает когда неверно указано название сервера MQTT
case -2: // Ошибка соединения. Обычно возникает когда неверно указано название сервера MQTT
return F("e3");
break;
case -1: //Клиент был отключен
case -1: // Клиент был отключен
return F("e4");
break;
case 0: //подключено
case 0: // подключено
return F("e5");
break;
case 1: //Ошибка версии
case 1: // Ошибка версии
return F("e6");
break;
case 2: //Отклонен идентификатор
case 2: // Отклонен идентификатор
return F("e7");
break;
case 3: //Не могу установить соединение
case 3: // Не могу установить соединение
return F("e8");
break;
case 4: //Неправильное имя пользователя/пароль
case 4: // Неправильное имя пользователя/пароль
return F("e9");
break;
case 5: //Не авторизован для подключения
case 5: // Не авторизован для подключения
return F("e10");
break;
case 6: //Название сервера пустое
case 6: // Название сервера пустое
return F("e11");
break;
case 7: //Имя пользователя или пароль пустые
case 7: // Имя пользователя или пароль пустые
return F("e12");
break;
case 8: //Подключение в процессе
case 8: // Подключение в процессе
return F("e13");
break;
default:

View File

@@ -58,7 +58,50 @@ void printGlobalVarSize() {
String ESP_getResetReason(void) {
return ESP.getResetReason();
}
#else
#endif
#ifdef esp32s2_4mb
String ESP_getResetReason(void) {
return ESP32GetResetReason(0); // CPU 0
}
String ESP32GetResetReason(uint32_t cpu_no) {
// tools\sdk\include\esp32\rom\rtc.h
switch (rtc_get_reset_reason((RESET_REASON)cpu_no)) {
case POWERON_RESET:
return F("Vbat power on reset"); // 1
case RTC_SW_SYS_RESET:
return F("Software reset digital core"); // 3
// case OWDT_RESET:
// return F("Legacy Watchdog reset digital core"); // 4
case DEEPSLEEP_RESET:
return F("Deep Sleep reset digital core"); // 5
// case SDIO_RESET:
// return F("Reset by SLC module, reset digital core"); // 6
case TG0WDT_SYS_RESET:
return F("Timer Group0 Watchdog reset digital core"); // 7
case TG1WDT_SYS_RESET:
return F("Timer Group1 Watchdog reset digital core"); // 8
case RTCWDT_SYS_RESET:
return F("RTC Watchdog Reset digital core"); // 9
case INTRUSION_RESET:
return F("Instrusion tested to reset CPU"); // 10
case TG0WDT_CPU_RESET:
return F("Time Group reset CPU"); // 11
case RTC_SW_CPU_RESET:
return F("Software reset CPU"); // 12
case RTCWDT_CPU_RESET:
return F("RTC Watchdog Reset CPU"); // 13
// case EXT_CPU_RESET:
// return F("or APP CPU, reseted by PRO CPU"); // 14
case RTCWDT_BROWN_OUT_RESET:
return F("Reset when the vdd voltage is not stable"); // 15
case RTCWDT_RTC_RESET:
return F("RTC Watchdog reset digital core and rtc module"); // 16
default:
return F("NO_MEAN"); // 0
}
}
#endif
#ifdef esp32_4mb
String ESP_getResetReason(void) {
return ESP32GetResetReason(0); // CPU 0
}

View File

@@ -48,17 +48,19 @@ bool upgradeFS() {
#endif
#ifdef ESP32
httpUpdate.rebootOnUpdate(false);
//обновляем little fs с помощью метода обновления spiffs
// обновляем little fs с помощью метода обновления spiffs
HTTPUpdateResult retFS = httpUpdate.updateSpiffs(wifiClient, getBinPath("littlefs.bin"));
#endif
//если FS обновилась успешно
// если FS обновилась успешно
if (retFS == HTTP_UPDATE_OK) {
SerialPrint("!!!", F("Update"), F("FS upgrade done!"));
handleUpdateStatus(true, UPDATE_FS_COMPLETED);
ret = true;
} else {
handleUpdateStatus(true, UPDATE_FS_FAILED);
}
handleUpdateStatus(true, UPDATE_FS_FAILED);
return ret;
}
@@ -72,22 +74,23 @@ bool upgradeBuild() {
handleUpdateStatus(true, PATH_ERROR);
return ret;
}
#if defined (esp8266_4mb) || defined (esp8266_1mb) || defined (esp8266_1mb_ota) || defined (esp8266_2mb) || defined (esp8266_2mb_ota)
#if defined(esp8266_4mb) || defined(esp8266_1mb) || defined(esp8266_1mb_ota) || defined(esp8266_2mb) || defined(esp8266_2mb_ota)
ESPhttpUpdate.rebootOnUpdate(false);
t_httpUpdate_return retBuild = ESPhttpUpdate.update(wifiClient, getBinPath("firmware.bin"));
#endif
#ifdef esp32_4mb
#ifdef ESP32
httpUpdate.rebootOnUpdate(false);
HTTPUpdateResult retBuild = httpUpdate.update(wifiClient, getBinPath("firmware.bin"));
#endif
//если BUILD обновился успешно
// если BUILD обновился успешно
if (retBuild == HTTP_UPDATE_OK) {
SerialPrint("!!!", F("Update"), F("BUILD upgrade done!"));
handleUpdateStatus(true, UPDATE_BUILD_COMPLETED);
ret = true;
} else {
handleUpdateStatus(true, UPDATE_BUILD_FAILED);
}
handleUpdateStatus(true, UPDATE_BUILD_FAILED);
return ret;
}
@@ -132,5 +135,5 @@ void saveUserDataToFlash() {
void handleUpdateStatus(bool send, int state) {
jsonWriteInt_(errorsHeapJson, F("upd"), state);
if (!send) sendStringToWs("errors", errorsHeapJson, -1);
if (send) sendStringToWs("errors", errorsHeapJson, -1);
}

View File

@@ -135,11 +135,12 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
// RouterFind(jsonReadStr(settingsFlashJson, F("routerssid")));
}
// обработка кнопки сохранить настройки wifi
// обработка кнопки сохранить settings.json
if (headerStr == "/sgnittes|") {
writeUint8tToString(payload, length, headerLenth, settingsFlashJson);
writeFileUint8tByFrames("settings.json", payload, length, headerLenth, 256);
sendStringToWs("errors", errorsHeapJson, num);
// если не было создано приема данных по udp - то создадим его
addThisDeviceToList();
}
@@ -162,9 +163,22 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
// Страница веб интерфейса list
//----------------------------------------------------------------------//
// отвечаем данными на запрос страницы
// отвечаем данными на запрос страницы list
if (headerStr == "/list|") {
sendStringToWs("devlis", devListHeapJson, num);
sendStringToWs("settin", settingsFlashJson, num);
// отправим список устройств в зависимости от того что выбрал user
// sendDeviceList(num);
}
// отвечаем на запрос списка устройств (это отдельный запрос который делает приложение при подключении)
if (headerStr == "/devlist|") {
// отправим список устройств в зависимости от того что выбрал user
sendDeviceList(num);
}
// сохраняем данные листа
if (headerStr == "/tsil|") {
writeFileUint8tByFrames("devlist.json", payload, length, headerLenth, 256);
}
//----------------------------------------------------------------------//
@@ -307,7 +321,10 @@ void publishJsonWs(const String& topic, String& json) {
void periodicWsSend() {
sendStringToWs("ssidli", ssidListHeapJson, -1);
sendStringToWs("errors", errorsHeapJson, -1);
sendStringToWs("devlis", devListHeapJson, -1);
// отправляем переодичестки только в авто режиме
if (jsonReadInt(settingsFlashJson, F("udps")) != 0) {
sendStringToWs("devlis", devListHeapJson, -1);
}
}
#ifdef ESP32
@@ -413,3 +430,15 @@ void sendStringToWs(const String& header, String& payload, int client_id) {
standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize);
}
}
void sendDeviceList(uint8_t num) {
if (jsonReadInt(settingsFlashJson, F("udps")) != 0) {
// если включен автопоиск то отдаем список из оперативной памяти
SerialPrint("i", "FS", "heap list");
sendStringToWs("devlis", devListHeapJson, num);
} else {
// если выключен автопоиск то отдаем список из флешь памяти
sendFileToWsByFrames("/devlist.json", "devlis", "", num, WEB_SOCKETS_FRAME_SIZE);
SerialPrint("i", "FS", "flash list");
}
}

View File

@@ -15,6 +15,7 @@ IoTItem::IoTItem(const String& parameters) {
if (!jsonRead(parameters, F("multiply"), _multiply, false)) _multiply = 1;
if (!jsonRead(parameters, F("plus"), _plus, false)) _plus = 0;
if (!jsonRead(parameters, F("round"), _round, false)) _round = -1;
if (!jsonRead(parameters, F("numDigits"), _numDigits, false)) _numDigits = 1;
if (!jsonRead(parameters, F("global"), _global, false)) _global = false;
@@ -119,9 +120,9 @@ String IoTItem::getRoundValue() {
if (_round >= 0 && _round <= 6) {
int sot = _round ? pow(10, (int)_round) : 1;
value.valD = round(value.valD * sot) / sot;
//todo: оптимизировать. Вынести расчет строки формата округления, чтоб использовать постоянно готовую
char buf[15];
sprintf(buf, ("%1." + (String)_round + "f").c_str(), value.valD);
sprintf(buf, ("%0" + (String)(_numDigits + _round) + "." + (String)_round + "f").c_str(), value.valD);
value.valS = (String)buf;
return value.valS;
} else {

View File

@@ -1,22 +1,14 @@
#include "Global.h"
#include "classes/IoTItem.h"
//#include "LiquidCrystal_I2C.h"
#include <RobotClass_LiquidCrystal_I2C.h>
#include <map>
void scanI2C();
//LiquidCrystal_I2C *LCDI2C;
RobotClass_LiquidCrystal_I2C *LCDI2C;
class Lcd2004 : public IoTItem {
private:
unsigned int _x;
unsigned int _y;
String _id2show;
String _descr;
String _id2show, _prefix = "", _postfix = "";
int _prevStrSize;
String _addr;
@@ -37,42 +29,52 @@ class Lcd2004 : public IoTItem {
int w = selectFromMarkerToMarker(size, ",", 0).toInt(); //количество столбцов
int h = selectFromMarkerToMarker(size, ",", 1).toInt(); //количество строк
if (LCDI2C == nullptr) { //инициализации экрана еще не было
//LCDI2C = new LiquidCrystal_I2C(hexStringToUint8(_addr), w, h);
LCDI2C = new RobotClass_LiquidCrystal_I2C(hexStringToUint8(_addr), w, h, CP_UTF8);
if (LCDI2C != nullptr) {
LCDI2C->init();
LCDI2C->clear();
LCDI2C->backlight();
}
}
LCDI2C->clear();
LCDI2C->backlight();
jsonRead(parameters, "coord", xy);
_x = selectFromMarkerToMarker(xy, ",", 0).toInt();
_y = selectFromMarkerToMarker(xy, ",", 1).toInt();
jsonRead(parameters, "descr", _descr);
jsonRead(parameters, "id2show", _id2show);
jsonRead(parameters, "prefix", _prefix);
jsonRead(parameters, "postfix", _postfix);
}
void doByInterval() {
if (LCDI2C != nullptr) {
printBlankStr(_prevStrSize);
String tmpStr = getItemValue(_id2show);
if (_descr != "none") tmpStr = _descr + " " + tmpStr;
LCDI2C->setCursor(_x, _y);
LCDI2C->print(tmpStr);
//LCDI2C->print("Helloy,Manager 404 !");
//Serial.printf("ffff %s\n", _id2show);
_prevStrSize = tmpStr.length();
} else {
scanI2C();
void drawItem(IoTItem* item) {
String tmpStr = _prefix;
tmpStr += item->getValue();
tmpStr += _postfix;
printBlankStr(_prevStrSize);
LCDI2C->setCursor(_x, _y);
LCDI2C->print(tmpStr);
_prevStrSize = tmpStr.length();
}
void setValue(const IoTValue& Value, bool genEvent = true) {
if (LCDI2C == nullptr) return;
value = Value;
drawItem(this);
IoTItem::setValue(Value, genEvent);
}
void onRegEvent(IoTItem* eventItem) {
if (LCDI2C == nullptr) { scanI2C(); return;}
if (!eventItem || _id2show == "") return;
if (_id2show == eventItem->getID()) {
setValue(eventItem->value, false);
}
}
IoTValue execute(String command, std::vector<IoTValue> &param) { // будет возможным использовать, когда сценарии запустятся
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "noBacklight")
LCDI2C->noBacklight();
else if (command == "backlight")
@@ -99,9 +101,13 @@ class Lcd2004 : public IoTItem {
if (param.size()) {
_y = param[0].valD;
}
} else if (command == "descr") {
} else if (command == "prefix") {
if (param.size()) {
_descr = param[0].valS;
_prefix = param[0].valS;
}
} else if (command == "postfix") {
if (param.size()) {
_postfix = param[0].valS;
}
} else if (command == "id2show") {
if (param.size()) {

View File

@@ -7,30 +7,32 @@
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"widget": "inputTxt",
"page": "Экраны",
"descr": "LCD Экран",
"int": 15,
"addr": "0x27",
"size": "20,4",
"coord": "0,0",
"id2show": "id датчика"
"id2show": "",
"prefix": "",
"postfix": ""
},
{
"name": "LCD экран 1602",
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"widget": "inputTxt",
"page": "Экраны",
"descr": "LCD Экран",
"int": 15,
"addr": "0x27",
"size": "16,2",
"coord": "0,0",
"id2show": "id датчика"
"id2show": "",
"prefix": "",
"postfix": ""
}],
"about": {
@@ -46,11 +48,12 @@
},
"moduleDesc": "Позволяет выводить на символьные экраны по указанным позициям значения других элементов конфигурации.",
"propInfo": {
"int": "Период времени в секундах обновления информации на экране по конкретному элементу.",
"addr": "Адрес устройства на шине, обычно 0x27.",
"addr": "Адрес устройства на шине, обычно 0x27. Установите пустую строку для включения режима сканирования адресов на шине (результат в консоли).",
"size": "Размерность матрицы экрана.",
"coord": "Координата позиции для вывода данных элемента конфигурации.",
"id2show": "id элемента конфигурации."
"id2show": "id элемента конфигурации для отображения на экране. Если пустое значение, то данные берутся из собственной переменной.",
"prefix": "Символы до значения.",
"postfix": "Символы после значения."
},
"funcInfo": [
{
@@ -89,10 +92,15 @@
"params": ["Номер столбца первого символа"]
},
{
"name": "descr",
"name": "prefix",
"descr": "Задает приставку слева от значения",
"params": ["Строка"]
},
{
"name": "postfix",
"descr": "Задает приставку справа от значения",
"params": ["Строка"]
},
{
"name": "id2show",
"descr": "Задает ИД элемента, значение которого хотим отображать на экране",

View File

@@ -0,0 +1,150 @@
#include "Modbus_master_for_Smi2_m.h"
Smi_display::Smi_display() {
}
// Modbus Master
void Smi_display::modbus_update() {
idle();
}
void Smi_display::idle() {
static unsigned int packet_index;
unsigned int failed_connections = 0;
unsigned char current_connection;
do {
if (packet_index == total_no_of_packets) // wrap around to the beginning
packet_index = 0;
// proceed to the next packet
packet = &packetArray[packet_index];
// get the current connection status
current_connection = packet->connection;
if (!current_connection) {
// If all the connection attributes are false return
// immediately to the main sketch
if (++failed_connections == total_no_of_packets)
return;
}
packet_index++;
// if a packet has no connection get the next one
} while (!current_connection);
constructPacket();
}
void Smi_display::constructPacket() {
packet->requests++;
frame[0] = packet->id;
frame[1] = packet->function;
frame[2] = packet->address >> 8; // address Hi
frame[3] = packet->address & 0xFF; // address Lo
frame[4] = packet->data >> 8; // MSB
frame[5] = packet->data & 0xFF; // LSB
unsigned char frameSize;
// construct the frame according to the modbus function
if (packet->function == PRESET_MULTIPLE_REGISTERS)
frameSize = construct_F16();
else // else functions 1,2,3,4,5 & 6 is assumed. They all share the exact same request format.
frameSize = 8; // the request is always 8 bytes in size for the above mentioned functions.
unsigned int crc16 = calculateCRC(frameSize - 2);
frame[frameSize - 2] = crc16 >> 8; // split crc into 2 bytes
frame[frameSize - 1] = crc16 & 0xFF;
sendPacket(frameSize);
}
unsigned char Smi_display::construct_F16() {
unsigned char no_of_bytes = packet->data * 2;
// first 6 bytes of the array + no_of_bytes + 2 bytes CRC
frame[6] = no_of_bytes; // number of bytes
unsigned char index = 7; // user data starts at index 7
unsigned char no_of_registers = packet->data;
/*unsigned*/ int temp;
for (unsigned char i = 0; i < no_of_registers; i++) {
temp = register_array[packet->local_start_address + i]; // get the data
frame[index] = temp >> 8;
index++;
frame[index] = temp & 0xFF;
index++;
}
unsigned char frameSize = (9 + no_of_bytes); // first 7 bytes of the array + 2 bytes CRC + noOfBytes
return frameSize;
}
void Smi_display::modbus_configure(HardwareSerial* SerialPort,
long baud,
unsigned char byteFormat,
int rx,
int tx,
unsigned int _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets,
/*unsigned*/ int* _register_array) {
TxEnablePin = _TxEnablePin;
total_no_of_packets = _total_no_of_packets;
packetArray = _packets;
register_array = _register_array;
ModbusPort = SerialPort;
(*ModbusPort).begin(baud, byteFormat, rx, tx);
pinMode(TxEnablePin, OUTPUT);
digitalWrite(TxEnablePin, LOW);
}
void Smi_display::modbus_construct(Packet* _packet,
unsigned char id,
unsigned char function,
unsigned int address,
unsigned int data,
unsigned int local_start_address) {
_packet->id = id;
_packet->function = function;
_packet->address = address;
_packet->data = data;
_packet->local_start_address = local_start_address;
_packet->connection = 1;
}
unsigned int Smi_display::calculateCRC(unsigned char bufferSize) {
unsigned int temp, temp2, flag;
temp = 0xFFFF;
for (unsigned char i = 0; i < bufferSize; i++) {
temp = temp ^ frame[i];
for (unsigned char j = 1; j <= 8; j++) {
flag = temp & 0x0001;
temp >>= 1;
if (flag)
temp ^= 0xA001;
}
}
// Reverse byte order.
temp2 = temp >> 8;
temp = (temp << 8) | temp2;
temp &= 0xFFFF;
// the returned value is already swapped
// crcLo byte is first & crcHi byte is last
return temp;
}
void Smi_display::sendPacket(unsigned char bufferSize) {
digitalWrite(TxEnablePin, HIGH);
for (unsigned char i = 0; i < bufferSize; i++)
(*ModbusPort).write(frame[i]);
(*ModbusPort).flush();
digitalWrite(TxEnablePin, LOW);
}

View File

@@ -0,0 +1,71 @@
#pragma once
#include "HardwareSerial.h"
#define PRESET_MULTIPLE_REGISTERS 16
#define BUFFER_SIZE 64
typedef struct
{
unsigned char id;
unsigned char function;
unsigned int address;
unsigned int data;
unsigned int local_start_address;
unsigned int requests;
unsigned int successful_requests;
unsigned int failed_requests;
unsigned int exception_errors;
unsigned int retries;
unsigned char connection;
} Packet;
class Smi_display {
public:
Smi_display();
~Smi_display();
public:
void modbus_update();
void modbus_construct(Packet* _packet,
unsigned char id,
unsigned char function,
unsigned int address,
unsigned int data,
unsigned _local_start_address);
void modbus_configure(HardwareSerial* SerialPort,
long baud,
unsigned char byteFormat,
int rx,
int tx,
unsigned int _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets,
/*unsigned*/ int* _register_array);
private:
void idle();
void constructPacket();
unsigned char construct_F16();
unsigned int calculateCRC(unsigned char bufferSize);
void sendPacket(unsigned char bufferSize);
private:
unsigned char state;
unsigned char retry_count;
unsigned int TxEnablePin;
unsigned char frame[BUFFER_SIZE];
unsigned char buffer;
unsigned int T1_5;
unsigned int frameDelay;
unsigned int total_no_of_packets;
Packet* packetArray;
Packet* packet;
/*unsigned*/ int* register_array;
HardwareSerial* ModbusPort;
};

View File

@@ -0,0 +1,71 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include "Modbus_master_for_Smi2_m.h"
// Общая сумма доступной памяти на ведущем устройстве, чтобы хранить данные
#define TOTAL_NO_OF_REGISTERS 4
// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum {
PACKET1,
TOTAL_NO_OF_PACKETS // leave this last entry
};
// Масив пакетов модбус
Packet packets[TOTAL_NO_OF_PACKETS];
// Массив хранения содержимого принятых и передающихся регистров
/*unsigned*/ int regs[TOTAL_NO_OF_REGISTERS];
class Smi2_m : public IoTItem {
private:
Smi_display* smi;
unsigned int _pin; // номер порта, управляющий передачей по RS-485
long int _baud; // скорость обмена, бит/с
int _rx, _tx; // номера ножек мк, к которым подключен UART
String _show;
int i = 10;
public:
public:
Smi2_m(String parameters) : IoTItem(parameters) {
smi = new Smi_display();
_pin = jsonReadInt(parameters, "pin");
_baud = jsonReadLInt(parameters, "baud");
_rx = jsonReadInt(parameters, "rx");
_tx = jsonReadInt(parameters, "tx");
// Настраиваем пакеты
// Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет
// помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив reg
// Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
// Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
smi->modbus_construct(&packets[PACKET1], 1, PRESET_MULTIPLE_REGISTERS, 4200, 1, 0);
smi->modbus_configure(&Serial, _baud, SERIAL_8N1, _rx, _tx, _pin, packets, TOTAL_NO_OF_PACKETS, regs);
jsonRead(parameters, "id2show", _show);
}
void doByInterval() {
if (smi) {
smi->modbus_update();
float tmpStr = getItemValue(_show).toFloat();
regs[0] = tmpStr * 10;
}
}
~Smi2_m(){};
};
void* getAPI_Smi2_m(String subtype, String param) {
if (subtype == F("Smi2_m")) {
return new Smi2_m(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,56 @@
{
"menuSection": "Экраны",
"configItem": [
{
"global": 0,
"name": "Smi2_m",
"type": "Writing",
"subtype": "Smi2_m",
"id": "Smi",
"widget": "",
"page": "Дисплеи",
"descr": "",
"int": 2,
"pin": 4,
"id2show": "id датчика",
"baud": "9600",
"rx": "16",
"tx": "17"
}
],
"about": {
"moduleName": "Smi2_m",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"moduleDesc": "Позволяет вывести индикацию на семисегментный индикатор по Modbus (Работает в Slave режиме, Read Holding Registers 0х03)",
"propInfo": {
"int": "Период времени в секундах обновления информации на экране по конкретному элементу.",
"pin": "номер порта, управляющий передачей по RS-485",
"id2show": "id элемента конфигурации.",
"baud": "скорость обмена, бит/с"
},
"funcInfo": [
{
"name": "descr",
"descr": "Задает приставку слева от значения",
"params": [
"Строка"
]
},
{
"name": "id2show",
"descr": "Задает ИД элемента, значение которого хотим отображать на экране",
"params": [
"Имя элемента конфигурации"
]
}
]
},
"defActive": true,
"usedLibs": {
"esp32_4mb": []
}
}

View File

@@ -0,0 +1,86 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <TM1637.h>
#include <TM1638.h>
#include <TM16xxDisplay.h>
class TM16XX : public IoTItem {
private:
TM16xxDisplay *_display = nullptr;
TM16xx *_module = nullptr;
std::vector<String> _ids2show;
public:
TM16XX(String parameters) : IoTItem(parameters) {
//jsonRead(parameters, "id2show", _id2show);
int DIO, CLK, STB, chip, numDigits, intensity;
bool onoff;
String id2show;
jsonRead(parameters, "DIO", DIO);
jsonRead(parameters, "CLK", CLK);
jsonRead(parameters, "STB", STB);
jsonRead(parameters, "chip", chip);
jsonRead(parameters, "numDigits", numDigits);
jsonRead(parameters, "intensity", intensity);
jsonRead(parameters, "on", onoff);
jsonRead(parameters, "id2show", id2show);
if (id2show != "") _ids2show = splitStr(id2show, ",");
if (chip == 1637) {
_module = new TM1637(DIO, CLK, numDigits);
} else if (chip == 1638) {
_module = new TM1638(DIO, CLK, STB, numDigits);
}
_module->setupDisplay(onoff, intensity);
_display = new TM16xxDisplay(_module, numDigits);
}
void doByInterval() {
}
void setValue(const IoTValue& Value, bool genEvent = true) {
if (_display == nullptr) return;
value = Value;
_display->println(getValue());
IoTItem::setValue(Value, genEvent);
}
void onRegEvent(IoTItem* eventItem) {
if (_display == nullptr) return;
if (!eventItem || _ids2show.size() == 0) return;
if (strInVector(eventItem->getID(), _ids2show)) {
if (_ids2show.size() == 1) {
_display->println(eventItem->getValue());
} else {
_display->println();
for (int i = 0; i < _ids2show.size(); i++) {
IoTItem* item = findIoTItem(_ids2show[i]);
if (item) {
_display->print(item->getValue());
}
}
}
}
}
~TM16XX() {
delete _display;
delete _module;
};
};
void *getAPI_TM16XX(String subtype, String param) {
if (subtype == F("TM16XX")) {
return new TM16XX(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,133 @@
{
"menuSection": "Экраны",
"configItem": [{
"global": 0,
"name": "7 сегментный дисплей TM16XX",
"type": "Writing",
"subtype": "TM16XX",
"id": "tm",
"widget": "inputTxt",
"page": "Экраны",
"descr": "Экран",
"round": 0,
"chip": 1637,
"numDigits": 4,
"DIO": "13",
"CLK": "14",
"STB": "12",
"intensity": "5",
"on": "1",
"id2show": ""
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "TM16XX",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"moduleDesc": "Позволяет выводить на 7 сегментный экран серии TM16XX (TM1637, TM1638). Может быть расширен до поддержки TM1616, TM1620, TM1628, TM1630, TM1637, TM1638, TM1640, TM1650, TM1652 и TM1668",
"propInfo": {
"int": "Период времени в секундах обновления информации на экране по конкретному элементу.",
"chip": "Номер чипа TM1637 или TM1638",
"numDigits": "Число цифр на дисплее",
"DIO": "Номер пина данных",
"CLK": "Номер пина часового сигнала",
"intensity": "Яркость 0-7",
"on": "Вкл/выкл при старте 1/0",
"STB": "Номер пина стекового сигнала - не используется на определенных моделях",
"id2show": "id элемента конфигурации для отображения. Если пустая строка, то дисплей использует свою переменную. Если указать несколько значений через запятую, то все данные будут последовательно выводиться в строку."
},
"funcInfo": [
{
"name": "noBacklight",
"descr": "Выключить подсветку",
"params": []
},
{
"name": "backlight",
"descr": "Включить подсветку",
"params": []
},
{
"name": "noDisplay",
"descr": "Спрятать все данные",
"params": []
},
{
"name": "display",
"descr": "Показать данные на экране",
"params": []
},
{
"name": "toggle",
"descr": "Переключает видимость значений на экране",
"params": []
},
{
"name": "x",
"descr": "Устанавливает первую координату",
"params": ["Номер строки первого символа"]
},
{
"name": "y",
"descr": "Устанавливает вторую координату",
"params": ["Номер столбца первого символа"]
},
{
"name": "descr",
"descr": "Задает приставку слева от значения",
"params": ["Строка"]
},
{
"name": "id2show",
"descr": "Задает ИД элемента, значение которого хотим отображать на экране",
"params": ["Имя элемента конфигурации"]
}
]
},
"defActive": true,
"usedLibs": {
"esp32_4mb": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8266_4mb": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8266_1mb": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8266_1mb_ota": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8285_1mb": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8285_1mb_ota": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8266_2mb": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
],
"esp8266_2mb_ota": [
"https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5"
]
}
}

View File

@@ -0,0 +1,97 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <SimpleFTPServer.h>
#define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_LITTLEFS
class FTPModule : public IoTItem
{
private:
String login;
String pass;
FtpServer ftpSrv; // set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
public:
FTPModule(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("login"), login);
jsonRead(parameters, F("pass"), pass);
ftpSrv.setCallback(FTPModule::_callback);
ftpSrv.setTransferCallback(FTPModule::_transferCallback);
ftpSrv.begin(login.c_str(), pass.c_str(), "Welcome IoTManager FTP server"); // username, password for ftp. (default 21, 50009 for PASV)
SerialPrint("I", "FtpServer " + (String)_id, "begin");
}
void loop()
{
ftpSrv.handleFTP();
}
static void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace)
{
switch (ftpOperation)
{
case FTP_CONNECT:
SerialPrint("i", "FTP", F("Connected!"));
break;
case FTP_DISCONNECT:
SerialPrint("i", "FTP", F("Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
SerialPrint("i", "FTP", "Free space change, free " + (String)freeSpace + " of " + (String)totalSpace);
break;
default:
break;
}
}
static void _transferCallback(FtpTransferOperation ftpOperation, const char *name, unsigned int transferredSize)
{
switch (ftpOperation)
{
case FTP_UPLOAD_START:
SerialPrint("i","FTP", F("Upload start!"));
break;
case FTP_UPLOAD:
SerialPrint("i","FTP", "Upload of file " + (String)name + " byte " + (String)transferredSize);
break;
case FTP_TRANSFER_STOP:
SerialPrint("i","FTP", F("Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
SerialPrint("E","FTP", F("Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
}
~FTPModule(){};
};
void *getAPI_FTPModule(String subtype, String param)
{
if (subtype == F("ftp"))
{
return new FTPModule(param);
}
//}
return nullptr;
}

View File

@@ -0,0 +1,46 @@
{
"menuSection": "Исполнительные устройства",
"configItem": [
{
"global": 0,
"name": "FTP сервер",
"type": "Reading",
"subtype": "ftp",
"id": "ftp",
"widget": "nil",
"page": "",
"descr": "FTP сервер",
"login": "admin",
"pass": "admin"
}
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"specialThanks": "",
"moduleName": "FTPModule",
"moduleVersion": "0.1",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "FTP-сервер",
"moduleDesc": "Запускает FTP-сервер на плате esp",
"propInfo": {
"login": "Логин FTP сервера",
"pass": "Пароль FTP сервера"
}
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": []
}
}

View File

@@ -49,6 +49,7 @@
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -56,6 +56,7 @@
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -15,7 +15,7 @@
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mitchel",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",

View File

@@ -21,7 +21,7 @@
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mitchel",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",
@@ -41,6 +41,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -0,0 +1,178 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <DS2423.h>
#include <OneWire.h>
#include <map>
typedef uint8_t DeviceAddressDS2423[8];
// глобальные списки необходимы для хранения объектов об активных линиях 1-wire используемых разными датчиками из модуля. Ключ - номер пина
std::map<int, OneWire *> oneWireDS2423Array;
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
OneWire *instanceOneWire_DS2423(uint8_t ONE_WIRE_PIN)
{
// учитываем, что библиотека может работать с несколькими линиями на разных пинах, поэтому инициируем библиотеку, если линия ранее не использовалась
if (oneWireDS2423Array.find(ONE_WIRE_PIN) == oneWireDS2423Array.end())
oneWireDS2423Array[ONE_WIRE_PIN] = new OneWire((uint8_t)ONE_WIRE_PIN);
return oneWireDS2423Array[ONE_WIRE_PIN];
}
// Определяем адрес.
bool getDeviceAddressDS2423(uint8_t pin, uint8_t *deviceAddress, int index)
{
OneWire *_wire = instanceOneWire_DS2423(pin);
uint8_t depth = 0;
_wire->reset_search();
while (depth <= index && _wire->search(deviceAddress))
{
if (depth == index && _wire->crc8((uint8_t *)deviceAddress, 7) == deviceAddress[7])
return true;
depth++;
}
return false;
}
class Ds2423a : public IoTItem
{
private:
// описание параметров передаваемых из настроек датчика из веба
String _addr;
int _pin;
int _index;
DS2423 *ds2423;
DeviceAddressDS2423 _deviceAddress;
public:
Ds2423a(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, "pin", _pin);
jsonRead(parameters, "index", _index, false);
jsonRead(parameters, "addr", _addr, false);
// Определяем адрес. Если параметр addr не установлен, то узнаем адрес по индексу
if (_addr == "")
{
if (getDeviceAddressDS2423(_pin, _deviceAddress, _index))
{
char addrStr[20] = "";
hex2string(_deviceAddress, 8, addrStr);
SerialPrint("I", "Sensor " + (String)_id, "index: " + (String)_index + " addr: " + String(addrStr));
}
else
{
SerialPrint("E", "Sensor " + (String)_id, "index: " + (String)_index + " addres not search");
}
}
else
{
string2hex(_addr.c_str(), _deviceAddress);
}
ds2423 = new DS2423(instanceOneWire_DS2423(_pin), _deviceAddress);
ds2423->begin(DS2423_COUNTER_A | DS2423_COUNTER_B);
}
void doByInterval()
{
ds2423->update();
if (ds2423->isError())
{
Serial.println("Error reading counter");
}
else
{
value.valD = ds2423->getCount(DS2423_COUNTER_A);
// if (value.valD != -127)
regEvent(value.valD, "Ds2423a"); // обязательный вызов для отправки результата работы
// else
// SerialPrint("E", "Sensor Ds2423a", "Error");
}
}
//=======================================================================================================
~Ds2423a(){};
};
class Ds2423b : public IoTItem
{
private:
// описание параметров передаваемых из настроек датчика из веба
String _addr;
int _pin;
int _index;
DS2423 *ds2423;
DeviceAddressDS2423 _deviceAddress;
public:
Ds2423b(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, "pin", _pin);
jsonRead(parameters, "index", _index, false);
jsonRead(parameters, "addr", _addr, false);
// Определяем адрес. Если параметр addr не установлен, то узнаем адрес по индексу
if (_addr == "")
{
if (getDeviceAddressDS2423(_pin, _deviceAddress, _index))
{
char addrStr[20] = "";
hex2string(_deviceAddress, 8, addrStr);
SerialPrint("I", "Sensor " + (String)_id, "index: " + (String)_index + " addr: " + String(addrStr));
}
else
{
SerialPrint("E", "Sensor " + (String)_id, "index: " + (String)_index + " addres not search");
}
}
else
{
string2hex(_addr.c_str(), _deviceAddress);
}
ds2423 = new DS2423(instanceOneWire_DS2423(_pin), _deviceAddress);
ds2423->begin(DS2423_COUNTER_A | DS2423_COUNTER_B);
}
void doByInterval()
{
ds2423->update();
if (ds2423->isError())
{
Serial.println("Error reading counter");
}
else
{
// запускаем опрос измерений у всех датчиков на линии
value.valD = ds2423->getCount(DS2423_COUNTER_B);
// if (value.valD != -127)
regEvent(value.valD, "Ds2423b"); // обязательный вызов для отправки результата работы
// else
// SerialPrint("E", "Sensor Ds2423b", "Error");
}
}
//=======================================================================================================
~Ds2423b(){};
};
void *getAPI_Ds2423(String subtype, String param)
{
if (subtype == F("Ds2423a"))
{
return new Ds2423a(param);
}
else if (subtype == F("Ds2423b"))
{
return new Ds2423b(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,72 @@
{
"menuSection": "Сенсоры",
"configItem": [
{
"global": 0,
"name": "DS2423 счетчик 1",
"type": "Reading",
"subtype": "Ds2423a",
"id": "dscounta",
"widget": "anydataDef",
"page": "Счетчики",
"descr": "DS1 V",
"plus": 0,
"multiply": 1,
"pin": 4,
"index": 0,
"addr": "",
"int": 10,
"round": 0,
"needSave": 0
},
{
"global": 0,
"name": "DS2423 счетчик 2",
"type": "Reading",
"subtype": "Ds2423b",
"id": "dscountb",
"widget": "anydataDef",
"page": "Счетчики",
"descr": "DS2 V",
"plus": 0,
"multiply": 1,
"pin": 4,
"index": 0,
"addr": "",
"int": 10,
"round": 0,
"needSave": 0
}
],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Bubnov Mikhail @Mit4bmw",
"moduleName": "Ds2423",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "Cчетчик ds2423",
"moduleDesc": "Позволяет получить значения с Ds2423.",
"propInfo": {
"pin": "GPIO номер, к которому подключена шина данных датчиков.",
"index": "Порядковый номер датчика на шине.",
"addr": "Адрес датчика на шине для точной идентификации. Если оставить пустым, то попробует найти по индексу и пину и Можно скопировать из консоли.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"https://github.com/jbechter/arduino-onewire-DS2423",
"paulstoffregen/OneWire @ ^2.3.7"
],
"esp8266_4mb": [
"https://github.com/jbechter/arduino-onewire-DS2423",
"paulstoffregen/OneWire @ ^2.3.7"
]
}
}

View File

@@ -11,126 +11,198 @@
#include <Wire.h>
#include <Adafruit_INA219.h>
#include <map>
Adafruit_INA219 ina219;
// Adafruit_INA219 ina219;
// Структура для хранения данных с датчика
struct Ina219Value
{
float shuntvoltage = 0;
float busvoltage = 0;
};
// глобальные списки необходимы для хранения данных, полученных разными датчиками из модуля. Ключ - адрес
std::map<uint8_t, Ina219Value *> ina219ValueArray;
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
// глобальные списки необходимы для хранения объектов используемых разными датчиками из модуля. Ключ - адрес
std::map<uint8_t, Adafruit_INA219 *> ina219Array;
// shuntvoltage = ina219.getShuntVoltage_mV(); // Получение напряжение на шунте
// busvoltage = ina219.getBusVoltage_V(); // Получение значение напряжения V
// current_mA = ina219.getCurrent_mA(); // Получение значение тока в мА
// power_mW = ina219.getPower_mW(); // Получение значение мощности
// loadvoltage = busvoltage + (shuntvoltage / 1000); // Расчет напряжение на нагрузки
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
Adafruit_INA219 *instanceIna219(uint8_t ADDR)
{
/** default I2C address **/
if (ADDR == 0)
ADDR = INA219_ADDRESS; // 1000000 (A0+A1=GND)
class Ina219loadvoltage : public IoTItem {
public:
Ina219loadvoltage(String parameters) : IoTItem(parameters) {
// учитываем, что библиотека может работать с несколькими линиями на разных пинах, поэтому инициируем библиотеку, если линия ранее не использовалась
if (ina219Array.find(ADDR) == ina219Array.end())
{
ina219Array[ADDR] = new Adafruit_INA219((uint8_t)ADDR);
ina219Array[ADDR]->begin();
ina219ValueArray[ADDR] = new Ina219Value;
}
return ina219Array[ADDR];
}
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
/*
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
*/
// shuntvoltage = ina219.getShuntVoltage_mV(); // Получение напряжение на шунте
// busvoltage = ina219.getBusVoltage_V(); // Получение значение напряжения V
// current_mA = ina219.getCurrent_mA(); // Получение значение тока в мА
// power_mW = ina219.getPower_mW(); // Получение значение мощности
// loadvoltage = busvoltage + (shuntvoltage / 1000); // Расчет напряжение на нагрузки
class Ina219loadvoltage : public IoTItem
{
private:
uint8_t _addr = 0;
public:
Ina219loadvoltage(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
loadvoltage = busvoltage + (shuntvoltage / 1000);
value.valD = loadvoltage;
regEvent(value.valD, "Ina219loadvoltage");
void doByInterval()
{
value.valD = ina219ValueArray[_addr]->busvoltage + (ina219ValueArray[_addr]->shuntvoltage / 1000);
regEvent(value.valD, "Ina219loadvoltage");
}
~Ina219loadvoltage(){};
};
class Ina219busvoltage : public IoTItem {
public:
Ina219busvoltage(String parameters) : IoTItem(parameters) {
class Ina219busvoltage : public IoTItem
{
private:
uint8_t _addr = 0;
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
public:
Ina219busvoltage(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
busvoltage = ina219.getBusVoltage_V();
value.valD = busvoltage;
regEvent(value.valD, "Ina219busvoltage");
void doByInterval()
{
ina219ValueArray[_addr]->busvoltage = instanceIna219(_addr)->getBusVoltage_V();
value.valD = ina219ValueArray[_addr]->busvoltage;
regEvent(value.valD, "Ina219busvoltage");
}
~Ina219busvoltage(){};
};
class Ina219shuntvoltage : public IoTItem
{
private:
uint8_t _addr = 0;
class Ina219curr : public IoTItem {
public:
Ina219curr(String parameters) : IoTItem(parameters) {
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
public:
Ina219shuntvoltage(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
current_mA = ina219.getCurrent_mA();
value.valD = current_mA;
regEvent(value.valD, "Ina219curr");
}
~Ina219curr(){};
};
class Ina219shuntvoltage : public IoTItem {
public:
Ina219shuntvoltage(String parameters) : IoTItem(parameters) {
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
}
void doByInterval() {
shuntvoltage = ina219.getShuntVoltage_mV();
value.valD = shuntvoltage;
regEvent(value.valD, "Ina219shuntvoltage");
void doByInterval()
{
ina219ValueArray[_addr]->shuntvoltage = instanceIna219(_addr)->getShuntVoltage_mV();
value.valD = ina219ValueArray[_addr]->shuntvoltage;
regEvent(value.valD, "Ina219shuntvoltage");
}
~Ina219shuntvoltage(){};
};
class Power_mW : public IoTItem {
public:
Power_mW(String parameters) : IoTItem(parameters) {
class Ina219curr : public IoTItem
{
private:
uint8_t _addr = 0;
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
public:
Ina219curr(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
power_mW = ina219.getPower_mW();
value.valD = power_mW;
regEvent(value.valD, "Ina219power"); // TODO: найти способ понимания ошибки получения данных
void doByInterval()
{
value.valD = instanceIna219(_addr)->getCurrent_mA();
regEvent(value.valD, "Ina219curr");
}
~Power_mW(){};
~Ina219curr(){};
};
void* getAPI_Ina219(String subtype, String param) {
if (subtype == F("Ina219curr")) {
ina219.begin();
class Ina219Power_mW : public IoTItem
{
private:
uint8_t _addr = 0;
public:
Ina219Power_mW(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval()
{
value.valD = instanceIna219(_addr)->getPower_mW();
regEvent(value.valD, "Ina219power"); // TODO: найти способ понимания ошибки получения данных
}
~Ina219Power_mW(){};
};
void *getAPI_Ina219(String subtype, String param)
{
if (subtype == F("Ina219curr"))
{
return new Ina219curr(param);
} else if (subtype == F("Ina219shuntvoltage")) {
ina219.begin();
}
else if (subtype == F("Ina219shuntvoltage"))
{
return new Ina219shuntvoltage(param);
} else if (subtype == F("power_mW")) {
ina219.begin();
return new Power_mW(param);
} else if (subtype == F("Ina219busvoltage")) {
ina219.begin();
}
else if (subtype == F("Ina219power_mW"))
{
return new Ina219Power_mW(param);
}
else if (subtype == F("Ina219busvoltage"))
{
return new Ina219busvoltage(param);
} else if (subtype == F("Ina219loadvoltage")) {
ina219.begin();
}
else if (subtype == F("Ina219loadvoltage"))
{
return new Ina219loadvoltage(param);
} else {
return nullptr;
}
else
{
return nullptr;
}
}

View File

@@ -10,6 +10,10 @@
"widget": "anydatamAmp",
"page": "INA 219",
"descr": "219 Датчик тока",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
@@ -21,17 +25,25 @@
"widget": "anydataVlt",
"page": "INA 219",
"descr": "219 Датчик напряжения",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Мощность",
"type": "Reading",
"subtype": "power_mW",
"subtype": "Ina219power_mW",
"id": "Ina219power",
"widget": "anydatamWtt",
"widget": "anydatamWt",
"page": "INA 219",
"descr": "219 Мощность",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
@@ -43,6 +55,10 @@
"widget": "anydataVlt",
"page": "INA 219",
"descr": "219 Напряжение нагрузки",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
@@ -54,6 +70,10 @@
"widget": "anydatamVlt",
"page": "INA 219",
"descr": "219 Напряжение шунта",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
}],
@@ -61,9 +81,9 @@
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Дмитрий , Serg",
"specialThanks": "Дмитрий, Serg, v2.0 - Mitchel @Mit4bmw",
"moduleName": "Ina219",
"moduleVersion": "1.0",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
@@ -71,14 +91,15 @@
"subTypes": [
"Ina219curr",
"Ina219busvoltage",
"power_mW",
"Ina219power_mW",
"Ina219loadvoltage",
"Ina219shuntvoltage"
],
"title": "Милливатметр постоянного тока",
"moduleDesc": "Измеряет постоянный ток до 3.2 ампера, напряжение до 26 вольт и мощность на нагрузке",
"moduleDesc": "Измеряет постоянный ток до 3.2 ампера, напряжение до 26 вольт и мощность на нагрузке. Для расчета Наряжения нагрузки, необходимы Напряжение шунта и Датчик Напряжения",
"propInfo": {
"int": "Количество секунд между опросами датчика."
"int": "Количество секунд между опросами датчика.",
"addr": "Адрес датчика на шине, обычно 0x40. Если оставить поле пустым, то запуститься сканер I2C и подключение к адресу 0x40"
}
},
@@ -88,6 +109,9 @@
"esp32_4mb": [
"https://github.com/adafruit/Adafruit_INA219.git"
],
"esp32s2_4mb": [
"https://github.com/adafruit/Adafruit_INA219.git"
],
"esp8266_4mb": [
"https://github.com/adafruit/Adafruit_INA219.git"

View File

@@ -78,6 +78,7 @@
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": ["plerup/EspSoftwareSerial"],
"esp8266_4mb": []
}
}

View File

@@ -0,0 +1,75 @@
/******************************************************************
Simple library for NTC thermistors
https://github.com/GyverLibs/GyverNTC
adapted for version 4 @Serghei63
******************************************************************/
#include "Global.h"
#include "classes/IoTItem.h"
class NTCt : public IoTItem {
private:
unsigned int _pin;
float R1 = 10000.0; // voltage divider resistor value
float Beta = 3950.0; // Beta value
float To = 25.; // Temperature Celsius
float Ro = 10000.0; // Resistance of Thermistor at 25 degree Celsius
float adcMax = 1023.0;
float Vs = 3.3;
public:
NTCt(String parameters): IoTItem(parameters) {
_pin = jsonReadInt(parameters, "pin");
R1 = jsonReadInt(parameters, "R1"); // voltage divider resistor value
Beta = jsonReadInt(parameters, "Beta"); // Beta value
To = jsonReadInt(parameters, "T0"); // Temperature degree Celsius
Ro = jsonReadInt(parameters, "R0"); // Resistance of Thermistor at 25 degree Celsius
Vs = jsonReadInt(parameters, "Vs"); // Resistance of Thermistor at 25 degree Celsius
To = To+273.15;
#if defined ESP8266
adcMax = 1023.0;
#elif defined ESP32
adcMax = 4095.0;
#endif
}
void doByInterval() {
float Vout, Rt = 0;
float T = 0;
float adc = 0;
for (int i = 0; i < 10; i++)
{
adc += IoTgpio.analogRead(_pin);
}
adc /= 10;
Vout = adc * Vs/adcMax;
Rt = R1 * Vout / (Vs - Vout);
T = 1/(1/To + log(Rt/Ro)/Beta); // Temperature in Kelvin
value.valD = T - 273.15; // Celsius
SerialPrint("i", F("Ntc"), "adc = " + String(adc)+ " ,Vout = " + String(Vout)+ " ,T = " + String(value.valD));
if (String(value.valD) != "nan") regEvent(value.valD, "Ntc");
else
SerialPrint("E", "Ntc", "Error");
}
~NTCt() {};
};
void* getAPI_Ntc(String subtype, String param) {
if (subtype == F("Ntc")) {
return new NTCt(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,65 @@
{
"menuSection": "Сенсоры",
"configItem": [
{
"global": 0,
"name": "Cенсор температуры NTC",
"type": "Reading",
"subtype": "Ntc",
"id": "Ntctmp",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "NTC Температура",
"needSave": 0,
"val": "0",
"int": 15,
"pin": "35",
"R1":"10000",
"R0":"10000",
"Beta":"3950.0",
"T0":"25",
"Vs":"3.3",
"round" : 1
}
],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "https://t.me/Mit4bmw",
"moduleName": "Ntc",
"moduleVersion": "1.1",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Ntc"
],
"title": "Модуль датчика Ntc",
"moduleDesc": "",
"retInfo": "",
"propInfo": {
"pin": "Аналоговый пин (для esp8266 = 0, для esp32 алаоговый gpio, например 35)",
"R1":"Сопротивление подтягивающего резистора, должен быть равен сопротивлению термистера",
"Vs":"Напряжение питания датчика, Для точности измерить и ввести своё, по умолчанию 3.3В",
"R0":"Сопротивление термистора при температуре То, например 10 КОм при 25С",
"T0":"Базовая температура, температура измерения сопротивление термистора (Rterm), обычно 25С",
"Beta":"Beta термистора"
}
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],
"esp8285_1mb": [],
"esp8285_1mb_ota": [],
"esp8266_2mb": [],
"esp8266_2mb_ota": []
}
}

View File

@@ -39,18 +39,18 @@ class RTC : public IoTItem {
return this;
}
ulong getRtcUnixTime() {
return _watch->gettimeUnix();
unsigned long getRtcUnixTime() {
return _watch->gettimeUnix() - jsonReadInt(settingsFlashJson, F("timezone")) * 60 * 60;
}
void onModuleOrder(String &key, String &value) {
if (key == "setUTime") {
char *stopstring;
ulong ut = strtoul(value.c_str(), &stopstring, 10);
unsigned long ut = strtoul(value.c_str(), &stopstring, 10);
_watch->settimeUnix(ut);
SerialPrint("i", F("RTC"), "Устанавливаем время: " + value);
} else if (key == "setSysTime") {
_watch->settimeUnix(unixTime);
_watch->settimeUnix(unixTime + jsonReadInt(settingsFlashJson, F("timezone")) * 60 * 60);
SerialPrint("i", F("RTC"), F("Запоминаем системное время"));
}
}

View File

@@ -0,0 +1,432 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <SensirionI2CScd4x.h>
#include <SensirionCore.h>
#include <Wire.h>
// SensirionI2CScd4x scd4x;
SensirionI2CScd4x *scd4x = nullptr; // create an object of the CSD40 class
char errorMessageScd4x[256];
uint16_t errorCodeScd4x;
void printUint16Hex(uint16_t value)
{
Serial.print(value < 4096 ? "0" : "");
Serial.print(value < 256 ? "0" : "");
Serial.print(value < 16 ? "0" : "");
Serial.print(value, HEX);
}
void printSerialNumber(uint16_t serial0, uint16_t serial1, uint16_t serial2)
{
Serial.print("Serial: 0x");
printUint16Hex(serial0);
printUint16Hex(serial1);
printUint16Hex(serial2);
Serial.println();
}
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
SensirionI2CScd4x *instanceScd4x()
{
if (!scd4x)
{ // Если библиотека ранее инициализировалась, т о просто вернем указатель
// Инициализируем библиотеку
scd4x = new SensirionI2CScd4x();
Wire.begin();
scd4x->begin(Wire);
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
//Запрашиваем и выводим серийный номер датчика
uint16_t serial0;
uint16_t serial1;
uint16_t serial2;
errorCodeScd4x = instanceScd4x()->getSerialNumber(serial0, serial1, serial2);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getSerialNumber(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
printSerialNumber(serial0, serial1, serial2);
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
return scd4x;
}
class Scd40co2 : public IoTItem
{
private:
bool lowPeriodic = true;
bool autoCalibration = true;
//int targetCo2 = 0;
public:
Scd40co2(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("lowPeriodic"), lowPeriodic);
jsonRead(parameters, F("autoCalibration"), autoCalibration);
// jsonRead(parameters, F("targetCo2"), targetCo2);
settingParameters();
}
void doByInterval()
{
// Read Measurement
uint16_t co2 = 0;
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
//Запрашиваем библиотеку о готовности отправить запрос
errorCodeScd4x = instanceScd4x()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
return;
}
if (!isDataReady)
{
return;
}
//Если все нормально забираем у библиотеки данные
errorCodeScd4x = instanceScd4x()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute readMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else if (co2 == 0)
{
Serial.println("Invalid sample detected, skipping.");
}
else
{
Serial.print("Co2:");
Serial.print(co2);
Serial.print("\t");
// Serial.print("Temperature:");
// Serial.print(temperature);
// Serial.print("\t");
// Serial.print("Humidity:");
// Serial.println(humidity);
}
// value.valD = scd4x.readMeasurement(temperature);
value.valD = co2;
if (value.valD < 5000)
regEvent(value.valD, "Scd40co2");
else
SerialPrint("E", "Sensor Scd40co2", "Error", _id);
}
//Хук для обработки кнопки
void onModuleOrder(String &key, String &value)
{
if (key == "Recalibration")//название кнопки btn-Recalibration
{
SerialPrint("i", F("Sensor Scd40co2"), "User run calibration, targetCo2: " + value);
Recalibration(value.toInt());
}
}
void Recalibration(int targetCo2)
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
delay(500); // Из описания performForcedRecalibration 2. Stop periodic measurement. Wait 500 ms.
uint16_t frcCorrection;
errorCodeScd4x = instanceScd4x()->performForcedRecalibration(targetCo2, frcCorrection);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute performForcedRecalibration(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("performForcedRecalibration(): OK!");
SerialPrint("i", F("Sensor Scd40co2"), "Calibration is OK, frcCorrection: " + String(frcCorrection));
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
void settingParameters()
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
errorCodeScd4x = instanceScd4x()->startLowPowerPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startLowPowerPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("startLowPowerPeriodicMeasurement(): OK!");
}
errorCodeScd4x = instanceScd4x()->setAutomaticSelfCalibration((uint16_t)autoCalibration);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute setAutomaticSelfCalibration(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("setAutomaticSelfCalibration(): OK!");
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
~Scd40co2(){};
};
class Scd40t : public IoTItem
{
private:
int offsetT;
public:
Scd40t(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("offset"), offsetT);
setTemperatureOffset();
}
void doByInterval()
{
// Read Measurement
uint16_t co2 = 0;
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
errorCodeScd4x = instanceScd4x()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
return;
}
if (!isDataReady)
{
return;
}
errorCodeScd4x = instanceScd4x()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("errorCodeScd4x trying to execute readMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else if (co2 == 0)
{
Serial.println("Invalid sample detected, skipping.");
}
else
{
// Serial.print("Co2:");
// Serial.print(co2);
// Serial.print("\t");
Serial.print("Temperature:");
Serial.print(temperature);
Serial.print("\t");
// Serial.print("Humidity:");
// Serial.println(humidity);
}
// value.valD = scd4x.readMeasurement(temperature);
value.valD = temperature;
if (value.valD < 124)
regEvent(value.valD, "Scd40t");
else
SerialPrint("E", "Sensor Scd40t", "Error", _id);
}
void setTemperatureOffset()
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
errorCodeScd4x = instanceScd4x()->setTemperatureOffset((uint16_t)offsetT);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute setTemperatureOffset(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("setTemperatureOffset(): OK!");
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
~Scd40t(){};
};
class Scd40h : public IoTItem
{
public:
Scd40h(String parameters) : IoTItem(parameters)
{
}
void doByInterval()
{
// Read Measurement
uint16_t co2 = 0;
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
errorCodeScd4x = instanceScd4x()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
return;
}
if (!isDataReady)
{
return;
}
errorCodeScd4x = instanceScd4x()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute readMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else if (co2 == 0)
{
Serial.println("Invalid sample detected, skipping.");
}
else
{
// Serial.print("Co2:");
// Serial.print(co2);
// Serial.print("\t");
// Serial.print("Temperature:");
// Serial.print(temperature);
// Serial.print("\t");
Serial.print("Humidity:");
Serial.println(humidity);
Serial.print("\t");
}
// value.valD = scd4x.readMeasurement(temperature);
value.valD = humidity;
if (value.valD < 100)
regEvent(value.valD, "Scd40h");
else
SerialPrint("E", "Sensor Scd40h", "Error", _id);
}
~Scd40h(){};
};
void *getAPI_Scd40(String subtype, String param)
{
if (subtype == F("Scd40co2"))
{
// hdc1080.begin(0x40);
// scd4x->begin(Wire);
// scd4x.begin(Wire);
return new Scd40co2(param);
}
else if (subtype == F("Scd40t"))
{
// hdc1080.begin(0x40);
// scd4x->begin(Wire);
return new Scd40t(param);
}
else if (subtype == F("Scd40h"))
{
// hdc1080.begin(0x40);
// scd4x->begin(Wire);
return new Scd40h(param);
// } else {
// return nullptr;
}
return nullptr;
}

View File

@@ -0,0 +1,84 @@
{
"menuSection": "Сенсоры",
"configItem": [
{
"global": 0,
"name": "SCD40 Углекислый газ",
"type": "Reading",
"subtype": "Scd40co2",
"id": "Scd40co2",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "SCD40 Углекислый газ",
"int": 15,
"round": 0,
"lowPeriodic": 1,
"autoCalibration": 1,
"btn-Recalibration": 0
},
{
"global": 0,
"name": "SCD40 Влажность",
"type": "Reading",
"subtype": "Scd40h",
"id": "Scd40h",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "SCD40 Влажность",
"int": 15,
"round": 1
},
{
"global": 0,
"name": "SCD40 Температура",
"type": "Reading",
"subtype": "Scd40t",
"id": "Scd40t",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "SCD40 Температура",
"int": 15,
"round": 1,
"offset": 4
}
],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Bubnov Mikhail @Mit4bmw",
"moduleName": "Scd40",
"moduleVersion": "0.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Scd40co2",
"Scd40t",
"Scd40h"
],
"title": "Датчик температуры и влажности Scd40",
"moduleDesc": "Позволяет получить значения температуры и влажности с Scd40.",
"propInfo": {
"int": "Количество секунд между опросами библиотеки (датчик опрашивается библиотекой по своему таймеру, см. lowPeriodic).",
"offset": "Смещение температуры представляет собой разницу между температурой, измеренной SCD4x, и фактической температурой окружающей среды температура. По умолчанию смещение температуры в библиотеке/датчике установлено на 4°C.",
"lowPeriodic": "Медленные режим опроса датчика библиотекой. 0-каждые 5сек, 1-каждые 30сек",
"autoCalibration": "Автоматическая калибровка, по умолчанию включена AutomaticSelfCalibration, 0 - выключена",
"btn-Recalibration": "Кнопка принудительной калибровки. В поле указать Целевая концентрация CO₂ в миллионных долях. Перед калибровкой необходимо находтся в течение > 3 минут в среде с однородной и постоянной концентрацией CO₂. Выдает в лог Значение коррекции FRC в co₂ ppm"
}
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"Sensirion I2C SCD4x @0.4.0",
"Sensirion Core @0.6.0"
],
"esp8266_4mb": [
"Sensirion I2C SCD4x @0.4.0",
"Sensirion Core @0.6.0"
]
}
}

View File

@@ -0,0 +1,432 @@
#include "Global.h"
#include "classes/IoTItem.h"
#define MONITOR_SERIAL Serial
#define RADAR_SERIAL Serial1
// #define RADAR_RX_PIN 32
// #define RADAR_TX_PIN 33
#include <ld2410.h>
// ld2410 radar;
ld2410 *radar = nullptr;
ld2410 *instanceradar(uint8_t _rx, uint8_t _tx)
{
if (!radar)
{ // Если библиотека ранее инициализировалась, т о просто вернем указатель
// Инициализируем библиотеку
radar = new ld2410();
// radar->begin(); // При необходимости делаем begin библиотеке
RADAR_SERIAL.begin(256000, SERIAL_8N1, _rx, _tx); // UART for monitoring the radar
if (radar->begin(RADAR_SERIAL))
{
SerialPrint("i", "LD2410", "Radar sensor подключен");
SerialPrint("i", "LD2410", "Connect LD2410 radar TX to GPIO: " + String(_rx));
SerialPrint("i", "LD2410", "Connect LD2410 radar RX to GPIO: " + String(_tx));
SerialPrint("i", "LD2410", "LD2410 firmware version: " + String(radar->firmware_major_version));
SerialPrint("i", "LD2410", "LD2410 firmware version: " + String(radar->firmware_minor_version));
SerialPrint("i", "LD2410", "LD2410 firmware version: " + String(radar->firmware_bugfix_version));
}
else
{
SerialPrint("i", "LD2410", "Radar sensor не подключен");
}
}
return radar;
}
int presence = 0;
int presence_last = 0;
int movement = 0;
int movement_last = 0;
int distance = 0;
int distance_last = 0;
int energy = 0;
int energy_last = 0;
int err = 0;
uint32_t lastReadingP = 0;
uint32_t lastReadingM = 0;
uint32_t lastReadingD = 0;
uint32_t lastReadingE = 0;
bool radarConnected = false;
// датчик присутствия
class ld2410m : public IoTItem
{
private:
int _ticker;
uint8_t _rx, _tx;
public:
//=======================================================================================================
// setup()
ld2410m(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, "ticker", _ticker);
String tmp;
jsonRead(parameters, "RX", tmp);
_rx = tmp.toInt();
jsonRead(parameters, "TX", tmp);
_tx = tmp.toInt();
}
void loop()
{
instanceradar(_rx, _tx)->read();
if (instanceradar(_rx, _tx)->isConnected() && millis() - lastReadingP > 1000) // Report every 1000ms
{
lastReadingP = millis();
err = 0;
presence = instanceradar(_rx, _tx)->presenceDetected();
if (instanceradar(_rx, _tx)->stationaryTargetDetected())
{
movement = 0;
distance = instanceradar(_rx, _tx)->stationaryTargetDistance();
energy = instanceradar(_rx, _tx)->stationaryTargetEnergy();
}
if (instanceradar(_rx, _tx)->movingTargetDetected())
{
movement = 1;
distance = instanceradar(_rx, _tx)->movingTargetDistance();
energy = instanceradar(_rx, _tx)->movingTargetEnergy();
}
if (presence != presence_last)
{
value.valD = int(presence);
regEvent(value.valD, "ld2410m");
presence_last = presence;
// SerialPrint("i", "LD2410", "присутствие: " + String(int(presence)));
}
if (presence && movement != movement_last)
{
value.valD = int(presence);
regEvent(value.valD, "ld2410m");
}
if (presence && _ticker)
{
value.valD = int(presence);
regEvent(value.valD, "ld2410m");
presence_last = presence;
}
}
if (!instanceradar(_rx, _tx)->isConnected())
{
if (err == 0)
{
// value.valD = "Err";
// regEvent(value.valD, "ld2410m");
// SerialPrint("E", "LD2410", "Radar sensor ошибка получения данных");
}
err = 1;
}
}
IoTValue execute(String command, std::vector<IoTValue> &param)
{
if (command == "setmaxvalues")
{
if (param[0].isDecimal && param[1].isDecimal && param[2].isDecimal)
{
uint8_t newMovingMaxDistance = param[0].valD;
uint8_t newStationaryMaxDistance = param[1].valD;
uint16_t inactivityTimer = param[2].valD;
if (newMovingMaxDistance > 0 && newStationaryMaxDistance > 0 && newMovingMaxDistance <= 8 && newStationaryMaxDistance <= 8)
{
if (instanceradar(_rx, _tx)->setMaxValues(newMovingMaxDistance, newStationaryMaxDistance, inactivityTimer))
{
SerialPrint("i", "LD2410", "Параметры установлены. Перезапустите датчик");
}
else
{
SerialPrint("E", "LD2410", "Ошибка записи параметров.");
}
}
else
{
SerialPrint("E", "LD2410", "Заданы не корректные параметры. Диапазон от 1 до 8 ");
}
}
}
if (command == "setsensitivity")
{
if (param[0].isDecimal && param[1].isDecimal && param[2].isDecimal)
{
uint8_t gate = param[0].valD;
uint8_t motionSensitivity = param[1].valD;
uint16_t stationarySensitivity = param[2].valD;
if (motionSensitivity >= 0 && stationarySensitivity >= 0 && motionSensitivity <= 100 && stationarySensitivity <= 100)
{
if (instanceradar(_rx, _tx)->setGateSensitivityThreshold(gate, motionSensitivity, stationarySensitivity))
{
SerialPrint("i", "LD2410", "Параметры установлены. Перезапустите датчик");
}
else
{
SerialPrint("E", "LD2410", "Ошибка записи параметров.");
}
}
else
{
SerialPrint("E", "LD2410", "Заданы не корректные параметры. Диапазон от 1 до 100 ");
}
}
}
if (command == "enableengineeringmode")
{
if (instanceradar(_rx, _tx)->requestStartEngineeringMode())
{
SerialPrint("i", "LD2410", "Параметры установлены. Перезапустите датчик");
}
else
{
SerialPrint("E", "LD2410", "Ошибка записи параметров.");
}
}
if (command == "disableengineeringmode")
{
if (instanceradar(_rx, _tx)->requestEndEngineeringMode())
{
SerialPrint("i", "LD2410", "Параметры установлены. Перезапустите датчик");
}
else
{
SerialPrint("E", "LD2410", "Ошибка записи параметров.");
}
}
if (command == "restart")
{
if (instanceradar(_rx, _tx)->requestRestart())
{
SerialPrint("i", "LD2410", "Датчик перезапущен");
}
else
{
SerialPrint("E", "LD2410", "Ошибка перезапуска датчика.");
}
}
if (command == "readversion")
{
if (instanceradar(_rx, _tx)->requestFirmwareVersion())
{
SerialPrint("i", "LD2410", (String)instanceradar(_rx, _tx)->firmware_major_version);
SerialPrint("i", "LD2410", (String)instanceradar(_rx, _tx)->firmware_minor_version);
}
else
{
SerialPrint("E", "LD2410", "Ошибка получения версии.");
}
}
if (command == "factoryreset")
{
if (instanceradar(_rx, _tx)->requestFactoryReset())
{
SerialPrint("i", "LD2410", "Параметры установлены. Перезапустите датчик");
}
else
{
SerialPrint("E", "LD2410", "Ошибка сброса параметров.");
}
}
}
~ld2410m(){};
};
//---------------------------------------------------------------------------
// движение / стационарное - присутствие
class ld2410t : public IoTItem
{
private:
uint8_t _rx, _tx;
public:
//=======================================================================================================
// setup()
ld2410t(String parameters) : IoTItem(parameters)
{
String tmp;
jsonRead(parameters, "RX", tmp);
_rx = tmp.toInt();
jsonRead(parameters, "TX", tmp);
_tx = tmp.toInt();
}
void loop()
{
instanceradar(_rx, _tx)->read();
if (instanceradar(_rx, _tx)->isConnected() && millis() - lastReadingM > 1000) // Report every 1000ms
{
lastReadingM = millis();
err = 0;
presence = instanceradar(_rx, _tx)->presenceDetected();
if (instanceradar(_rx, _tx)->stationaryTargetDetected())
{
movement = 0;
// distance = instanceradar(_rx, _tx)->stationaryTargetDistance();
// energy = instanceradar(_rx, _tx)->stationaryTargetEnergy();
}
if (instanceradar(_rx, _tx)->movingTargetDetected())
{
movement = 1;
// distance = instanceradar(_rx, _tx)->movingTargetDistance();
// energy = instanceradar(_rx, _tx)->movingTargetEnergy();
}
}
if (presence == 0 && movement_last != 0)
{
movement = 0;
}
if (movement != movement_last)
{
value.valD = int(movement);
regEvent(value.valD, "ld2410t");
movement_last = movement;
}
}
~ld2410t(){};
};
//---------------------------------------------------------------------------
// дистанция
class ld2410d : public IoTItem
{
private:
uint8_t _rx, _tx;
public:
//=======================================================================================================
// setup()
ld2410d(String parameters) : IoTItem(parameters)
{
String tmp;
jsonRead(parameters, "RX", tmp);
_rx = tmp.toInt();
jsonRead(parameters, "TX", tmp);
_tx = tmp.toInt();
}
void loop()
{
instanceradar(_rx, _tx)->read();
if (instanceradar(_rx, _tx)->isConnected() && millis() - lastReadingD > 1000) // Report every 1000ms
{
lastReadingD = millis();
err = 0;
presence = instanceradar(_rx, _tx)->presenceDetected();
if (instanceradar(_rx, _tx)->stationaryTargetDetected())
{
// movement = 0;
distance = instanceradar(_rx, _tx)->stationaryTargetDistance();
// energy = instanceradar(_rx, _tx)->stationaryTargetEnergy();
}
if (instanceradar(_rx, _tx)->movingTargetDetected())
{
// movement = 1;
distance = instanceradar(_rx, _tx)->movingTargetDistance();
// energy = instanceradar(_rx, _tx)->movingTargetEnergy();
}
if (presence == 0 && distance_last != 0)
{
distance = 0;
}
if (distance != distance_last)
{
value.valD = int(distance);
regEvent(value.valD, "ld2410d");
distance_last = distance;
}
}
}
~ld2410d(){};
};
//---------------------------------------------------------------------------
// энергия
class ld2410e : public IoTItem
{
private:
uint8_t _rx, _tx;
public:
//=======================================================================================================
// setup()
ld2410e(String parameters) : IoTItem(parameters)
{
String tmp;
jsonRead(parameters, "RX", tmp);
_rx = tmp.toInt();
jsonRead(parameters, "TX", tmp);
_tx = tmp.toInt();
}
void loop()
{
instanceradar(_rx, _tx)->read();
if (instanceradar(_rx, _tx)->isConnected() && millis() - lastReadingE > 1000) // Report every 1000ms
{
lastReadingE = millis();
err = 0;
presence = instanceradar(_rx, _tx)->presenceDetected();
if (instanceradar(_rx, _tx)->stationaryTargetDetected())
{
// movement = 0;
// distance = instanceradar(_rx, _tx)->stationaryTargetDistance();
energy = instanceradar(_rx, _tx)->stationaryTargetEnergy();
}
if (instanceradar(_rx, _tx)->movingTargetDetected())
{
// movement = 1;
// distance = instanceradar(_rx, _tx)->movingTargetDistance();
energy = instanceradar(_rx, _tx)->movingTargetEnergy();
}
if (presence == 0 && energy_last != 0)
{
energy = 0;
}
if (energy != energy_last)
{
value.valD = int(energy);
regEvent(value.valD, "ld2410e");
// value = Value;
// regEvent((String)(int)value.valD, F("ld2410e"), false, true);
// SerialPrint("i", "LD2410", "Radar sensor энергия: " + String(energy));
energy_last = energy;
}
}
}
~ld2410e(){};
};
//---------------------------------------------------------------------------
void *getAPI_ld2410(String subtype, String param)
{
if (subtype == F("ld2410m"))
{
return new ld2410m(param);
}
else if (subtype == F("ld2410t"))
{
return new ld2410t(param);
}
else if (subtype == F("ld2410d"))
{
return new ld2410d(param);
}
else if (subtype == F("ld2410e"))
{
return new ld2410e(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,92 @@
{
"menuSection": "Сенсоры",
"configItem": [
{
"global": 0,
"name": "LD2410 Датчик присутствия",
"type": "Reading",
"subtype": "ld2410m",
"id": "ld2410m",
"widget": "anydataDef",
"page": "Сенсоры",
"descr": "Присутствие",
"RX": 32,
"TX": 33,
"val": 0,
"round": 0,
"ticker": 0
},
{
"global": 0,
"name": "LD2410 подвижность объета",
"type": "Reading",
"subtype": "ld2410t",
"id": "ld2410t",
"widget": "anydataDef",
"page": "Сенсоры",
"descr": "Движение",
"RX": 32,
"TX": 33,
"val": 0,
"round": 0
},
{
"global": 0,
"name": "LD2410 дистанция до объекта",
"type": "Reading",
"subtype": "ld2410d",
"id": "ld2410d",
"widget": "anydataCm",
"page": "Сенсоры",
"descr": "Дистанция",
"RX": 32,
"TX": 33,
"val": 0,
"round": 0
},
{
"global": 0,
"name": "LD2410 отраженная энергия",
"type": "Reading",
"subtype": "ld2410e",
"id": "ld2410e",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "Энергия",
"RX": 32,
"TX": 33,
"val": 0,
"round": 0
}
],
"about": {
"authorName": "AVAKS",
"authorContact": "https://t.me/avaks",
"authorGit": "https://github.com/avaksru",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "Mitchel https://t.me/Mit4bmw",
"moduleName": "ld2410",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 0
},
"subTypes": [
"ld2410m",
"ld2410t",
"ld2410d",
"ld2410e"
],
"title": "Радарный датчик присутствия человека Hi-Link HLK-LD2410",
"moduleDesc": "Умный датчик, который измеряет расстояние, определяет стоит объект или двигается. Умеет разбивать зоны движения (всего можно до 8 зон задать). ",
"propInfo": {
"ticker": "1 - генерирует событие каждую секунду пока обнаружено присутствие, 0 - событие генереруется только один раз когда присутствие обнаружено или когда обьект вышел из поля обнаружения датчика"
}
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"ncmreynolds/ld2410@^0.1.3"
]
}
}

View File

@@ -28,7 +28,7 @@
"esp8266_4mb": 15
},
"title": "Будильник типа Cron",
"moduleDesc": "Планировщик времени для периодического выполнения заданий в определённое время. Генерирует событие в указанное время по формату Cron https://ru.wikipedia.org/wiki/Cron ",
"moduleDesc": "Планировщик времени для периодического выполнения заданий в определённое время. Генерирует событие в указанное время по формату Cron https://ru.wikipedia.org/wiki/Cron . Но в данной реализации есть возможность задавать секундный интервал, поэтому слева необходимо добавить еще один разряд значений секунд - подробнее в базовой библиотеке https://github.com/staticlibs/ccronexpr",
"propInfo": {
"formatNextAlarm": "Формат представления даты и времени срабатывания следующего уведомления. http://cppstudio.com/post/621/",
"needSave": "Требуется сохранять(1) или нет(0) состояние в энерго независимую память."
@@ -50,6 +50,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -0,0 +1,170 @@
#include "Global.h"
#include "classes/IoTItem.h"
String URL = F("https://script.google.com/macros/s/");
class GoogleSheet : public IoTItem
{
private:
String id;
String logid;
String scid = "";
String shname = "";
// bool init = false;
int interval = 1;
// long interval;
String urlFinal;
public:
GoogleSheet(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("id"), id);
jsonRead(parameters, F("logid"), logid);
jsonRead(parameters, F("scid"), scid);
jsonRead(parameters, F("shname"), shname);
jsonRead(parameters, F("int"), interval);
interval = interval * 1000 * 60; // так как у нас в минутах
urlFinal = URL + scid + F("/exec?") + F("sheet=") + shname;
}
void doByInterval()
{
if (WiFi.status() == WL_CONNECTED)
{
String value = getItemValue(logid);
if (value != "")
send2Google(logid, value, true);
}
}
void loop()
{
if (enableDoByInt)
{
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= interval)
{
prevMillis = millis();
this->doByInterval();
}
}
}
IoTValue execute(String command, std::vector<IoTValue> &param)
{
if (WiFi.status() == WL_CONNECTED)
{
if (command == F("logGoogle"))
{ // Логирование определенного элемента по его идентификатору в GoogleSheet
/* if (param.size() == 1)
{
String id = param[0].valS;
String value = getItemValue(id);
send2Google(id, value, true);
return {};
}
*/
if (param.size() >= 1)
{
int sizeOfParam = param.size();
for (unsigned int i = 0; i < sizeOfParam; i++)
{
IoTItem *itm = findIoTItemOnValue(param[i].valS);
if (itm != nullptr)
{
if (i == sizeOfParam - 1)
send2Google(itm->getID(), param[i].valS, true);
else
send2Google(itm->getID(), param[i].valS, false);
}
}
}
}
else if (command == F("logGoogleAny"))
{ // Запись произвольных данных в GoogleSheet
if (param.size() == 2)
{
send2Google(param[0].valS, param[1].valS, true);
return {};
}
}
}
return {};
}
void send2Google(String logid, String value, bool send)
{
urlFinal = urlFinal + ("&id=") + logid + ("&value=") + value;
if (!send)
return; // Не отправляем просто накапливаем данные
/* if (!init)
{
init = true;
urlFinal = urlFinal + "&init=1";
}
*/
HTTPClient http;
#if defined ESP8266
WiFiClientSecure client;
client.setInsecure();
if (!http.begin(client, urlFinal))
{
#elif defined ESP32
WiFiClient client;
if (!http.begin(urlFinal))
{
#endif
SerialPrint("I", F("GoogleSheet"), F("connection failed"));
}
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); // HTTPC_STRICT_FOLLOW_REDIRECTS HTTPC_FORCE_FOLLOW_REDIRECTS
http.addHeader(F("Content-Type"), F("application/x-www-form-urlencoded"));
int httpCode = http.GET();
// String payload = http.getString();
SerialPrint("<-", F("GoogleSheet"), "URL: " + urlFinal);
SerialPrint("->", F("GoogleSheet"), "server: " + (String)httpCode); /*"URL: " + urlFinal + */
/* if (httpCode > 0)
{
SerialPrint("->", F("GoogleSheet"), "msg from server: " + (String)payload.c_str());
}
*/
http.end();
// Обнуляем данные в запросе, так как все отправили
urlFinal = URL + scid + F("/exec?") + F("sheet=") + shname;
};
// поиск элемента модуля в существующей конфигурации по его значению
// По хорошему ЭТО наверное надо в ЯДРО пернести
IoTItem *findIoTItemOnValue(const String &value)
{
if (value == "")
return nullptr;
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it)
{
if ((*it)->getValue() == value)
return *it;
}
return nullptr;
};
~GoogleSheet(){};
};
void *getAPI_GoogleSheet(String subtype, String param)
{
if (subtype == F("GoogleSheet"))
{
return new GoogleSheet(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,52 @@
var SS = SpreadsheetApp.openById('GOOGLE_SHEET_ID');
function doGet(e){
var value = e.parameters.value;
var id = e.parameters.id;
var sheet = e.parameter.sheet;
var init = e.parameter.init;
if (sheet == undefined) {
sheet = SS.getActiveSheet();
} else{
sheet = SS.getSheetByName(sheet);
}
if (sheet == null) {
return ContentService.createTextOutput("Error sheet name");
}
// if (init !== undefined){
sheet.getRange('A1').setValue("ID");
sheet.getRange('B1').setValue("VALUE");
sheet.getRange('C1').setValue("DATE");
// }
var nextFreeRow = sheet.getLastRow() + 1;
if (id == undefined) id = "nan";
if (value !== undefined){
try {
var now = Utilities.formatDate(new Date(), "GMT+03:00", "dd.MM.yyyy HH:mm:ss");
for (let i = 0; i < id.length; i++) {
sheet.getRange("A"+nextFreeRow).setValue(id[i]);
value[i] = value[i].replace(/\./, ",");
sheet.getRange("B"+nextFreeRow).setValue(value[i]);
sheet.getRange("C"+nextFreeRow).setValue(now);
nextFreeRow++;
}
return ContentService.createTextOutput("Successfully wrote: " +
e.parameter.value + "\ninto spreadsheet.");
//Logger.log(str);
}
catch(f){
return ContentService.createTextOutput("Error in parsing appendRow");
}
} else {
return ContentService.createTextOutput("Error wrote: value = " +
e.parameter.value + " , id = "+e.parameter.id);
}
}

View File

@@ -0,0 +1,64 @@
{
"menuSection": "Виртуальные элементы",
"configItem": [
{
"global": 0,
"name": "GoogleSheet",
"type": "Reading",
"subtype": "GoogleSheet",
"id": "sheet",
"widget": "nil",
"page": "",
"descr": "",
"int": 5,
"logid": "",
"scid": "Script_ID",
"shname": "Logger"
}
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",
"moduleName": "GoogleSheet",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 10,
"esp8266_4mb": 10
},
"title": "Логирование в Google таблицы",
"moduleDesc": "Расширение позволяющее логировать любую величину в Google таблицы. Инструкция https://drive.google.com/file/d/1VuI06arObNfH3rsOSHKww1tyhfgqXd9F/view?usp=sharing",
"propInfo": {
"int": "Интервал логирования в минутах",
"logid": "ID величины которую будем логировать",
"scid": "Идентификатор развертывания Google Apps (script id)",
"shname": "Наименование листа в таблице (sheet name)"
},
"retInfo": "",
"funcInfo": [
{
"name": "logGoogle",
"descr": "Использовать не чаще раз в минуту! Логирование элементов по их идентификатору в GoogleSheet, указывать через запятую, от одного до N (проверено на 16шт)",
"params": [
"id Идентификатор 1-го элеменета",
"id Идентификатор N-го элеменета"
]
},
{
"name": "logGoogleAny",
"descr": "Использовать не чаще раз в минуту! Запись произвольных данных в GoogleSheet",
"params": [
"Наименование данных",
"Значение для записи"
]
}
]
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": []
}
}

View File

@@ -51,6 +51,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -44,6 +44,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -70,6 +70,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -36,6 +36,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -96,6 +96,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

Some files were not shown because too many files have changed in this diff Show More