mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 09:19:51 +03:00
1.9.0 web - new implementation
This commit is contained in:
2173
lib/MyESP/MyESP.cpp
2173
lib/MyESP/MyESP.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,430 +0,0 @@
|
||||
/*
|
||||
* MyESP.h
|
||||
*
|
||||
* Paul Derbyshire - December 2018
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef MyESP_h
|
||||
#define MyESP_h
|
||||
|
||||
#define MYESP_VERSION "1.1.24"
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <AsyncMqttClient.h> // https://github.com/marvinroger/async-mqtt-client and for ESP32 see https://github.com/marvinroger/async-mqtt-client/issues/127
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <FS.h>
|
||||
#include <JustWifi.h> // https://github.com/xoseperez/justwifi
|
||||
#include <TelnetSpy.h> // modified from https://github.com/yasheena/telnetspy
|
||||
|
||||
#ifdef CRASH
|
||||
#include <EEPROM_Rotate.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
void custom_crash_callback(struct rst_info *, uint32_t, uint32_t);
|
||||
#include "user_interface.h"
|
||||
extern struct rst_info resetInfo;
|
||||
}
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
//#include <ESPmDNS.h>
|
||||
#include <SPIFFS.h> // added for ESP32
|
||||
#define ets_vsnprintf vsnprintf // added for ESP32
|
||||
#define OTA_PORT 3232
|
||||
#else
|
||||
#include <ESPAsyncTCP.h>
|
||||
#define OTA_PORT 8266
|
||||
#endif
|
||||
|
||||
#define MYEMS_CONFIG_FILE "/config.json"
|
||||
|
||||
#define LOADAVG_INTERVAL 30000 // Interval between calculating load average (in ms) = 30 seconds
|
||||
|
||||
// WIFI
|
||||
#define WIFI_CONNECT_TIMEOUT 10000 // Connecting timeout for WIFI in ms (10 seconds)
|
||||
#define WIFI_RECONNECT_INTERVAL 600000 // If could not connect to WIFI, retry after this time in ms. 10 minutes
|
||||
|
||||
// MQTT
|
||||
#define MQTT_PORT 1883 // MQTT port
|
||||
#define MQTT_RECONNECT_DELAY_MIN 2000 // Try to reconnect in 3 seconds upon disconnection
|
||||
#define MQTT_RECONNECT_DELAY_STEP 3000 // Increase the reconnect delay in 3 seconds after each failed attempt
|
||||
#define MQTT_RECONNECT_DELAY_MAX 120000 // Set reconnect time to 2 minutes at most
|
||||
#define MQTT_MAX_TOPIC_SIZE 50 // max length of MQTT topic
|
||||
#define MQTT_TOPIC_START "start"
|
||||
#define MQTT_TOPIC_HEARTBEAT "heartbeat"
|
||||
#define MQTT_TOPIC_START_PAYLOAD "start"
|
||||
#define MQTT_TOPIC_RESTART "restart"
|
||||
|
||||
// Internal MQTT events
|
||||
#define MQTT_CONNECT_EVENT 0
|
||||
#define MQTT_DISCONNECT_EVENT 1
|
||||
#define MQTT_MESSAGE_EVENT 2
|
||||
|
||||
// Telnet
|
||||
#define TELNET_SERIAL_BAUD 115200
|
||||
#define TELNET_MAX_COMMAND_LENGTH 80 // length of a command
|
||||
#define TELNET_EVENT_CONNECT 1
|
||||
#define TELNET_EVENT_DISCONNECT 0
|
||||
#define TELNET_EVENT_SHOWCMD 10
|
||||
#define TELNET_EVENT_SHOWSET 20
|
||||
|
||||
// ANSI Colors
|
||||
#define COLOR_RESET "\x1B[0m"
|
||||
#define COLOR_BLACK "\x1B[0;30m"
|
||||
#define COLOR_RED "\x1B[0;31m"
|
||||
#define COLOR_GREEN "\x1B[0;32m"
|
||||
#define COLOR_YELLOW "\x1B[0;33m"
|
||||
#define COLOR_BLUE "\x1B[0;34m"
|
||||
#define COLOR_MAGENTA "\x1B[0;35m"
|
||||
#define COLOR_CYAN "\x1B[0;36m"
|
||||
#define COLOR_WHITE "\x1B[0;37m"
|
||||
#define COLOR_BOLD_ON "\x1B[1m"
|
||||
#define COLOR_BOLD_OFF "\x1B[22m"
|
||||
#define COLOR_BRIGHT_BLACK "\x1B[0;90m"
|
||||
#define COLOR_BRIGHT_RED "\x1B[0;91m"
|
||||
#define COLOR_BRIGHT_GREEN "\x1B[0;92m"
|
||||
#define COLOR_BRIGHT_YELLOW "\x1B[0;99m"
|
||||
#define COLOR_BRIGHT_BLUE "\x1B[0;94m"
|
||||
#define COLOR_BRIGHT_MAGENTA "\x1B[0;95m"
|
||||
#define COLOR_BRIGHT_CYAN "\x1B[0;96m"
|
||||
#define COLOR_BRIGHT_WHITE "\x1B[0;97m"
|
||||
|
||||
// reset reason codes
|
||||
PROGMEM const char custom_reset_hardware[] = "Hardware button";
|
||||
PROGMEM const char custom_reset_terminal[] = "Reboot from terminal";
|
||||
PROGMEM const char custom_reset_mqtt[] = "Reboot from MQTT";
|
||||
PROGMEM const char custom_reset_ota[] = "Reboot after successful OTA update";
|
||||
PROGMEM const char * const custom_reset_string[] = {custom_reset_hardware, custom_reset_terminal, custom_reset_mqtt, custom_reset_ota};
|
||||
#define CUSTOM_RESET_HARDWARE 1 // Reset from hardware button
|
||||
#define CUSTOM_RESET_TERMINAL 2 // Reset from terminal
|
||||
#define CUSTOM_RESET_MQTT 3 // Reset via MQTT
|
||||
#define CUSTOM_RESET_OTA 4 // Reset after successful OTA update
|
||||
#define CUSTOM_RESET_MAX 4
|
||||
|
||||
// SPIFFS
|
||||
#define SPIFFS_MAXSIZE 800 // https://arduinojson.org/v6/assistant/
|
||||
|
||||
// CRASH
|
||||
/**
|
||||
* Structure of the single crash data set
|
||||
*
|
||||
* 1. Crash time
|
||||
* 2. Restart reason
|
||||
* 3. Exception cause
|
||||
* 4. epc1
|
||||
* 5. epc2
|
||||
* 6. epc3
|
||||
* 7. excvaddr
|
||||
* 8. depc
|
||||
* 9. address of stack start
|
||||
* 10. address of stack end
|
||||
* 11. stack trace bytes
|
||||
* ...
|
||||
*/
|
||||
#define SAVE_CRASH_EEPROM_OFFSET 0x0100 // initial address for crash data
|
||||
#define SAVE_CRASH_CRASH_TIME 0x00 // 4 bytes
|
||||
#define SAVE_CRASH_RESTART_REASON 0x04 // 1 byte
|
||||
#define SAVE_CRASH_EXCEPTION_CAUSE 0x05 // 1 byte
|
||||
#define SAVE_CRASH_EPC1 0x06 // 4 bytes
|
||||
#define SAVE_CRASH_EPC2 0x0A // 4 bytes
|
||||
#define SAVE_CRASH_EPC3 0x0E // 4 bytes
|
||||
#define SAVE_CRASH_EXCVADDR 0x12 // 4 bytes
|
||||
#define SAVE_CRASH_DEPC 0x16 // 4 bytes
|
||||
#define SAVE_CRASH_STACK_START 0x1A // 4 bytes
|
||||
#define SAVE_CRASH_STACK_END 0x1E // 4 bytes
|
||||
#define SAVE_CRASH_STACK_TRACE 0x22 // variable
|
||||
|
||||
// Base address of USER RTC memory
|
||||
// https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map#memmory-mapped-io-registers
|
||||
#define RTCMEM_ADDR_BASE (0x60001200)
|
||||
|
||||
// RTC memory is accessed using blocks of 4 bytes.
|
||||
// Blocks 0..63 are reserved by the SDK, 64..192 are available to the user.
|
||||
// Blocks 64..96 are reserved by the eboot 'struct eboot_command' (128 -> (128 / 4) -> 32):
|
||||
// https://github.com/esp8266/Arduino/blob/master/bootloaders/eboot/eboot_command.h
|
||||
#define RTCMEM_OFFSET 32u
|
||||
#define RTCMEM_ADDR (RTCMEM_ADDR_BASE + (RTCMEM_OFFSET * 4u))
|
||||
#define RTCMEM_BLOCKS 96u
|
||||
#define RTCMEM_MAGIC 0x45535076
|
||||
|
||||
struct RtcmemData {
|
||||
uint32_t magic; // RTCMEM_MAGIC
|
||||
uint32_t sys; // system details
|
||||
};
|
||||
|
||||
static_assert(sizeof(RtcmemData) <= (RTCMEM_BLOCKS * 4u), "RTCMEM struct is too big");
|
||||
|
||||
#define SYSTEM_CHECK_TIME 60000 // The system is considered stable after these many millis (1 minute)
|
||||
#define SYSTEM_CHECK_MAX 5 // After this many crashes on boot
|
||||
#define HEARTBEAT_INTERVAL 120000 // in milliseconds, how often the MQTT heartbeat is sent (2 mins)
|
||||
|
||||
typedef struct {
|
||||
bool set; // is it a set command
|
||||
char key[50];
|
||||
char description[100];
|
||||
} command_t;
|
||||
|
||||
typedef enum { MYESP_FSACTION_SET, MYESP_FSACTION_LIST, MYESP_FSACTION_SAVE, MYESP_FSACTION_LOAD } MYESP_FSACTION;
|
||||
|
||||
typedef enum {
|
||||
MYESP_BOOTSTATUS_POWERON = 0,
|
||||
MYESP_BOOTSTATUS_BOOTED = 1,
|
||||
MYESP_BOOTSTATUS_BOOTING = 2,
|
||||
MYESP_BOOTSTATUS_RESETNEEDED = 3
|
||||
} MYESP_BOOTSTATUS; // boot messages
|
||||
|
||||
typedef std::function<void(unsigned int, const char *, const char *)> mqtt_callback_f;
|
||||
typedef std::function<void()> wifi_callback_f;
|
||||
typedef std::function<void()> ota_callback_f;
|
||||
typedef std::function<void(uint8_t, const char *)> telnetcommand_callback_f;
|
||||
typedef std::function<void(uint8_t)> telnet_callback_f;
|
||||
typedef std::function<bool(MYESP_FSACTION, const JsonObject json)> fs_callback_f;
|
||||
typedef std::function<bool(MYESP_FSACTION, uint8_t, const char *, const char *)> fs_settings_callback_f;
|
||||
typedef std::function<void(char *)> web_callback_f;
|
||||
|
||||
// calculates size of an 2d array at compile time
|
||||
template <typename T, size_t N>
|
||||
constexpr size_t ArraySize(T (&)[N]) {
|
||||
return N;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PROGMEM_readAnything(const T * sce, T & dest) {
|
||||
memcpy_P(&dest, sce, sizeof(T));
|
||||
}
|
||||
|
||||
#define UPTIME_OVERFLOW 4294967295 // Uptime overflow value
|
||||
|
||||
// web min and max length of wifi ssid and password
|
||||
#define MAX_SSID_LEN 32
|
||||
#define MAX_PWD_LEN 64
|
||||
|
||||
#define MYESP_BOOTUP_FLASHDELAY 50 // flash duration for LED at bootup sequence
|
||||
#define MYESP_BOOTUP_DELAY 2000 // time before we open the window to reset. This is to stop resetting values when uploading firmware via USB
|
||||
|
||||
// max size of char buffer for storing web page
|
||||
#define MYESP_MAXCHARBUFFER 800
|
||||
|
||||
// Holds the admin webpage in the program memory
|
||||
const char webCommonPage_start[] = "<html>"
|
||||
"<head>"
|
||||
"<style>input {font-size: 1.2em; width: 100%; max-width: 350px; display: block; margin: 5px auto; }"
|
||||
"body {background-color: #FFA500;font: normal 18px Verdana, Arial, sans-serif;} </style>";
|
||||
|
||||
const char webCommonPage_start_body[] = "</head><body>";
|
||||
|
||||
const char webCommonPage_end[] = "</body></html>";
|
||||
|
||||
const char webResetPage_form[] = "<form id='form' action='/reset' method='post'>"
|
||||
"<input name='newssid' type='text' maxlength='32' placeholder='SSID'>"
|
||||
"<input name='newpassword' id='password1' type='password' maxlength='64' placeholder='Password'>"
|
||||
"<input type='submit' value='Save and reboot'>"
|
||||
"</form>";
|
||||
|
||||
const char webResetPage_post[] =
|
||||
"<p>New wifi credentials set. System is now rebooting. Please wait a few seconds and then reconnect via telnet or browser to its new IP given address.</p>";
|
||||
|
||||
const char webResetAllPage_form[] = "<form id='resetform' action='/resetall' method='post'>"
|
||||
"<input name='confirm' type='text' minlength='3' maxlength='16' placeholder='yes'>"
|
||||
"<input type='submit' value='Reset All'>"
|
||||
"</form>";
|
||||
|
||||
// class definition
|
||||
class MyESP {
|
||||
public:
|
||||
MyESP();
|
||||
~MyESP();
|
||||
|
||||
ESP8266WebServer webServer; // Web server on port 80
|
||||
|
||||
// wifi
|
||||
void setWIFICallback(void (*callback)());
|
||||
void setWIFI(const char * wifi_ssid, const char * wifi_password, wifi_callback_f callback);
|
||||
bool isWifiConnected();
|
||||
bool isAPmode();
|
||||
|
||||
// mqtt
|
||||
bool isMQTTConnected();
|
||||
void mqttSubscribe(const char * topic);
|
||||
void mqttUnsubscribe(const char * topic);
|
||||
void mqttPublish(const char * topic, const char * payload);
|
||||
void setMQTT(const char * mqtt_host,
|
||||
const char * mqtt_username,
|
||||
const char * mqtt_password,
|
||||
const char * mqtt_base,
|
||||
unsigned long mqtt_keepalive,
|
||||
unsigned char mqtt_qos,
|
||||
bool mqtt_retain,
|
||||
const char * mqtt_will_topic,
|
||||
const char * mqtt_will_online_payload,
|
||||
const char * mqtt_will_offline_payload,
|
||||
mqtt_callback_f callback);
|
||||
|
||||
// OTA
|
||||
void setOTA(ota_callback_f OTACallback_pre, ota_callback_f OTACallback_post);
|
||||
|
||||
// debug & telnet
|
||||
void myDebug(const char * format, ...);
|
||||
void myDebug_P(PGM_P format_P, ...);
|
||||
void setTelnet(telnetcommand_callback_f callback_cmd, telnet_callback_f callback);
|
||||
bool getUseSerial();
|
||||
void setUseSerial(bool toggle);
|
||||
|
||||
// FS
|
||||
void setSettings(fs_callback_f callback, fs_settings_callback_f fs_settings_callback);
|
||||
bool fs_saveConfig();
|
||||
|
||||
// Web
|
||||
void setWeb(web_callback_f callback_web);
|
||||
|
||||
// Crash
|
||||
void crashClear();
|
||||
void crashDump();
|
||||
void crashTest(uint8_t t);
|
||||
void crashInfo();
|
||||
|
||||
// general
|
||||
void end();
|
||||
void loop();
|
||||
void begin(const char * app_hostname, const char * app_name, const char * app_version);
|
||||
void setBoottime(const char * boottime);
|
||||
void resetESP();
|
||||
int getWifiQuality();
|
||||
void showSystemStats();
|
||||
bool getHeartbeat();
|
||||
uint32_t getSystemLoadAverage();
|
||||
uint32_t getSystemResetReason();
|
||||
uint8_t getSystemBootStatus();
|
||||
|
||||
private:
|
||||
// mqtt
|
||||
AsyncMqttClient mqttClient;
|
||||
unsigned long _mqtt_reconnect_delay;
|
||||
void _mqttOnMessage(char * topic, char * payload, size_t len);
|
||||
void _mqttConnect();
|
||||
void _mqtt_setup();
|
||||
mqtt_callback_f _mqtt_callback;
|
||||
void _mqttOnConnect();
|
||||
void _sendStart();
|
||||
char * _mqttTopic(const char * topic);
|
||||
char * _mqtt_host;
|
||||
char * _mqtt_username;
|
||||
char * _mqtt_password;
|
||||
char * _mqtt_base;
|
||||
unsigned long _mqtt_keepalive;
|
||||
unsigned char _mqtt_qos;
|
||||
bool _mqtt_retain;
|
||||
char * _mqtt_will_topic;
|
||||
char * _mqtt_will_online_payload;
|
||||
char * _mqtt_will_offline_payload;
|
||||
char * _mqtt_topic;
|
||||
unsigned long _mqtt_last_connection;
|
||||
bool _mqtt_connecting;
|
||||
bool _rtcmem_status;
|
||||
|
||||
// wifi
|
||||
void _wifiCallback(justwifi_messages_t code, char * parameter);
|
||||
void _wifi_setup();
|
||||
wifi_callback_f _wifi_callback;
|
||||
char * _wifi_ssid;
|
||||
char * _wifi_password;
|
||||
bool _wifi_connected;
|
||||
String _getESPhostname();
|
||||
|
||||
// ota
|
||||
ota_callback_f _ota_pre_callback;
|
||||
ota_callback_f _ota_post_callback;
|
||||
void _ota_setup();
|
||||
void _OTACallback();
|
||||
bool _ota_doing_update;
|
||||
|
||||
// crash
|
||||
void _eeprom_setup();
|
||||
|
||||
// telnet & debug
|
||||
TelnetSpy SerialAndTelnet;
|
||||
void _telnetConnected();
|
||||
void _telnetDisconnected();
|
||||
void _telnetHandle();
|
||||
void _telnetCommand(char * commandLine);
|
||||
char * _telnet_readWord(bool allow_all_chars);
|
||||
void _telnet_setup();
|
||||
char _command[TELNET_MAX_COMMAND_LENGTH]; // the input command from either Serial or Telnet
|
||||
void _consoleShowHelp();
|
||||
telnetcommand_callback_f _telnetcommand_callback; // Callable for projects commands
|
||||
telnet_callback_f _telnet_callback; // callback for connect/disconnect
|
||||
bool _changeSetting(uint8_t wc, const char * setting, const char * value);
|
||||
|
||||
// fs
|
||||
void _fs_setup();
|
||||
bool _fs_loadConfig();
|
||||
void _fs_printConfig();
|
||||
void _fs_eraseConfig();
|
||||
|
||||
// settings
|
||||
fs_callback_f _fs_callback;
|
||||
fs_settings_callback_f _fs_settings_callback;
|
||||
void _printSetCommands();
|
||||
|
||||
// web
|
||||
web_callback_f _web_callback;
|
||||
|
||||
// general
|
||||
char * _app_hostname;
|
||||
char * _app_name;
|
||||
char * _app_version;
|
||||
char * _boottime;
|
||||
bool _suspendOutput;
|
||||
bool _serial;
|
||||
bool _heartbeat;
|
||||
unsigned long _getUptime();
|
||||
String _buildTime();
|
||||
bool _firstInstall;
|
||||
|
||||
// reset reason and rtcmem
|
||||
bool _rtcmemStatus();
|
||||
bool _getRtcmemStatus();
|
||||
|
||||
void _rtcmemInit();
|
||||
void _rtcmemSetup();
|
||||
|
||||
void _deferredReset(unsigned long delay, uint8_t reason);
|
||||
|
||||
uint8_t _getSystemStabilityCounter();
|
||||
void _setSystemStabilityCounter(uint8_t counter);
|
||||
|
||||
void _setSystemResetReason(uint8_t reason);
|
||||
uint8_t _getCustomResetReason();
|
||||
void _setCustomResetReason(uint8_t reason);
|
||||
uint8_t _getSystemResetReason();
|
||||
|
||||
void _setSystemBootStatus(uint8_t status);
|
||||
|
||||
bool _systemStable;
|
||||
void _bootupSequence();
|
||||
bool _getSystemCheck();
|
||||
void _systemCheckLoop();
|
||||
void _setSystemCheck(bool stable);
|
||||
|
||||
// load average (0..100) and heap ram
|
||||
void _calculateLoad();
|
||||
uint32_t _load_average;
|
||||
uint32_t _getInitialFreeHeap();
|
||||
uint32_t _getUsedHeap();
|
||||
|
||||
// heartbeat
|
||||
void _heartbeatCheck(bool force);
|
||||
|
||||
// webserver
|
||||
void _webserver_setup();
|
||||
void _webRootPage();
|
||||
void _webResetPage();
|
||||
void _webResetAllPage();
|
||||
};
|
||||
|
||||
extern MyESP myESP;
|
||||
|
||||
#endif
|
||||
@@ -1,655 +0,0 @@
|
||||
/*
|
||||
* TELNET SERVER FOR ESP8266 / ESP32
|
||||
* Cloning the serial port via Telnet.
|
||||
*
|
||||
* Written by Wolfgang Mattis (arduino@yasheena.de).
|
||||
* Version 1.1 / September 7, 2018.
|
||||
* MIT license, all text above must be included in any redistribution.
|
||||
*/
|
||||
|
||||
#ifdef ESP8266
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "TelnetSpy.h"
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
static TelnetSpy * actualObject = NULL;
|
||||
|
||||
static void TelnetSpy_putc(char c) {
|
||||
if (actualObject) {
|
||||
actualObject->write(c);
|
||||
}
|
||||
}
|
||||
|
||||
static void TelnetSpy_ignore_putc(char c) {
|
||||
;
|
||||
}
|
||||
|
||||
TelnetSpy::TelnetSpy() {
|
||||
port = TELNETSPY_PORT;
|
||||
telnetServer = NULL;
|
||||
started = false;
|
||||
listening = false;
|
||||
firstMainLoop = true;
|
||||
usedSer = &Serial;
|
||||
storeOffline = true;
|
||||
connected = false;
|
||||
callbackConnect = NULL;
|
||||
callbackDisconnect = NULL;
|
||||
welcomeMsg = strdup(TELNETSPY_WELCOME_MSG);
|
||||
rejectMsg = strdup(TELNETSPY_REJECT_MSG);
|
||||
minBlockSize = TELNETSPY_MIN_BLOCK_SIZE;
|
||||
collectingTime = TELNETSPY_COLLECTING_TIME;
|
||||
maxBlockSize = TELNETSPY_MAX_BLOCK_SIZE;
|
||||
pingTime = TELNETSPY_PING_TIME;
|
||||
pingRef = 0xFFFFFFFF;
|
||||
waitRef = 0xFFFFFFFF;
|
||||
telnetBuf = NULL;
|
||||
bufLen = 0;
|
||||
uint16_t size = TELNETSPY_BUFFER_LEN;
|
||||
while (!setBufferSize(size)) {
|
||||
size = size >> 1;
|
||||
if (size < minBlockSize) {
|
||||
setBufferSize(minBlockSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
debugOutput = TELNETSPY_CAPTURE_OS_PRINT;
|
||||
if (debugOutput) {
|
||||
setDebugOutput(true);
|
||||
}
|
||||
}
|
||||
|
||||
TelnetSpy::~TelnetSpy() {
|
||||
end();
|
||||
}
|
||||
|
||||
// added by proddy
|
||||
void TelnetSpy::disconnectClient() {
|
||||
if (client.connected()) {
|
||||
client.flush();
|
||||
client.stop();
|
||||
}
|
||||
if (connected && (callbackDisconnect != NULL)) {
|
||||
callbackDisconnect();
|
||||
}
|
||||
connected = false;
|
||||
}
|
||||
|
||||
void TelnetSpy::setPort(uint16_t portToUse) {
|
||||
port = portToUse;
|
||||
if (listening) {
|
||||
if (client.connected()) {
|
||||
client.flush();
|
||||
client.stop();
|
||||
}
|
||||
if (connected && (callbackDisconnect != NULL)) {
|
||||
callbackDisconnect();
|
||||
}
|
||||
connected = false;
|
||||
telnetServer->close();
|
||||
delete telnetServer;
|
||||
telnetServer = new WiFiServer(port);
|
||||
if (started) {
|
||||
telnetServer->begin();
|
||||
telnetServer->setNoDelay(bufLen > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetSpy::setWelcomeMsg(const char * msg) {
|
||||
if (welcomeMsg) {
|
||||
free(welcomeMsg);
|
||||
}
|
||||
welcomeMsg = strdup(msg);
|
||||
}
|
||||
|
||||
void TelnetSpy::setRejectMsg(const char * msg) {
|
||||
if (rejectMsg) {
|
||||
free(rejectMsg);
|
||||
}
|
||||
rejectMsg = strdup(msg);
|
||||
}
|
||||
|
||||
void TelnetSpy::setMinBlockSize(uint16_t minSize) {
|
||||
minBlockSize = min(max((uint16_t)1, minSize), maxBlockSize);
|
||||
}
|
||||
|
||||
void TelnetSpy::setCollectingTime(uint16_t colTime) {
|
||||
collectingTime = colTime;
|
||||
}
|
||||
|
||||
void TelnetSpy::setMaxBlockSize(uint16_t maxSize) {
|
||||
maxBlockSize = max(maxSize, minBlockSize);
|
||||
}
|
||||
|
||||
bool TelnetSpy::setBufferSize(uint16_t newSize) {
|
||||
if (telnetBuf && (bufLen == newSize)) {
|
||||
return true;
|
||||
}
|
||||
if (newSize == 0) {
|
||||
bufLen = 0;
|
||||
if (telnetBuf) {
|
||||
free(telnetBuf);
|
||||
telnetBuf = NULL;
|
||||
}
|
||||
if (telnetServer) {
|
||||
telnetServer->setNoDelay(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
newSize = max(newSize, minBlockSize);
|
||||
uint16_t oldBufLen = bufLen;
|
||||
bufLen = newSize;
|
||||
uint16_t tmp;
|
||||
if (!telnetBuf || (bufUsed == 0)) {
|
||||
bufRdIdx = 0;
|
||||
bufWrIdx = 0;
|
||||
bufUsed = 0;
|
||||
} else {
|
||||
if (bufLen < oldBufLen) {
|
||||
if (bufRdIdx < bufWrIdx) {
|
||||
if (bufWrIdx > bufLen) {
|
||||
tmp = min(bufLen, (uint16_t)(bufWrIdx - max(bufLen, bufRdIdx)));
|
||||
memcpy(telnetBuf, &telnetBuf[bufWrIdx - tmp], tmp);
|
||||
bufWrIdx = tmp;
|
||||
if (bufWrIdx > bufRdIdx) {
|
||||
bufRdIdx = bufWrIdx;
|
||||
} else {
|
||||
if (bufRdIdx > bufLen) {
|
||||
bufRdIdx = 0;
|
||||
}
|
||||
}
|
||||
if (bufRdIdx == bufWrIdx) {
|
||||
bufUsed = bufLen;
|
||||
} else {
|
||||
bufUsed = bufWrIdx - bufRdIdx;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bufWrIdx > bufLen) {
|
||||
memcpy(telnetBuf, &telnetBuf[bufWrIdx - bufLen], bufLen);
|
||||
bufRdIdx = 0;
|
||||
bufWrIdx = 0;
|
||||
bufUsed = bufLen;
|
||||
} else {
|
||||
tmp = min(bufLen - bufWrIdx, oldBufLen - bufRdIdx);
|
||||
memcpy(&telnetBuf[bufLen - tmp], &telnetBuf[oldBufLen - tmp], tmp);
|
||||
bufRdIdx = bufLen - tmp;
|
||||
bufUsed = bufWrIdx + tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
char * temp = (char *)realloc(telnetBuf, bufLen);
|
||||
if (!temp) {
|
||||
return false;
|
||||
}
|
||||
telnetBuf = temp;
|
||||
if (telnetBuf && (bufLen > oldBufLen) && (bufRdIdx > bufWrIdx)) {
|
||||
tmp = bufLen - (oldBufLen - bufRdIdx);
|
||||
memcpy(&telnetBuf[tmp], &telnetBuf[bufRdIdx], oldBufLen - bufRdIdx);
|
||||
bufRdIdx = tmp;
|
||||
}
|
||||
if (telnetServer) {
|
||||
telnetServer->setNoDelay(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t TelnetSpy::getBufferSize() {
|
||||
if (!telnetBuf) {
|
||||
return 0;
|
||||
}
|
||||
return bufLen;
|
||||
}
|
||||
|
||||
void TelnetSpy::setStoreOffline(bool store) {
|
||||
storeOffline = store;
|
||||
}
|
||||
|
||||
bool TelnetSpy::getStoreOffline() {
|
||||
return storeOffline;
|
||||
}
|
||||
|
||||
void TelnetSpy::setPingTime(uint16_t pngTime) {
|
||||
pingTime = pngTime;
|
||||
if (pingTime == 0) {
|
||||
pingRef = 0xFFFFFFFF;
|
||||
} else {
|
||||
pingRef = (millis() & 0x7FFFFFF) + pingTime;
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetSpy::setSerial(HardwareSerial * usedSerial) {
|
||||
usedSer = usedSerial;
|
||||
}
|
||||
|
||||
size_t TelnetSpy::write(uint8_t data) {
|
||||
if (telnetBuf) {
|
||||
if (storeOffline || client.connected()) {
|
||||
if (bufUsed == bufLen) {
|
||||
if (client.connected()) {
|
||||
sendBlock();
|
||||
}
|
||||
if (bufUsed == bufLen) {
|
||||
char c;
|
||||
while (bufUsed > 0) {
|
||||
c = pullTelnetBuf();
|
||||
if (c == '\n') {
|
||||
addTelnetBuf('\r');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (peekTelnetBuf() == '\r') {
|
||||
pullTelnetBuf();
|
||||
}
|
||||
}
|
||||
}
|
||||
addTelnetBuf(data);
|
||||
/*
|
||||
if (data == '\n') {
|
||||
addTelnetBuf('\r'); // added by proddy, fix for Windows
|
||||
}
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
if (client.connected()) {
|
||||
client.write(data);
|
||||
}
|
||||
}
|
||||
if (usedSer) {
|
||||
return usedSer->write(data);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// this still needs some work
|
||||
bool TelnetSpy::isSerialAvailable(void) {
|
||||
if (usedSer) {
|
||||
usedSer->write("test");
|
||||
//Wait for four seconds or till data is available on serial, whichever occurs first.
|
||||
while (usedSer->available() == 0 && millis() < 4000)
|
||||
;
|
||||
|
||||
if (usedSer->available() > 0) {
|
||||
(void)usedSer->read(); // We then clear the input buffer
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int TelnetSpy::available(void) {
|
||||
if (usedSer) {
|
||||
int avail = usedSer->available();
|
||||
if (avail > 0) {
|
||||
return avail;
|
||||
}
|
||||
}
|
||||
if (client.connected()) {
|
||||
return telnetAvailable();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TelnetSpy::read(void) {
|
||||
int val;
|
||||
if (usedSer) {
|
||||
val = usedSer->read();
|
||||
if (val != -1) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
if (client.connected()) {
|
||||
if (telnetAvailable()) {
|
||||
val = client.read();
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int TelnetSpy::peek(void) {
|
||||
int val;
|
||||
if (usedSer) {
|
||||
val = usedSer->peek();
|
||||
if (val != -1) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
if (client.connected()) {
|
||||
if (telnetAvailable()) {
|
||||
val = client.peek();
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void TelnetSpy::flush(void) {
|
||||
if (usedSer) {
|
||||
usedSer->flush();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
void TelnetSpy::begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin) {
|
||||
if (usedSer) {
|
||||
usedSer->begin(baud, config, mode, tx_pin);
|
||||
}
|
||||
|
||||
started = true;
|
||||
}
|
||||
|
||||
#else // ESP32
|
||||
|
||||
void TelnetSpy::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert) {
|
||||
if (usedSer) {
|
||||
usedSer->begin(baud, config, rxPin, txPin, invert);
|
||||
}
|
||||
started = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void TelnetSpy::end() {
|
||||
if (debugOutput) {
|
||||
setDebugOutput(false);
|
||||
}
|
||||
if (usedSer) {
|
||||
usedSer->end();
|
||||
}
|
||||
if (client.connected()) {
|
||||
client.flush();
|
||||
client.stop();
|
||||
}
|
||||
if (connected && (callbackDisconnect != NULL)) {
|
||||
callbackDisconnect();
|
||||
}
|
||||
connected = false;
|
||||
telnetServer->close();
|
||||
delete telnetServer;
|
||||
telnetServer = NULL;
|
||||
listening = false;
|
||||
started = false;
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
void TelnetSpy::swap(uint8_t tx_pin) {
|
||||
if (usedSer) {
|
||||
usedSer->swap(tx_pin);
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetSpy::set_tx(uint8_t tx_pin) {
|
||||
if (usedSer) {
|
||||
usedSer->set_tx(tx_pin);
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetSpy::pins(uint8_t tx, uint8_t rx) {
|
||||
if (usedSer) {
|
||||
usedSer->pins(tx, rx);
|
||||
}
|
||||
}
|
||||
|
||||
bool TelnetSpy::isTxEnabled(void) {
|
||||
if (usedSer) {
|
||||
return usedSer->isTxEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TelnetSpy::isRxEnabled(void) {
|
||||
if (usedSer) {
|
||||
return usedSer->isRxEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int TelnetSpy::availableForWrite(void) {
|
||||
if (usedSer) {
|
||||
return min(usedSer->availableForWrite(), bufLen - bufUsed);
|
||||
}
|
||||
return bufLen - bufUsed;
|
||||
}
|
||||
|
||||
TelnetSpy::operator bool() const {
|
||||
if (usedSer) {
|
||||
return (bool)*usedSer;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TelnetSpy::setDebugOutput(bool en) {
|
||||
debugOutput = en;
|
||||
|
||||
if (debugOutput) {
|
||||
actualObject = this;
|
||||
|
||||
#ifdef ESP8266
|
||||
os_install_putc1((void *)TelnetSpy_putc); // Set system printing (os_printf) to TelnetSpy
|
||||
system_set_os_print(true);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
if (actualObject == this) {
|
||||
#ifdef ESP8266
|
||||
system_set_os_print(false);
|
||||
os_install_putc1((void *)TelnetSpy_ignore_putc); // Ignore system printing
|
||||
#endif
|
||||
|
||||
actualObject = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TelnetSpy::baudRate(void) {
|
||||
if (usedSer) {
|
||||
return usedSer->baudRate();
|
||||
}
|
||||
return 115200;
|
||||
}
|
||||
|
||||
void TelnetSpy::sendBlock() {
|
||||
uint16_t len = bufUsed;
|
||||
if (len > maxBlockSize) {
|
||||
len = maxBlockSize;
|
||||
}
|
||||
len = min(len, (uint16_t)(bufLen - bufRdIdx));
|
||||
client.write(&telnetBuf[bufRdIdx], len);
|
||||
bufRdIdx += len;
|
||||
if (bufRdIdx >= bufLen) {
|
||||
bufRdIdx = 0;
|
||||
}
|
||||
bufUsed -= len;
|
||||
if (bufUsed == 0) {
|
||||
bufRdIdx = 0;
|
||||
bufWrIdx = 0;
|
||||
}
|
||||
waitRef = 0xFFFFFFFF;
|
||||
if (pingRef != 0xFFFFFFFF) {
|
||||
pingRef = (millis() & 0x7FFFFFF) + pingTime;
|
||||
if (pingRef > 0x7FFFFFFF) {
|
||||
pingRef -= 0x80000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetSpy::addTelnetBuf(char c) {
|
||||
telnetBuf[bufWrIdx] = c;
|
||||
if (bufUsed == bufLen) {
|
||||
bufRdIdx++;
|
||||
if (bufRdIdx >= bufLen) {
|
||||
bufRdIdx = 0;
|
||||
}
|
||||
} else {
|
||||
bufUsed++;
|
||||
}
|
||||
bufWrIdx++;
|
||||
if (bufWrIdx >= bufLen) {
|
||||
bufWrIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
char TelnetSpy::pullTelnetBuf() {
|
||||
if (bufUsed == 0) {
|
||||
return 0;
|
||||
}
|
||||
char c = telnetBuf[bufRdIdx++];
|
||||
if (bufRdIdx >= bufLen) {
|
||||
bufRdIdx = 0;
|
||||
}
|
||||
bufUsed--;
|
||||
return c;
|
||||
}
|
||||
|
||||
char TelnetSpy::peekTelnetBuf() {
|
||||
if (bufUsed == 0) {
|
||||
return 0;
|
||||
}
|
||||
return telnetBuf[bufRdIdx];
|
||||
}
|
||||
|
||||
int TelnetSpy::telnetAvailable() {
|
||||
int n = client.available();
|
||||
while (n > 0) {
|
||||
if (0xff == client.peek()) { // If esc char for telnet NVT protocol data remove that telegram:
|
||||
client.read(); // Remove esc char
|
||||
n--;
|
||||
if (0xff == client.peek()) { // If esc sequence for 0xFF data byte...
|
||||
return n; // ...return info about available data (just this 0xFF data byte)
|
||||
}
|
||||
client.read(); // Skip the rest of the telegram of the telnet NVT protocol data
|
||||
client.read();
|
||||
n--;
|
||||
n--;
|
||||
} else { // If next char is a normal data byte...
|
||||
return n; // ...return info about available data
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TelnetSpy::isClientConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
void TelnetSpy::setCallbackOnConnect(telnetSpyCallback callback) {
|
||||
callbackConnect = callback;
|
||||
}
|
||||
|
||||
void TelnetSpy::setCallbackOnDisconnect(telnetSpyCallback callback) {
|
||||
callbackDisconnect = callback;
|
||||
}
|
||||
|
||||
void TelnetSpy::serialPrint(char c) {
|
||||
if (usedSer) {
|
||||
usedSer->print(c);
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetSpy::handle() {
|
||||
if (firstMainLoop) {
|
||||
firstMainLoop = false;
|
||||
// Between setup() and loop() the configuration for os_print may be changed so it must be renewed
|
||||
if (debugOutput && (actualObject == this)) {
|
||||
setDebugOutput(true);
|
||||
}
|
||||
}
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
if (!listening) {
|
||||
|
||||
if ((WiFi.status() == WL_DISCONNECTED) && (WiFi.getMode() & WIFI_AP)) {
|
||||
if (usedSer) {
|
||||
usedSer->println("[TELNET] in AP mode"); // added by Proddy
|
||||
}
|
||||
} else if (WiFi.status() != WL_CONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
telnetServer = new WiFiServer(port);
|
||||
telnetServer->begin();
|
||||
telnetServer->setNoDelay(bufLen > 0);
|
||||
listening = true;
|
||||
if (usedSer) {
|
||||
usedSer->println("[TELNET] Telnet server started"); // added by Proddy
|
||||
}
|
||||
}
|
||||
if (telnetServer->hasClient()) {
|
||||
if (client.connected()) {
|
||||
WiFiClient rejectClient = telnetServer->available();
|
||||
if (strlen(rejectMsg) > 0) {
|
||||
rejectClient.write((const uint8_t *)rejectMsg, strlen(rejectMsg));
|
||||
}
|
||||
rejectClient.flush();
|
||||
rejectClient.stop();
|
||||
} else {
|
||||
client = telnetServer->available();
|
||||
if (strlen(welcomeMsg) > 0) {
|
||||
client.write((const uint8_t *)welcomeMsg, strlen(welcomeMsg));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (client.connected()) {
|
||||
if (!connected) {
|
||||
connected = true;
|
||||
if (pingTime != 0) {
|
||||
pingRef = (millis() & 0x7FFFFFF) + pingTime;
|
||||
}
|
||||
if (callbackConnect != NULL) {
|
||||
callbackConnect();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (connected) {
|
||||
connected = false;
|
||||
client.flush();
|
||||
client.stop();
|
||||
pingRef = 0xFFFFFFFF;
|
||||
waitRef = 0xFFFFFFFF;
|
||||
if (callbackDisconnect != NULL) {
|
||||
callbackDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (client.connected() && (bufUsed > 0)) {
|
||||
if (bufUsed >= minBlockSize) {
|
||||
sendBlock();
|
||||
} else {
|
||||
unsigned long m = millis() & 0x7FFFFFF;
|
||||
if (waitRef == 0xFFFFFFFF) {
|
||||
waitRef = m + collectingTime;
|
||||
if (waitRef > 0x7FFFFFFF) {
|
||||
waitRef -= 0x80000000;
|
||||
}
|
||||
} else {
|
||||
if (!((waitRef < 0x20000000) && (m > 0x60000000)) && (m >= waitRef)) {
|
||||
sendBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (client.connected() && (pingRef != 0xFFFFFFFF)) {
|
||||
unsigned long m = millis() & 0x7FFFFFF;
|
||||
if (!((pingRef < 0x20000000) && (m > 0x60000000)) && (m >= pingRef)) {
|
||||
addTelnetBuf(0);
|
||||
sendBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* TELNET SERVER FOR ESP8266 / ESP32
|
||||
* Cloning the serial port via Telnet.
|
||||
*
|
||||
* Written by Wolfgang Mattis (arduino@yasheena.de).
|
||||
* Version 1.1 / September 7, 2018.
|
||||
* MIT license, all text above must be included in any redistribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This module allows you "Debugging over the air". So if you already use
|
||||
* ArduinoOTA this is a helpful extension for wireless development. Use
|
||||
* "TelnetSpy" instead of "Serial" to send data to the serial port and a copy
|
||||
* to a telnet connection. There is a circular buffer which allows to store the
|
||||
* data while the telnet connection is not established. So its possible to
|
||||
* collect data even when the Wifi and Telnet connections are still not
|
||||
* established. Its also possible to create a telnet session only if it is
|
||||
* neccessary: then you will get the already collected data as far as it is
|
||||
* still stored in the circular buffer. Data send from telnet terminal to
|
||||
* ESP8266 / ESP32 will be handled as data received by serial port. It is also
|
||||
* possible to use more than one instance of TelnetSpy, for example to send
|
||||
* control information on the first instance and data dumps on the second
|
||||
* instance.
|
||||
*
|
||||
* USAGE
|
||||
*
|
||||
* Add the following line to your sketch:
|
||||
* #include <TelnetSpy.h>
|
||||
* TelnetSpy LOG;
|
||||
*
|
||||
* Add the following line to your initialisation block ( void setup() ):
|
||||
* LOG.begin();
|
||||
*
|
||||
* Add the following line at the beginning of your main loop ( void loop() ):
|
||||
* LOG.handle();
|
||||
*
|
||||
* Use the following functions of the TelnetSpy object to modify behavior
|
||||
*
|
||||
* Change the port number of this telnet server. If a client is already
|
||||
* connected it will be disconnected.
|
||||
* Default: 23
|
||||
* void setPort(uint16_t portToUse);
|
||||
*
|
||||
* Change the message which will be send to the telnet client after a session
|
||||
* is established.
|
||||
* Default: "Connection established via TelnetSpy.\n"
|
||||
* void setWelcomeMsg(char* msg);
|
||||
*
|
||||
* Change the message which will be send to the telnet client if another
|
||||
* session is already established.
|
||||
* Default: "TelnetSpy: Only one connection possible.\n"
|
||||
* void setRejectMsg(char* msg);
|
||||
*
|
||||
* Change the amount of characters to collect before sending a telnet block.
|
||||
* Default: 64
|
||||
* void setMinBlockSize(uint16_t minSize);
|
||||
*
|
||||
* Change the time (in ms) to wait before sending a telnet block if its size is
|
||||
* less than <minSize> (defined by setMinBlockSize).
|
||||
* Default: 100
|
||||
* void setCollectingTime(uint16_t colTime);
|
||||
*
|
||||
* Change the maximum size of the telnet packets to send.
|
||||
* Default: 512
|
||||
* void setMaxBlockSize(uint16_t maxSize);
|
||||
*
|
||||
* Change the size of the ring buffer. Set it to 0 to disable buffering.
|
||||
* Changing size tries to preserve the already collected data. If the new
|
||||
* buffer size is too small the youngest data will be preserved only. Returns
|
||||
* false if the requested buffer size cannot be set.
|
||||
* Default: 3000
|
||||
* bool setBufferSize(uint16_t newSize);
|
||||
*
|
||||
* This function returns the actual size of the ring buffer.
|
||||
* uint16_t getBufferSize();
|
||||
*
|
||||
* Enable / disable storing new data in the ring buffer if no telnet connection
|
||||
* is established. This function allows you to store important data only. You
|
||||
* can do this by disabling "storeOffline" for sending less important data.
|
||||
* Default: true
|
||||
* void setStoreOffline(bool store);
|
||||
*
|
||||
* Get actual state of storing data when offline.
|
||||
* bool getStoreOffline();
|
||||
*
|
||||
* If no data is sent via TelnetSpy the detection of a disconnected client has
|
||||
* a long timeout. Use setPingTime to define the time (in ms) without traffic
|
||||
* after which a ping (chr(0)) is sent to the telnet client to detect a
|
||||
* disconnect earlier. Use 0 as parameter to disable pings.
|
||||
* Default: 1500
|
||||
* void setPingTime(uint16_t pngTime);
|
||||
*
|
||||
* Set the serial port you want to use with this object (especially for ESP32)
|
||||
* or NULL if no serial port should be used (telnet only).
|
||||
* Default: Serial
|
||||
* void setSerial(HardwareSerial* usedSerial);
|
||||
*
|
||||
* This function returns true, if a telnet client is connected.
|
||||
* bool isClientConnected();
|
||||
*
|
||||
* This function installs a callback function which will be called on every
|
||||
* telnet connect of this object (except rejected connect tries). Use NULL to
|
||||
* remove the callback.
|
||||
* Default: NULL
|
||||
* void setCallbackOnConnect(void (*callback)());
|
||||
*
|
||||
* This function installs a callback function which will be called on every
|
||||
* telnet disconnect of this object (except rejected connect tries). Use NULL
|
||||
* to remove the callback.
|
||||
* Default: NULL
|
||||
* void setCallbackOnDisconnect(void (*callback)());
|
||||
*
|
||||
* HINT
|
||||
*
|
||||
* Add the following lines to your sketch:
|
||||
* #define SERIAL TelnetSpy
|
||||
* //#define SERIAL Serial
|
||||
*
|
||||
* Replace "Serial" with "SERIAL" in your sketch. Now you can switch between
|
||||
* serial only and serial with telnet by changing the comments of the defines
|
||||
* only.
|
||||
*
|
||||
* IMPORTANT
|
||||
*
|
||||
* To connect to the telnet server you have to:
|
||||
* - establish the Wifi connection
|
||||
* - execute "TelnetSpy.begin(WhatEverYouWant);"
|
||||
*
|
||||
* The order is not important.
|
||||
*
|
||||
* All you do with "Serial" you can also do with "TelnetSpy", but remember:
|
||||
* Transfering data also via telnet will need more performance than the serial
|
||||
* port only. So time critical things may be influenced.
|
||||
*
|
||||
* It is not possible to establish more than one telnet connection at the same
|
||||
* time. But its possible to use more than one instance of TelnetSpy.
|
||||
*
|
||||
* If you have problems with low memory you may reduce the value of the define
|
||||
* TELNETSPY_BUFFER_LEN for a smaller ring buffer on initialisation.
|
||||
*
|
||||
* Usage of void setDebugOutput(bool) to enable / disable of capturing of
|
||||
* os_print calls when you have more than one TelnetSpy instance: That
|
||||
* TelnetSpy object will handle this functionality where you used
|
||||
* setDebugOutput at last. On default TelnetSpy has the capturing of OS_print
|
||||
* calls enabled. So if you have more instances the last created instance will
|
||||
* handle the capturing.
|
||||
*/
|
||||
|
||||
#ifndef TelnetSpy_h
|
||||
#define TelnetSpy_h
|
||||
|
||||
#define TELNETSPY_BUFFER_LEN 3000
|
||||
#define TELNETSPY_MIN_BLOCK_SIZE 64
|
||||
#define TELNETSPY_COLLECTING_TIME 100
|
||||
#define TELNETSPY_MAX_BLOCK_SIZE 512
|
||||
#define TELNETSPY_PING_TIME 1500
|
||||
#define TELNETSPY_PORT 23
|
||||
#define TELNETSPY_CAPTURE_OS_PRINT true
|
||||
#define TELNETSPY_WELCOME_MSG "Connection established via Telnet.\n"
|
||||
#define TELNETSPY_REJECT_MSG "Telnet: Only one connection possible.\n"
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#else // ESP32
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#include <WiFiClient.h>
|
||||
|
||||
class TelnetSpy : public Stream {
|
||||
public:
|
||||
TelnetSpy();
|
||||
~TelnetSpy();
|
||||
void handle(void);
|
||||
void setPort(uint16_t portToUse);
|
||||
void setWelcomeMsg(const char * msg);
|
||||
void setRejectMsg(const char * msg);
|
||||
void setMinBlockSize(uint16_t minSize);
|
||||
void setCollectingTime(uint16_t colTime);
|
||||
void setMaxBlockSize(uint16_t maxSize);
|
||||
bool setBufferSize(uint16_t newSize);
|
||||
uint16_t getBufferSize();
|
||||
void setStoreOffline(bool store);
|
||||
bool getStoreOffline();
|
||||
void setPingTime(uint16_t pngTime);
|
||||
void setSerial(HardwareSerial * usedSerial);
|
||||
bool isClientConnected();
|
||||
void serialPrint(char c);
|
||||
|
||||
void disconnectClient(); // added by Proddy
|
||||
typedef std::function<void()> telnetSpyCallback; // added by Proddy
|
||||
void setCallbackOnConnect(telnetSpyCallback callback); // changed by proddy
|
||||
void setCallbackOnDisconnect(telnetSpyCallback callback); // changed by proddy
|
||||
|
||||
// Functions offered by HardwareSerial class:
|
||||
#ifdef ESP8266
|
||||
void begin(unsigned long baud) {
|
||||
begin(baud, SERIAL_8N1, SERIAL_FULL, 1);
|
||||
}
|
||||
void begin(unsigned long baud, SerialConfig config) {
|
||||
begin(baud, config, SERIAL_FULL, 1);
|
||||
}
|
||||
void begin(unsigned long baud, SerialConfig config, SerialMode mode) {
|
||||
begin(baud, config, mode, 1);
|
||||
}
|
||||
void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin);
|
||||
#else // ESP32
|
||||
void begin(unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false);
|
||||
#endif
|
||||
void end();
|
||||
#ifdef ESP8266
|
||||
void swap() {
|
||||
swap(1);
|
||||
}
|
||||
void swap(uint8_t tx_pin);
|
||||
void set_tx(uint8_t tx_pin);
|
||||
void pins(uint8_t tx, uint8_t rx);
|
||||
bool isTxEnabled(void);
|
||||
bool isRxEnabled(void);
|
||||
#endif
|
||||
int available(void) override;
|
||||
int peek(void) override;
|
||||
int read(void) override;
|
||||
int availableForWrite(void);
|
||||
void flush(void) override;
|
||||
size_t write(uint8_t) override;
|
||||
inline size_t write(unsigned long n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(long n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(unsigned int n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(int n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
using Print::write;
|
||||
operator bool() const;
|
||||
void setDebugOutput(bool);
|
||||
uint32_t baudRate(void);
|
||||
|
||||
bool isSerialAvailable(void);
|
||||
|
||||
protected:
|
||||
void sendBlock(void);
|
||||
void addTelnetBuf(char c);
|
||||
char pullTelnetBuf();
|
||||
char peekTelnetBuf();
|
||||
int telnetAvailable();
|
||||
WiFiServer * telnetServer;
|
||||
WiFiClient client;
|
||||
uint16_t port;
|
||||
HardwareSerial * usedSer;
|
||||
bool storeOffline;
|
||||
bool started;
|
||||
bool listening;
|
||||
bool firstMainLoop;
|
||||
unsigned long waitRef;
|
||||
unsigned long pingRef;
|
||||
uint16_t pingTime;
|
||||
char * welcomeMsg;
|
||||
char * rejectMsg;
|
||||
uint16_t minBlockSize;
|
||||
uint16_t collectingTime;
|
||||
uint16_t maxBlockSize;
|
||||
bool debugOutput;
|
||||
char * telnetBuf;
|
||||
uint16_t bufLen;
|
||||
uint16_t bufUsed;
|
||||
uint16_t bufRdIdx;
|
||||
uint16_t bufWrIdx;
|
||||
bool connected;
|
||||
|
||||
telnetSpyCallback callbackConnect; // added by proddy
|
||||
telnetSpyCallback callbackDisconnect; // added by proddy
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user