Compare commits
No commits in common. "74b0bf810cd3f344d576aabb8fa558f9e206095a" and "e108dd919ab273f55b3e63746dfa52c7466c255b" have entirely different histories.
74b0bf810c
...
e108dd919a
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ const Pin I2C_scl,
|
|||||||
const Pin SPI_mosi,
|
const Pin SPI_mosi,
|
||||||
const Pin SPI_miso,
|
const Pin SPI_miso,
|
||||||
const Pin SPI_clk,
|
const Pin SPI_clk,
|
||||||
const uint32_t spiSpeed
|
const SPISettings spiSpeed
|
||||||
):
|
):
|
||||||
_I2C_sda(I2C_sda == DEFAULT_PIN ? GPIO_4_SDA : I2C_sda),
|
_I2C_sda(I2C_sda == DEFAULT_PIN ? GPIO_4_SDA : I2C_sda),
|
||||||
_I2C_scl(I2C_scl == DEFAULT_PIN ? GPIO_5_SCL : I2C_scl),
|
_I2C_scl(I2C_scl == DEFAULT_PIN ? GPIO_5_SCL : I2C_scl),
|
||||||
@ -75,7 +75,7 @@ uint16_t BoardConfig::getRTCFlashAddress() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t BoardConfig::getSPISpeed() const
|
SPISettings BoardConfig::getSPISpeed() const
|
||||||
{
|
{
|
||||||
return _SPISpeed;
|
return _SPISpeed;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ class BoardConfig
|
|||||||
const Pin SPI_mosi = GPIO_13_MOSI,
|
const Pin SPI_mosi = GPIO_13_MOSI,
|
||||||
const Pin SPI_miso = GPIO_12_MISO,
|
const Pin SPI_miso = GPIO_12_MISO,
|
||||||
const Pin SPI_clk = GPIO_14_CLK,
|
const Pin SPI_clk = GPIO_14_CLK,
|
||||||
const uint32_t spiSpeed = SPI_FULL_SPEED
|
const SPISettings spiSpeed = SPI_FULL_SPEED
|
||||||
);
|
);
|
||||||
|
|
||||||
Pin getI2C_sda() const;
|
Pin getI2C_sda() const;
|
||||||
@ -37,7 +37,7 @@ class BoardConfig
|
|||||||
uint16_t getI2C_IOExpanderAddress() const;
|
uint16_t getI2C_IOExpanderAddress() const;
|
||||||
uint16_t getRTCFlashAddress() const;
|
uint16_t getRTCFlashAddress() const;
|
||||||
|
|
||||||
uint32_t getSPISpeed() const;
|
SPISettings getSPISpeed() const;
|
||||||
|
|
||||||
uint16_t getScreenWidth() const;
|
uint16_t getScreenWidth() const;
|
||||||
uint16_t getScreenHeight() const;
|
uint16_t getScreenHeight() const;
|
||||||
@ -58,7 +58,7 @@ class BoardConfig
|
|||||||
const uint16_t _I2C_RTCFlashAddress;
|
const uint16_t _I2C_RTCFlashAddress;
|
||||||
|
|
||||||
//3) SPI Speed
|
//3) SPI Speed
|
||||||
const uint32_t _SPISpeed;
|
const SPISettings _SPISpeed;
|
||||||
|
|
||||||
//4) Miscellaneous
|
//4) Miscellaneous
|
||||||
const uint16_t _screenWidth;
|
const uint16_t _screenWidth;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "SDCardManager.h"
|
#include "SDCardManager.h"
|
||||||
|
|
||||||
SDCardManager::SDCardManager(const Pin csPin, uint32_t cfg) : _csPin(csPin), _spiCfg(cfg), _mounted(false)
|
SDCardManager::SDCardManager(const Pin csPin, SPISettings cfg) : _csPin(csPin), _spiCfg(cfg), _mounted(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class SDCardManager : public SDClass
|
|||||||
{
|
{
|
||||||
friend class SAB;
|
friend class SAB;
|
||||||
public:
|
public:
|
||||||
SDCardManager(const Pin csPin, uint32_t cfg);
|
SDCardManager(const Pin csPin, SPISettings cfg);
|
||||||
double getSize(const SizeUnit sizeUnit = GBYTE);
|
double getSize(const SizeUnit sizeUnit = GBYTE);
|
||||||
boolean mountSD();
|
boolean mountSD();
|
||||||
void unMountSD();
|
void unMountSD();
|
||||||
@ -27,7 +27,7 @@ class SDCardManager : public SDClass
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const Pin _csPin;
|
const Pin _csPin;
|
||||||
uint32_t _spiCfg;
|
SPISettings _spiCfg;
|
||||||
boolean _mounted;
|
boolean _mounted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,11 @@ const int chipSelect = 4;
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Open serial communications and wait for port to open:
|
// Open serial communications and wait for port to open:
|
||||||
Serial.begin(115200);
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
|
; // wait for serial port to connect. Needed for Leonardo only
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Serial.print("Initializing SD card...");
|
Serial.print("Initializing SD card...");
|
||||||
|
|
||||||
|
@ -27,7 +27,11 @@ const int chipSelect = 4;
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Open serial communications and wait for port to open:
|
// Open serial communications and wait for port to open:
|
||||||
Serial.begin(115200);
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
|
; // wait for serial port to connect. Needed for Leonardo only
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Serial.print("Initializing SD card...");
|
Serial.print("Initializing SD card...");
|
||||||
|
|
||||||
|
@ -24,7 +24,11 @@ File myFile;
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Open serial communications and wait for port to open:
|
// Open serial communications and wait for port to open:
|
||||||
Serial.begin(115200);
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
|
; // wait for serial port to connect. Needed for Leonardo only
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Serial.print("Initializing SD card...");
|
Serial.print("Initializing SD card...");
|
||||||
|
|
||||||
|
@ -25,7 +25,11 @@ File myFile;
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Open serial communications and wait for port to open:
|
// Open serial communications and wait for port to open:
|
||||||
Serial.begin(115200);
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
|
; // wait for serial port to connect. Needed for Leonardo only
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Serial.print("Initializing SD card...");
|
Serial.print("Initializing SD card...");
|
||||||
|
|
||||||
|
@ -29,6 +29,9 @@ File root;
|
|||||||
void setup() {
|
void setup() {
|
||||||
// Open serial communications and wait for port to open:
|
// Open serial communications and wait for port to open:
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
while (!Serial) {
|
||||||
|
; // wait for serial port to connect. Needed for Leonardo only
|
||||||
|
}
|
||||||
|
|
||||||
Serial.print("Initializing SD card...");
|
Serial.print("Initializing SD card...");
|
||||||
|
|
||||||
@ -68,12 +71,11 @@ void printDirectory(File dir, int numTabs) {
|
|||||||
// files have sizes, directories do not
|
// files have sizes, directories do not
|
||||||
Serial.print("\t\t");
|
Serial.print("\t\t");
|
||||||
Serial.print(entry.size(), DEC);
|
Serial.print(entry.size(), DEC);
|
||||||
time_t cr = entry.getCreationTime();
|
Serial.print("\t\t");
|
||||||
time_t lw = entry.getLastWrite();
|
time_t ft = entry.getLastWrite();
|
||||||
struct tm * tmstruct = localtime(&cr);
|
struct tm *tm = localtime(&ft);
|
||||||
Serial.printf("\tCREATION: %d-%02d-%02d %02d:%02d:%02d", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
|
// US format. Feel free to convert to your own locale...
|
||||||
tmstruct = localtime(&lw);
|
Serial.printf("%02d-%02d-%02d %02d:%02d:%02d\n", tm->tm_mon + 1, tm->tm_mday, tm->tm_year % 100, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
Serial.printf("\tLAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
|
|
||||||
}
|
}
|
||||||
entry.close();
|
entry.close();
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,11 @@ close KEYWORD2
|
|||||||
seek KEYWORD2
|
seek KEYWORD2
|
||||||
position KEYWORD2
|
position KEYWORD2
|
||||||
size KEYWORD2
|
size KEYWORD2
|
||||||
|
rename KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
#######################################
|
#######################################
|
||||||
FILE_READ LITERAL1
|
FILE_READ LITERAL1
|
||||||
FILE_WRITE LITERAL1
|
FILE_WRITE LITERAL1
|
||||||
|
FILE_READWRITE LITERAL1
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name=SD
|
name=SD(esp8266)
|
||||||
version=2.0.0
|
version=2.0.0
|
||||||
author=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
author=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||||
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
class SDClass {
|
class SDClass {
|
||||||
public:
|
public:
|
||||||
boolean begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED) {
|
boolean begin(uint8_t csPin, SPISettings cfg = SPI_HALF_SPEED) {
|
||||||
SDFS.setConfig(SDFSConfig(csPin, cfg));
|
SDFS.setConfig(SDFSConfig(csPin, cfg));
|
||||||
return (boolean)SDFS.begin();
|
return (boolean)SDFS.begin();
|
||||||
}
|
}
|
||||||
@ -69,18 +69,6 @@ public:
|
|||||||
return (boolean)SDFS.exists(filepath.c_str());
|
return (boolean)SDFS.exists(filepath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rename(const char* filepathfrom, const char* filepathto) {
|
|
||||||
return (boolean)SDFS.rename(filepathfrom, filepathto);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool info64(FSInfo64& info) {
|
|
||||||
return (boolean)SDFS.info64(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean rename(const String &filepathfrom, const String &filepathto) {
|
|
||||||
return (boolean)rename(filepathfrom.c_str(), filepathto.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean mkdir(const char *filepath) {
|
boolean mkdir(const char *filepath) {
|
||||||
return (boolean)SDFS.mkdir(filepath);
|
return (boolean)SDFS.mkdir(filepath);
|
||||||
}
|
}
|
||||||
@ -105,6 +93,14 @@ public:
|
|||||||
return rmdir(filepath.c_str());
|
return rmdir(filepath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rename(const char* pathFrom, const char* pathTo) {
|
||||||
|
return (boolean)SDFS.rename(pathFrom, pathTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool info64(FSInfo64& info) {
|
||||||
|
return (boolean)SDFS.info64(info);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t type() {
|
uint8_t type() {
|
||||||
sdfs::SDFSImpl* sd = static_cast<sdfs::SDFSImpl*>(SDFS.getImpl().get());
|
sdfs::SDFSImpl* sd = static_cast<sdfs::SDFSImpl*>(SDFS.getImpl().get());
|
||||||
return sd->type();
|
return sd->type();
|
||||||
@ -188,7 +184,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Expose FatStructs.h helpers for MS-DOS date/time for use with dateTimeCallback
|
// Expose FatStructs.h helpers for MSDOS date/time for use with dateTimeCallback
|
||||||
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
|
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
|
||||||
return (year - 1980) << 9 | month << 5 | day;
|
return (year - 1980) << 9 | month << 5 | day;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
#include "SDFS.h"
|
#include "SDFS.h"
|
||||||
|
#include "SDFSFormatter.h"
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
||||||
using namespace fs;
|
using namespace fs;
|
||||||
@ -36,9 +37,6 @@ FS SDFS = FS(FSImplPtr(new sdfs::SDFSImpl()));
|
|||||||
|
|
||||||
namespace sdfs {
|
namespace sdfs {
|
||||||
|
|
||||||
// Required to be global because SDFAT doesn't allow a this pointer in it's own time call
|
|
||||||
time_t (*__sdfs_timeCallback)(void) = nullptr;
|
|
||||||
|
|
||||||
FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode)
|
FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode)
|
||||||
{
|
{
|
||||||
if (!_mounted) {
|
if (!_mounted) {
|
||||||
@ -64,13 +62,13 @@ FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode acces
|
|||||||
}
|
}
|
||||||
free(pathStr);
|
free(pathStr);
|
||||||
}
|
}
|
||||||
sdfat::File32 fd = _fs.open(path, flags);
|
sdfat::File fd = _fs.open(path, flags);
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
DEBUGV("SDFSImpl::openFile: fd=%p path=`%s` openMode=%d accessMode=%d",
|
DEBUGV("SDFSImpl::openFile: fd=%p path=`%s` openMode=%d accessMode=%d",
|
||||||
&fd, path, openMode, accessMode);
|
&fd, path, openMode, accessMode);
|
||||||
return FileImplPtr();
|
return FileImplPtr();
|
||||||
}
|
}
|
||||||
auto sharedFd = std::make_shared<sdfat::File32>(fd);
|
auto sharedFd = std::make_shared<sdfat::File>(fd);
|
||||||
return std::make_shared<SDFSFileImpl>(this, sharedFd, path);
|
return std::make_shared<SDFSFileImpl>(this, sharedFd, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +88,7 @@ DirImplPtr SDFSImpl::openDir(const char* path)
|
|||||||
}
|
}
|
||||||
// At this point we have a name of "/blah/blah/blah" or "blah" or ""
|
// At this point we have a name of "/blah/blah/blah" or "blah" or ""
|
||||||
// If that references a directory, just open it and we're done.
|
// If that references a directory, just open it and we're done.
|
||||||
sdfat::File32 dirFile;
|
sdfat::File dirFile;
|
||||||
const char *filter = "";
|
const char *filter = "";
|
||||||
if (!pathStr[0]) {
|
if (!pathStr[0]) {
|
||||||
// openDir("") === openDir("/")
|
// openDir("") === openDir("/")
|
||||||
@ -135,7 +133,7 @@ DirImplPtr SDFSImpl::openDir(const char* path)
|
|||||||
DEBUGV("SDFSImpl::openDir: path=`%s`\n", path);
|
DEBUGV("SDFSImpl::openDir: path=`%s`\n", path);
|
||||||
return DirImplPtr();
|
return DirImplPtr();
|
||||||
}
|
}
|
||||||
auto sharedDir = std::make_shared<sdfat::File32>(dirFile);
|
auto sharedDir = std::make_shared<sdfat::File>(dirFile);
|
||||||
auto ret = std::make_shared<SDFSDirImpl>(filter, this, sharedDir, pathStr);
|
auto ret = std::make_shared<SDFSDirImpl>(filter, this, sharedDir, pathStr);
|
||||||
free(pathStr);
|
free(pathStr);
|
||||||
return ret;
|
return ret;
|
||||||
@ -145,18 +143,12 @@ bool SDFSImpl::format() {
|
|||||||
if (_mounted) {
|
if (_mounted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sdfat::SdCardFactory cardFactory;
|
SDFSFormatter formatter;
|
||||||
sdfat::SdCard* card = cardFactory.newCard(sdfat::SdSpiConfig(_cfg._csPin, DEDICATED_SPI, _cfg._spiSettings));
|
bool ret = formatter.format(&_fs, _cfg._csPin, _cfg._spiSettings);
|
||||||
if (!card || card->errorCode()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sdfat::FatFormatter fatFormatter;
|
|
||||||
uint8_t *sectorBuffer = new uint8_t[512];
|
|
||||||
bool ret = fatFormatter.format(card, sectorBuffer, nullptr);
|
|
||||||
delete[] sectorBuffer;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t (*SDFSImpl::timeCallback)(void) = nullptr;
|
||||||
|
|
||||||
}; // namespace sdfs
|
}; // namespace sdfs
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class SDFSConfig : public FSConfig
|
|||||||
public:
|
public:
|
||||||
static constexpr uint32_t FSId = 0x53444653;
|
static constexpr uint32_t FSId = 0x53444653;
|
||||||
|
|
||||||
SDFSConfig(uint8_t csPin = 4, uint32_t spi = SD_SCK_MHZ(10)) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi) { }
|
SDFSConfig(uint8_t csPin = 4, SPISettings spi = SD_SCK_MHZ(10)) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi) { }
|
||||||
|
|
||||||
SDFSConfig setAutoFormat(bool val = true) {
|
SDFSConfig setAutoFormat(bool val = true) {
|
||||||
_autoFormat = val;
|
_autoFormat = val;
|
||||||
@ -57,7 +57,7 @@ public:
|
|||||||
_csPin = pin;
|
_csPin = pin;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
SDFSConfig setSPI(uint32_t spi) {
|
SDFSConfig setSPI(SPISettings spi) {
|
||||||
_spiSettings = spi;
|
_spiSettings = spi;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ public:
|
|||||||
// Inherit _type and _autoFormat
|
// Inherit _type and _autoFormat
|
||||||
uint8_t _csPin;
|
uint8_t _csPin;
|
||||||
uint8_t _part;
|
uint8_t _part;
|
||||||
uint32_t _spiSettings;
|
SPISettings _spiSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SDFSImpl : public FSImpl
|
class SDFSImpl : public FSImpl
|
||||||
@ -97,11 +97,11 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
info.maxOpenFiles = 999; // TODO - not valid
|
info.maxOpenFiles = 999; // TODO - not valid
|
||||||
info.blockSize = _fs.vol()->sectorsPerCluster() * _fs.vol()->bytesPerSector();
|
info.blockSize = _fs.vol()->blocksPerCluster() * 512;
|
||||||
info.pageSize = 0; // TODO ?
|
info.pageSize = 0; // TODO ?
|
||||||
info.maxPathLength = 255; // TODO ?
|
info.maxPathLength = 255; // TODO ?
|
||||||
info.totalBytes =_fs.vol()->clusterCount() * info.blockSize;
|
info.totalBytes =_fs.vol()->volumeBlockCount() * 512LL;
|
||||||
info.usedBytes = info.totalBytes - (_fs.vol()->freeClusterCount() * _fs.vol()->sectorsPerCluster() * _fs.vol()->bytesPerSector());
|
info.usedBytes = info.totalBytes - (_fs.vol()->freeClusterCount() * _fs.vol()->blocksPerCluster() * 512LL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,14 +149,14 @@ public:
|
|||||||
|
|
||||||
bool begin() override {
|
bool begin() override {
|
||||||
if (_mounted) {
|
if (_mounted) {
|
||||||
return true;
|
end();
|
||||||
}
|
}
|
||||||
_mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings);
|
_mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings);
|
||||||
if (!_mounted && _cfg._autoFormat) {
|
if (!_mounted && _cfg._autoFormat) {
|
||||||
format();
|
format();
|
||||||
_mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings);
|
_mounted = _fs.begin(_cfg._csPin, _cfg._spiSettings);
|
||||||
}
|
}
|
||||||
sdfat::FsDateTime::setCallback(dateTimeCB);
|
sdfat::SdFile::dateTimeCallback(dateTimeCB);
|
||||||
return _mounted;
|
return _mounted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ public:
|
|||||||
return _fs.vol()->fatType();
|
return _fs.vol()->fatType();
|
||||||
}
|
}
|
||||||
size_t blocksPerCluster() {
|
size_t blocksPerCluster() {
|
||||||
return _fs.vol()->sectorsPerCluster();
|
return _fs.vol()->blocksPerCluster();
|
||||||
}
|
}
|
||||||
size_t totalClusters() {
|
size_t totalClusters() {
|
||||||
return _fs.vol()->clusterCount();
|
return _fs.vol()->clusterCount();
|
||||||
@ -185,7 +185,7 @@ public:
|
|||||||
return (totalClusters() / blocksPerCluster());
|
return (totalClusters() / blocksPerCluster());
|
||||||
}
|
}
|
||||||
size_t clusterSize() {
|
size_t clusterSize() {
|
||||||
return blocksPerCluster() * _fs.vol()->bytesPerSector();
|
return blocksPerCluster() * 512; // 512b block size
|
||||||
}
|
}
|
||||||
size_t size() {
|
size_t size() {
|
||||||
return (clusterSize() * totalClusters());
|
return (clusterSize() * totalClusters());
|
||||||
@ -205,26 +205,24 @@ public:
|
|||||||
return mktime(&tiempo);
|
return mktime(&tiempo);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setTimeCallback(time_t (*cb)(void)) override {
|
|
||||||
extern time_t (*__sdfs_timeCallback)(void);
|
|
||||||
__sdfs_timeCallback = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Because SdFat has a single, global setting for this we can only use a
|
// Because SdFat has a single, global setting for this we can only use a
|
||||||
// static member of our class to return the time/date.
|
// static member of our class to return the time/date. However, since
|
||||||
|
// this is static, we can't see the time callback variable. Punt for now,
|
||||||
|
// using time(NULL) as the best we can do.
|
||||||
static void dateTimeCB(uint16_t *dosYear, uint16_t *dosTime) {
|
static void dateTimeCB(uint16_t *dosYear, uint16_t *dosTime) {
|
||||||
time_t now;
|
|
||||||
extern time_t (*__sdfs_timeCallback)(void);
|
time_t now = (timeCallback == nullptr) ? time(nullptr) : (*timeCallback)();
|
||||||
if (__sdfs_timeCallback) {
|
//time_t now = time(nullptr);
|
||||||
now = __sdfs_timeCallback();
|
|
||||||
} else {
|
|
||||||
now = time(nullptr);
|
|
||||||
}
|
|
||||||
struct tm *tiempo = localtime(&now);
|
struct tm *tiempo = localtime(&now);
|
||||||
*dosYear = ((tiempo->tm_year - 80) << 9) | ((tiempo->tm_mon + 1) << 5) | tiempo->tm_mday;
|
*dosYear = ((tiempo->tm_year - 80) << 9) | ((tiempo->tm_mon + 1) << 5) | tiempo->tm_mday;
|
||||||
*dosTime = (tiempo->tm_hour << 11) | (tiempo->tm_min << 5) | tiempo->tm_sec;
|
*dosTime = (tiempo->tm_hour << 11) | (tiempo->tm_min << 5) | tiempo->tm_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void setTimeCallback(time_t (*cb)(void))
|
||||||
|
{
|
||||||
|
timeCallback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class SDFileImpl;
|
friend class SDFileImpl;
|
||||||
friend class SDFSDirImpl;
|
friend class SDFSDirImpl;
|
||||||
@ -234,7 +232,6 @@ protected:
|
|||||||
return &_fs;
|
return &_fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t _getFlags(OpenMode openMode, AccessMode accessMode) {
|
static uint8_t _getFlags(OpenMode openMode, AccessMode accessMode) {
|
||||||
uint8_t mode = 0;
|
uint8_t mode = 0;
|
||||||
if (openMode & OM_CREATE) {
|
if (openMode & OM_CREATE) {
|
||||||
@ -258,13 +255,16 @@ protected:
|
|||||||
sdfat::SdFat _fs;
|
sdfat::SdFat _fs;
|
||||||
SDFSConfig _cfg;
|
SDFSConfig _cfg;
|
||||||
bool _mounted;
|
bool _mounted;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static time_t (*timeCallback)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SDFSFileImpl : public FileImpl
|
class SDFSFileImpl : public FileImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SDFSFileImpl(SDFSImpl *fs, std::shared_ptr<sdfat::File32> fd, const char *name)
|
SDFSFileImpl(SDFSImpl *fs, std::shared_ptr<sdfat::File> fd, const char *name)
|
||||||
: _fs(fs), _fd(fd), _opened(true)
|
: _fs(fs), _fd(fd), _opened(true)
|
||||||
{
|
{
|
||||||
_name = std::shared_ptr<char>(new char[strlen(name) + 1], std::default_delete<char[]>());
|
_name = std::shared_ptr<char>(new char[strlen(name) + 1], std::default_delete<char[]>());
|
||||||
@ -277,17 +277,12 @@ public:
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int availableForWrite() override
|
|
||||||
{
|
|
||||||
return _opened ? _fd->availableSpaceForWrite() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const uint8_t *buf, size_t size) override
|
size_t write(const uint8_t *buf, size_t size) override
|
||||||
{
|
{
|
||||||
return _opened ? _fd->write(buf, size) : -1;
|
return _opened ? _fd->write(buf, size) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read(uint8_t* buf, size_t size) override
|
size_t read(uint8_t* buf, size_t size) override
|
||||||
{
|
{
|
||||||
return _opened ? _fd->read(buf, size) : -1;
|
return _opened ? _fd->read(buf, size) : -1;
|
||||||
}
|
}
|
||||||
@ -295,6 +290,7 @@ public:
|
|||||||
void flush() override
|
void flush() override
|
||||||
{
|
{
|
||||||
if (_opened) {
|
if (_opened) {
|
||||||
|
_fd->flush();
|
||||||
_fd->sync();
|
_fd->sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,15 +370,15 @@ public:
|
|||||||
|
|
||||||
bool isDirectory() const override
|
bool isDirectory() const override
|
||||||
{
|
{
|
||||||
return _opened ? _fd->isDir() : false;
|
return _opened ? _fd->isDirectory() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t getLastWrite() override {
|
time_t getLastWrite() override {
|
||||||
time_t ftime = 0;
|
time_t ftime = 0;
|
||||||
if (_opened && _fd) {
|
if (_opened && _fd) {
|
||||||
sdfat::DirFat_t tmp;
|
sdfat::dir_t tmp;
|
||||||
if (_fd.get()->dirEntry(&tmp)) {
|
if (_fd.get()->dirEntry(&tmp)) {
|
||||||
ftime = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.modifyDate, *(uint16_t*)tmp.modifyTime);
|
ftime = SDFSImpl::FatToTimeT(tmp.lastWriteDate, tmp.lastWriteTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ftime;
|
return ftime;
|
||||||
@ -391,17 +387,19 @@ public:
|
|||||||
time_t getCreationTime() override {
|
time_t getCreationTime() override {
|
||||||
time_t ftime = 0;
|
time_t ftime = 0;
|
||||||
if (_opened && _fd) {
|
if (_opened && _fd) {
|
||||||
sdfat::DirFat_t tmp;
|
sdfat::dir_t tmp;
|
||||||
if (_fd.get()->dirEntry(&tmp)) {
|
if (_fd.get()->dirEntry(&tmp)) {
|
||||||
ftime = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.createDate, *(uint16_t*)tmp.createTime);
|
ftime = SDFSImpl::FatToTimeT(tmp.creationDate, tmp.creationTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ftime;
|
return ftime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SDFSImpl* _fs;
|
SDFSImpl* _fs;
|
||||||
std::shared_ptr<sdfat::File32> _fd;
|
std::shared_ptr<sdfat::File> _fd;
|
||||||
std::shared_ptr<char> _name;
|
std::shared_ptr<char> _name;
|
||||||
bool _opened;
|
bool _opened;
|
||||||
};
|
};
|
||||||
@ -409,7 +407,7 @@ protected:
|
|||||||
class SDFSDirImpl : public DirImpl
|
class SDFSDirImpl : public DirImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SDFSDirImpl(const String& pattern, SDFSImpl* fs, std::shared_ptr<sdfat::File32> dir, const char *dirPath = nullptr)
|
SDFSDirImpl(const String& pattern, SDFSImpl* fs, std::shared_ptr<sdfat::File> dir, const char *dirPath = nullptr)
|
||||||
: _pattern(pattern), _fs(fs), _dir(dir), _valid(false), _dirPath(nullptr)
|
: _pattern(pattern), _fs(fs), _dir(dir), _valid(false), _dirPath(nullptr)
|
||||||
{
|
{
|
||||||
if (dirPath) {
|
if (dirPath) {
|
||||||
@ -484,17 +482,17 @@ public:
|
|||||||
{
|
{
|
||||||
const int n = _pattern.length();
|
const int n = _pattern.length();
|
||||||
do {
|
do {
|
||||||
sdfat::File32 file;
|
sdfat::File file;
|
||||||
file.openNext(_dir.get(), sdfat::O_READ);
|
file.openNext(_dir.get(), sdfat::O_READ);
|
||||||
if (file) {
|
if (file) {
|
||||||
_valid = 1;
|
_valid = 1;
|
||||||
_size = file.fileSize();
|
_size = file.fileSize();
|
||||||
_isFile = file.isFile();
|
_isFile = file.isFile();
|
||||||
_isDirectory = file.isDir();
|
_isDirectory = file.isDirectory();
|
||||||
sdfat::DirFat_t tmp;
|
sdfat::dir_t tmp;
|
||||||
if (file.dirEntry(&tmp)) {
|
if (file.dirEntry(&tmp)) {
|
||||||
_time = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.modifyDate, *(uint16_t*)tmp.modifyTime);
|
_time = SDFSImpl::FatToTimeT(tmp.lastWriteDate, tmp.lastWriteTime);
|
||||||
_creation = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.createDate, *(uint16_t*)tmp.createTime);
|
_creation = SDFSImpl::FatToTimeT(tmp.creationDate, tmp.creationTime);
|
||||||
} else {
|
} else {
|
||||||
_time = 0;
|
_time = 0;
|
||||||
_creation = 0;
|
_creation = 0;
|
||||||
@ -518,7 +516,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
String _pattern;
|
String _pattern;
|
||||||
SDFSImpl* _fs;
|
SDFSImpl* _fs;
|
||||||
std::shared_ptr<sdfat::File32> _dir;
|
std::shared_ptr<sdfat::File> _dir;
|
||||||
bool _valid;
|
bool _valid;
|
||||||
char _lfn[64];
|
char _lfn[64];
|
||||||
time_t _time;
|
time_t _time;
|
||||||
|
405
src/libs/SDFS/src/SDFSFormatter.h
Normal file
405
src/libs/SDFS/src/SDFSFormatter.h
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
SDFSFormatter.cpp - Formatter for SdFat SD cards
|
||||||
|
Copyright (c) 2019 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
A C++ implementation of the SdFat/examples/SdFormatter sketch:
|
||||||
|
| Copyright (c) 2011-2018 Bill Greiman
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SDFSFORMATTER_H
|
||||||
|
#define _SDFSFORMATTER_H
|
||||||
|
|
||||||
|
#include "SDFS.h"
|
||||||
|
#include <FS.h>
|
||||||
|
#include <PolledTimeout.h>
|
||||||
|
|
||||||
|
namespace sdfs {
|
||||||
|
|
||||||
|
class SDFSFormatter {
|
||||||
|
private:
|
||||||
|
// Taken from main FS object
|
||||||
|
sdfat::Sd2Card *card;
|
||||||
|
sdfat::cache_t *cache;
|
||||||
|
|
||||||
|
uint32_t cardSizeBlocks;
|
||||||
|
uint32_t cardCapacityMB;
|
||||||
|
|
||||||
|
|
||||||
|
// MBR information
|
||||||
|
uint8_t partType;
|
||||||
|
uint32_t relSector;
|
||||||
|
uint32_t partSize;
|
||||||
|
|
||||||
|
// Fake disk geometry
|
||||||
|
uint8_t numberOfHeads;
|
||||||
|
uint8_t sectorsPerTrack;
|
||||||
|
|
||||||
|
// FAT parameters
|
||||||
|
uint16_t reservedSectors;
|
||||||
|
uint8_t sectorsPerCluster;
|
||||||
|
uint32_t fatStart;
|
||||||
|
uint32_t fatSize;
|
||||||
|
uint32_t dataStart;
|
||||||
|
|
||||||
|
uint8_t writeCache(uint32_t lbn) {
|
||||||
|
return card->writeBlock(lbn, cache->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearCache(uint8_t addSig) {
|
||||||
|
memset(cache, 0, sizeof(*cache));
|
||||||
|
if (addSig) {
|
||||||
|
cache->mbr.mbrSig0 = sdfat::BOOTSIG0;
|
||||||
|
cache->mbr.mbrSig1 = sdfat::BOOTSIG1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool clearFatDir(uint32_t bgn, uint32_t count) {
|
||||||
|
clearCache(false);
|
||||||
|
if (!card->writeStart(bgn, count)) {
|
||||||
|
DEBUGV("SDFS: Clear FAT/DIR writeStart failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
esp8266::polledTimeout::periodicFastMs timeToYield(5); // Yield every 5ms of runtime
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
if (timeToYield) {
|
||||||
|
delay(0); // WDT feed
|
||||||
|
}
|
||||||
|
if (!card->writeData(cache->data)) {
|
||||||
|
DEBUGV("SDFS: Clear FAT/DIR writeData failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!card->writeStop()) {
|
||||||
|
DEBUGV("SDFS: Clear FAT/DIR writeStop failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t lbnToCylinder(uint32_t lbn) {
|
||||||
|
return lbn / (numberOfHeads * sectorsPerTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lbnToHead(uint32_t lbn) {
|
||||||
|
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lbnToSector(uint32_t lbn) {
|
||||||
|
return (lbn % sectorsPerTrack) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeMbr() {
|
||||||
|
clearCache(true);
|
||||||
|
sdfat::part_t* p = cache->mbr.part;
|
||||||
|
p->boot = 0;
|
||||||
|
uint16_t c = lbnToCylinder(relSector);
|
||||||
|
if (c > 1023) {
|
||||||
|
DEBUGV("SDFS: MBR CHS");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p->beginCylinderHigh = c >> 8;
|
||||||
|
p->beginCylinderLow = c & 0XFF;
|
||||||
|
p->beginHead = lbnToHead(relSector);
|
||||||
|
p->beginSector = lbnToSector(relSector);
|
||||||
|
p->type = partType;
|
||||||
|
uint32_t endLbn = relSector + partSize - 1;
|
||||||
|
c = lbnToCylinder(endLbn);
|
||||||
|
if (c <= 1023) {
|
||||||
|
p->endCylinderHigh = c >> 8;
|
||||||
|
p->endCylinderLow = c & 0XFF;
|
||||||
|
p->endHead = lbnToHead(endLbn);
|
||||||
|
p->endSector = lbnToSector(endLbn);
|
||||||
|
} else {
|
||||||
|
// Too big flag, c = 1023, h = 254, s = 63
|
||||||
|
p->endCylinderHigh = 3;
|
||||||
|
p->endCylinderLow = 255;
|
||||||
|
p->endHead = 254;
|
||||||
|
p->endSector = 63;
|
||||||
|
}
|
||||||
|
p->firstSector = relSector;
|
||||||
|
p->totalSectors = partSize;
|
||||||
|
if (!writeCache(0)) {
|
||||||
|
DEBUGV("SDFS: write MBR");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t volSerialNumber() {
|
||||||
|
return (cardSizeBlocks << 8) + micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool makeFat16() {
|
||||||
|
uint16_t const BU16 = 128;
|
||||||
|
uint32_t nc;
|
||||||
|
for (dataStart = 2 * BU16;; dataStart += BU16) {
|
||||||
|
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||||
|
fatSize = (nc + 2 + 255)/256;
|
||||||
|
uint32_t r = BU16 + 1 + 2 * fatSize + 32;
|
||||||
|
if (dataStart < r) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
relSector = dataStart - r + BU16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// check valid cluster count for FAT16 volume
|
||||||
|
if (nc < 4085 || nc >= 65525) {
|
||||||
|
DEBUGV("SDFS: Bad cluster count");
|
||||||
|
}
|
||||||
|
reservedSectors = 1;
|
||||||
|
fatStart = relSector + reservedSectors;
|
||||||
|
partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
|
||||||
|
if (partSize < 32680) {
|
||||||
|
partType = 0X01;
|
||||||
|
} else if (partSize < 65536) {
|
||||||
|
partType = 0X04;
|
||||||
|
} else {
|
||||||
|
partType = 0X06;
|
||||||
|
}
|
||||||
|
// write MBR
|
||||||
|
if (!writeMbr()) {
|
||||||
|
DEBUGV("SDFS: writembr failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCache(true);
|
||||||
|
sdfat::fat_boot_t* pb = &cache->fbs;
|
||||||
|
pb->jump[0] = 0XEB;
|
||||||
|
pb->jump[1] = 0X00;
|
||||||
|
pb->jump[2] = 0X90;
|
||||||
|
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||||
|
pb->oemId[i] = ' ';
|
||||||
|
}
|
||||||
|
pb->bytesPerSector = 512;
|
||||||
|
pb->sectorsPerCluster = sectorsPerCluster;
|
||||||
|
pb->reservedSectorCount = reservedSectors;
|
||||||
|
pb->fatCount = 2;
|
||||||
|
pb->rootDirEntryCount = 512;
|
||||||
|
pb->mediaType = 0XF8;
|
||||||
|
pb->sectorsPerFat16 = fatSize;
|
||||||
|
pb->sectorsPerTrack = sectorsPerTrack;
|
||||||
|
pb->headCount = numberOfHeads;
|
||||||
|
pb->hidddenSectors = relSector;
|
||||||
|
pb->totalSectors32 = partSize;
|
||||||
|
pb->driveNumber = 0X80;
|
||||||
|
pb->bootSignature = sdfat::EXTENDED_BOOT_SIG;
|
||||||
|
pb->volumeSerialNumber = volSerialNumber();
|
||||||
|
memcpy_P(pb->volumeLabel, PSTR("NO NAME "), sizeof(pb->volumeLabel));
|
||||||
|
memcpy_P(pb->fileSystemType, PSTR("FAT16 "), sizeof(pb->fileSystemType));
|
||||||
|
// write partition boot sector
|
||||||
|
if (!writeCache(relSector)) {
|
||||||
|
DEBUGV("SDFS: FAT16 write PBS failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// clear FAT and root directory
|
||||||
|
if (!clearFatDir(fatStart, dataStart - fatStart)) {
|
||||||
|
DEBUGV("SDFS: FAT16 clear root failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(false);
|
||||||
|
cache->fat16[0] = 0XFFF8;
|
||||||
|
cache->fat16[1] = 0XFFFF;
|
||||||
|
// write first block of FAT and backup for reserved clusters
|
||||||
|
if (!writeCache(fatStart) || !writeCache(fatStart + fatSize)) {
|
||||||
|
DEBUGV("FAT16 reserve failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool makeFat32() {
|
||||||
|
uint16_t const BU32 = 8192;
|
||||||
|
uint32_t nc;
|
||||||
|
relSector = BU32;
|
||||||
|
for (dataStart = 2 * BU32;; dataStart += BU32) {
|
||||||
|
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||||
|
fatSize = (nc + 2 + 127)/128;
|
||||||
|
uint32_t r = relSector + 9 + 2 * fatSize;
|
||||||
|
if (dataStart >= r) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// error if too few clusters in FAT32 volume
|
||||||
|
if (nc < 65525) {
|
||||||
|
DEBUGV("SDFS: Bad cluster count");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reservedSectors = dataStart - relSector - 2 * fatSize;
|
||||||
|
fatStart = relSector + reservedSectors;
|
||||||
|
partSize = nc * sectorsPerCluster + dataStart - relSector;
|
||||||
|
// type depends on address of end sector
|
||||||
|
// max CHS has lbn = 16450560 = 1024*255*63
|
||||||
|
if ((relSector + partSize) <= 16450560) {
|
||||||
|
// FAT32
|
||||||
|
partType = 0X0B;
|
||||||
|
} else {
|
||||||
|
// FAT32 with INT 13
|
||||||
|
partType = 0X0C;
|
||||||
|
}
|
||||||
|
if (!writeMbr()) {
|
||||||
|
DEBUGV("SDFS: writembr failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCache(true);
|
||||||
|
|
||||||
|
sdfat::fat32_boot_t* pb = &cache->fbs32;
|
||||||
|
pb->jump[0] = 0XEB;
|
||||||
|
pb->jump[1] = 0X00;
|
||||||
|
pb->jump[2] = 0X90;
|
||||||
|
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||||
|
pb->oemId[i] = ' ';
|
||||||
|
}
|
||||||
|
pb->bytesPerSector = 512;
|
||||||
|
pb->sectorsPerCluster = sectorsPerCluster;
|
||||||
|
pb->reservedSectorCount = reservedSectors;
|
||||||
|
pb->fatCount = 2;
|
||||||
|
pb->mediaType = 0XF8;
|
||||||
|
pb->sectorsPerTrack = sectorsPerTrack;
|
||||||
|
pb->headCount = numberOfHeads;
|
||||||
|
pb->hidddenSectors = relSector;
|
||||||
|
pb->totalSectors32 = partSize;
|
||||||
|
pb->sectorsPerFat32 = fatSize;
|
||||||
|
pb->fat32RootCluster = 2;
|
||||||
|
pb->fat32FSInfo = 1;
|
||||||
|
pb->fat32BackBootBlock = 6;
|
||||||
|
pb->driveNumber = 0X80;
|
||||||
|
pb->bootSignature = sdfat::EXTENDED_BOOT_SIG;
|
||||||
|
pb->volumeSerialNumber = volSerialNumber();
|
||||||
|
memcpy_P(pb->volumeLabel, PSTR("NO NAME "), sizeof(pb->volumeLabel));
|
||||||
|
memcpy_P(pb->fileSystemType, PSTR("FAT32 "), sizeof(pb->fileSystemType));
|
||||||
|
// write partition boot sector and backup
|
||||||
|
if (!writeCache(relSector) || !writeCache(relSector + 6)) {
|
||||||
|
DEBUGV("SDFS: FAT32 write PBS failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearCache(true);
|
||||||
|
// write extra boot area and backup
|
||||||
|
if (!writeCache(relSector + 2) || !writeCache(relSector + 8)) {
|
||||||
|
DEBUGV("SDFS: FAT32 PBS ext failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sdfat::fat32_fsinfo_t* pf = &cache->fsinfo;
|
||||||
|
pf->leadSignature = sdfat::FSINFO_LEAD_SIG;
|
||||||
|
pf->structSignature = sdfat::FSINFO_STRUCT_SIG;
|
||||||
|
pf->freeCount = 0XFFFFFFFF;
|
||||||
|
pf->nextFree = 0XFFFFFFFF;
|
||||||
|
// write FSINFO sector and backup
|
||||||
|
if (!writeCache(relSector + 1) || !writeCache(relSector + 7)) {
|
||||||
|
DEBUGV("SDFS: FAT32 FSINFO failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster);
|
||||||
|
clearCache(false);
|
||||||
|
cache->fat32[0] = 0x0FFFFFF8;
|
||||||
|
cache->fat32[1] = 0x0FFFFFFF;
|
||||||
|
cache->fat32[2] = 0x0FFFFFFF;
|
||||||
|
// write first block of FAT and backup for reserved clusters
|
||||||
|
if (!writeCache(fatStart) || !writeCache(fatStart + fatSize)) {
|
||||||
|
DEBUGV("SDFS: FAT32 reserve failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool format(sdfat::SdFat *_fs, int8_t _csPin, SPISettings _spiSettings) {
|
||||||
|
card = static_cast<sdfat::Sd2Card*>(_fs->card());
|
||||||
|
cache = _fs->cacheClear();
|
||||||
|
|
||||||
|
if (!card->begin(_csPin, _spiSettings)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cardSizeBlocks = card->cardSize();
|
||||||
|
if (cardSizeBlocks == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
|
||||||
|
|
||||||
|
if (cardCapacityMB <= 6) {
|
||||||
|
return false; // Card is too small
|
||||||
|
} else if (cardCapacityMB <= 16) {
|
||||||
|
sectorsPerCluster = 2;
|
||||||
|
} else if (cardCapacityMB <= 32) {
|
||||||
|
sectorsPerCluster = 4;
|
||||||
|
} else if (cardCapacityMB <= 64) {
|
||||||
|
sectorsPerCluster = 8;
|
||||||
|
} else if (cardCapacityMB <= 128) {
|
||||||
|
sectorsPerCluster = 16;
|
||||||
|
} else if (cardCapacityMB <= 1024) {
|
||||||
|
sectorsPerCluster = 32;
|
||||||
|
} else if (cardCapacityMB <= 32768) {
|
||||||
|
sectorsPerCluster = 64;
|
||||||
|
} else {
|
||||||
|
// SDXC cards
|
||||||
|
sectorsPerCluster = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set fake disk geometry
|
||||||
|
sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
|
||||||
|
|
||||||
|
if (cardCapacityMB <= 16) {
|
||||||
|
numberOfHeads = 2;
|
||||||
|
} else if (cardCapacityMB <= 32) {
|
||||||
|
numberOfHeads = 4;
|
||||||
|
} else if (cardCapacityMB <= 128) {
|
||||||
|
numberOfHeads = 8;
|
||||||
|
} else if (cardCapacityMB <= 504) {
|
||||||
|
numberOfHeads = 16;
|
||||||
|
} else if (cardCapacityMB <= 1008) {
|
||||||
|
numberOfHeads = 32;
|
||||||
|
} else if (cardCapacityMB <= 2016) {
|
||||||
|
numberOfHeads = 64;
|
||||||
|
} else if (cardCapacityMB <= 4032) {
|
||||||
|
numberOfHeads = 128;
|
||||||
|
} else {
|
||||||
|
numberOfHeads = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erase all data on card (TRIM)
|
||||||
|
uint32_t const ERASE_SIZE = 262144L;
|
||||||
|
uint32_t firstBlock = 0;
|
||||||
|
uint32_t lastBlock;
|
||||||
|
do {
|
||||||
|
lastBlock = firstBlock + ERASE_SIZE - 1;
|
||||||
|
if (lastBlock >= cardSizeBlocks) {
|
||||||
|
lastBlock = cardSizeBlocks - 1;
|
||||||
|
}
|
||||||
|
if (!card->erase(firstBlock, lastBlock)) {
|
||||||
|
return false; // Erase fail
|
||||||
|
}
|
||||||
|
delay(0); // yield to the OS to avoid WDT
|
||||||
|
firstBlock += ERASE_SIZE;
|
||||||
|
} while (firstBlock < cardSizeBlocks);
|
||||||
|
|
||||||
|
if (!card->readBlock(0, cache->data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card->type() != sdfat::SD_CARD_TYPE_SDHC) {
|
||||||
|
return makeFat16();
|
||||||
|
} else {
|
||||||
|
return makeFat32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // class SDFSFormatter
|
||||||
|
|
||||||
|
}; // namespace sdfs
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _SDFSFORMATTER_H
|
@ -1,4 +1,4 @@
|
|||||||
WebSocket Server and Client for Arduino [](https://github.com/Links2004/arduinoWebSockets/actions?query=workflow%3ACI+branch%3Amaster)
|
WebSocket Server and Client for Arduino [](https://travis-ci.org/Links2004/arduinoWebSockets)
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
a WebSocket Server and Client for Arduino based on RFC6455.
|
a WebSocket Server and Client for Arduino based on RFC6455.
|
||||||
@ -34,9 +34,7 @@ a WebSocket Server and Client for Arduino based on RFC6455.
|
|||||||
|
|
||||||
###### Note: ######
|
###### Note: ######
|
||||||
|
|
||||||
version 2.0.0 and up is not compatible with AVR/ATmega, check ATmega branch.
|
version 2.0 and up is not compatible with AVR/ATmega, check ATmega branch.
|
||||||
|
|
||||||
version 2.3.0 has API changes for the ESP8266 BareSSL (may brakes existing code)
|
|
||||||
|
|
||||||
Arduino for AVR not supports std namespace of c++.
|
Arduino for AVR not supports std namespace of c++.
|
||||||
|
|
||||||
@ -59,22 +57,22 @@ The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE
|
|||||||
### High Level Client API ###
|
### High Level Client API ###
|
||||||
|
|
||||||
- `begin` : Initiate connection sequence to the websocket host.
|
- `begin` : Initiate connection sequence to the websocket host.
|
||||||
```c++
|
```
|
||||||
void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||||
void begin(String host, uint16_t port, String url = "/", String protocol = "arduino");
|
void begin(String host, uint16_t port, String url = "/", String protocol = "arduino");
|
||||||
```
|
```
|
||||||
- `onEvent`: Callback to handle for websocket events
|
- `onEvent`: Callback to handle for websocket events
|
||||||
|
|
||||||
```c++
|
```
|
||||||
void onEvent(WebSocketClientEvent cbEvent);
|
void onEvent(WebSocketClientEvent cbEvent);
|
||||||
```
|
```
|
||||||
|
|
||||||
- `WebSocketClientEvent`: Handler for websocket events
|
- `WebSocketClientEvent`: Handler for websocket events
|
||||||
```c++
|
```
|
||||||
void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length)
|
void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length)
|
||||||
```
|
```
|
||||||
Where `WStype_t type` is defined as:
|
Where `WStype_t type` is defined as:
|
||||||
```c++
|
```
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WStype_ERROR,
|
WStype_ERROR,
|
||||||
WStype_DISCONNECTED,
|
WStype_DISCONNECTED,
|
||||||
@ -85,8 +83,6 @@ Where `WStype_t type` is defined as:
|
|||||||
WStype_FRAGMENT_BIN_START,
|
WStype_FRAGMENT_BIN_START,
|
||||||
WStype_FRAGMENT,
|
WStype_FRAGMENT,
|
||||||
WStype_FRAGMENT_FIN,
|
WStype_FRAGMENT_FIN,
|
||||||
WStype_PING,
|
|
||||||
WStype_PONG,
|
|
||||||
} WStype_t;
|
} WStype_t;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* WebSocketClientSSLWithCA.ino
|
|
||||||
*
|
|
||||||
* Created on: 27.10.2019
|
|
||||||
*
|
|
||||||
* note SSL is only possible with the ESP8266
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
|
||||||
#include <ESP8266WiFiMulti.h>
|
|
||||||
|
|
||||||
#include <WebSocketsClient.h>
|
|
||||||
|
|
||||||
ESP8266WiFiMulti WiFiMulti;
|
|
||||||
WebSocketsClient webSocket;
|
|
||||||
|
|
||||||
#define USE_SERIAL Serial1
|
|
||||||
|
|
||||||
|
|
||||||
// Can be obtained with:
|
|
||||||
// openssl s_client -showcerts -connect echo.websocket.org:443 </dev/null
|
|
||||||
const char ENDPOINT_CA_CERT[] PROGMEM = R"EOF(
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
|
||||||
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
|
|
||||||
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
|
|
||||||
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
|
|
||||||
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
|
|
||||||
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
|
|
||||||
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
|
|
||||||
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
|
|
||||||
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
|
|
||||||
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
|
|
||||||
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
|
|
||||||
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlGPfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
|
|
||||||
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
)EOF";
|
|
||||||
|
|
||||||
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
|
|
||||||
switch(type) {
|
|
||||||
case WStype_DISCONNECTED:
|
|
||||||
USE_SERIAL.printf("[WSc] Disconnected!\n");
|
|
||||||
break;
|
|
||||||
case WStype_CONNECTED:
|
|
||||||
{
|
|
||||||
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
|
|
||||||
|
|
||||||
// send message to server when Connected
|
|
||||||
webSocket.sendTXT("Connected");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WStype_TEXT:
|
|
||||||
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
|
|
||||||
|
|
||||||
// send message to server
|
|
||||||
// webSocket.sendTXT("message here");
|
|
||||||
break;
|
|
||||||
case WStype_BIN:
|
|
||||||
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
|
|
||||||
hexdump(payload, length);
|
|
||||||
|
|
||||||
// send data to server
|
|
||||||
// webSocket.sendBIN(payload, length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
USE_SERIAL.begin(115200);
|
|
||||||
|
|
||||||
USE_SERIAL.setDebugOutput(true);
|
|
||||||
|
|
||||||
USE_SERIAL.println();
|
|
||||||
USE_SERIAL.println();
|
|
||||||
USE_SERIAL.println();
|
|
||||||
|
|
||||||
for(uint8_t t = 4; t > 0; t--) {
|
|
||||||
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
|
|
||||||
USE_SERIAL.flush();
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFiMulti.addAP("SSID", "passpasspass");
|
|
||||||
|
|
||||||
while(WiFiMulti.run() != WL_CONNECTED) {
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
//When using BearSSL, client certificate and private key can be set:
|
|
||||||
//webSocket.setSSLClientCertKey(clientCert, clientPrivateKey);
|
|
||||||
//clientCert and clientPrivateKey can be of types (const char *, const char *) , or of types (BearSSL::X509List, BearSSL::PrivateKey)
|
|
||||||
|
|
||||||
webSocket.beginSslWithCA("echo.websocket.org", 443, "/", ENDPOINT_CA_CERT);
|
|
||||||
webSocket.onEvent(webSocketEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
webSocket.loop();
|
|
||||||
}
|
|
@ -29,9 +29,6 @@ void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length)
|
|||||||
break;
|
break;
|
||||||
case sIOtype_CONNECT:
|
case sIOtype_CONNECT:
|
||||||
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
|
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
|
||||||
|
|
||||||
// join default namespace (no auto join in Socket.IO V3)
|
|
||||||
socketIO.send(sIOtype_CONNECT, "/");
|
|
||||||
break;
|
break;
|
||||||
case sIOtype_EVENT:
|
case sIOtype_EVENT:
|
||||||
USE_SERIAL.printf("[IOc] get event: %s\n", payload);
|
USE_SERIAL.printf("[IOc] get event: %s\n", payload);
|
||||||
@ -113,7 +110,7 @@ void loop() {
|
|||||||
|
|
||||||
// add payload (parameters) for the event
|
// add payload (parameters) for the event
|
||||||
JsonObject param1 = array.createNestedObject();
|
JsonObject param1 = array.createNestedObject();
|
||||||
param1["now"] = (uint32_t) now;
|
param1["now"] = now;
|
||||||
|
|
||||||
// JSON to String (serializion)
|
// JSON to String (serializion)
|
||||||
String output;
|
String output;
|
||||||
|
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* WebSocketClientSocketIOack.ino
|
|
||||||
*
|
|
||||||
* Created on: 20.07.2019
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
|
||||||
#include <ESP8266WiFiMulti.h>
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
#include <WebSocketsClient.h>
|
|
||||||
#include <SocketIOclient.h>
|
|
||||||
|
|
||||||
#include <Hash.h>
|
|
||||||
|
|
||||||
ESP8266WiFiMulti WiFiMulti;
|
|
||||||
SocketIOclient socketIO;
|
|
||||||
|
|
||||||
#define USE_SERIAL Serial
|
|
||||||
|
|
||||||
|
|
||||||
void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
|
|
||||||
switch(type) {
|
|
||||||
case sIOtype_DISCONNECT:
|
|
||||||
USE_SERIAL.printf("[IOc] Disconnected!\n");
|
|
||||||
break;
|
|
||||||
case sIOtype_CONNECT:
|
|
||||||
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
|
|
||||||
|
|
||||||
// join default namespace (no auto join in Socket.IO V3)
|
|
||||||
socketIO.send(sIOtype_CONNECT, "/");
|
|
||||||
break;
|
|
||||||
case sIOtype_EVENT:
|
|
||||||
{
|
|
||||||
char * sptr = NULL;
|
|
||||||
int id = strtol((char *)payload, &sptr, 10);
|
|
||||||
USE_SERIAL.printf("[IOc] get event: %s id: %d\n", payload, id);
|
|
||||||
if(id) {
|
|
||||||
payload = (uint8_t *)sptr;
|
|
||||||
}
|
|
||||||
DynamicJsonDocument doc(1024);
|
|
||||||
DeserializationError error = deserializeJson(doc, payload, length);
|
|
||||||
if(error) {
|
|
||||||
USE_SERIAL.print(F("deserializeJson() failed: "));
|
|
||||||
USE_SERIAL.println(error.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String eventName = doc[0];
|
|
||||||
USE_SERIAL.printf("[IOc] event name: %s\n", eventName.c_str());
|
|
||||||
|
|
||||||
// Message Includes a ID for a ACK (callback)
|
|
||||||
if(id) {
|
|
||||||
// creat JSON message for Socket.IO (ack)
|
|
||||||
DynamicJsonDocument docOut(1024);
|
|
||||||
JsonArray array = docOut.to<JsonArray>();
|
|
||||||
|
|
||||||
// add payload (parameters) for the ack (callback function)
|
|
||||||
JsonObject param1 = array.createNestedObject();
|
|
||||||
param1["now"] = millis();
|
|
||||||
|
|
||||||
// JSON to String (serializion)
|
|
||||||
String output;
|
|
||||||
output += id;
|
|
||||||
serializeJson(docOut, output);
|
|
||||||
|
|
||||||
// Send event
|
|
||||||
socketIO.send(sIOtype_ACK, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sIOtype_ACK:
|
|
||||||
USE_SERIAL.printf("[IOc] get ack: %u\n", length);
|
|
||||||
hexdump(payload, length);
|
|
||||||
break;
|
|
||||||
case sIOtype_ERROR:
|
|
||||||
USE_SERIAL.printf("[IOc] get error: %u\n", length);
|
|
||||||
hexdump(payload, length);
|
|
||||||
break;
|
|
||||||
case sIOtype_BINARY_EVENT:
|
|
||||||
USE_SERIAL.printf("[IOc] get binary: %u\n", length);
|
|
||||||
hexdump(payload, length);
|
|
||||||
break;
|
|
||||||
case sIOtype_BINARY_ACK:
|
|
||||||
USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
|
|
||||||
hexdump(payload, length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
//USE_SERIAL.begin(921600);
|
|
||||||
USE_SERIAL.begin(115200);
|
|
||||||
|
|
||||||
//Serial.setDebugOutput(true);
|
|
||||||
USE_SERIAL.setDebugOutput(true);
|
|
||||||
|
|
||||||
USE_SERIAL.println();
|
|
||||||
USE_SERIAL.println();
|
|
||||||
USE_SERIAL.println();
|
|
||||||
|
|
||||||
for(uint8_t t = 4; t > 0; t--) {
|
|
||||||
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
|
|
||||||
USE_SERIAL.flush();
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable AP
|
|
||||||
if(WiFi.getMode() & WIFI_AP) {
|
|
||||||
WiFi.softAPdisconnect(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFiMulti.addAP("SSID", "passpasspass");
|
|
||||||
|
|
||||||
//WiFi.disconnect();
|
|
||||||
while(WiFiMulti.run() != WL_CONNECTED) {
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
String ip = WiFi.localIP().toString();
|
|
||||||
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
|
|
||||||
|
|
||||||
// server address, port and URL
|
|
||||||
socketIO.begin("10.11.100.100", 8880);
|
|
||||||
|
|
||||||
// event handler
|
|
||||||
socketIO.onEvent(socketIOEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long messageTimestamp = 0;
|
|
||||||
void loop() {
|
|
||||||
socketIO.loop();
|
|
||||||
|
|
||||||
uint64_t now = millis();
|
|
||||||
|
|
||||||
if(now - messageTimestamp > 2000) {
|
|
||||||
messageTimestamp = now;
|
|
||||||
|
|
||||||
// creat JSON message for Socket.IO (event)
|
|
||||||
DynamicJsonDocument doc(1024);
|
|
||||||
JsonArray array = doc.to<JsonArray>();
|
|
||||||
|
|
||||||
// add evnet name
|
|
||||||
// Hint: socket.on('event_name', ....
|
|
||||||
array.add("event_name");
|
|
||||||
|
|
||||||
// add payload (parameters) for the event
|
|
||||||
JsonObject param1 = array.createNestedObject();
|
|
||||||
param1["now"] = (uint32_t) now;
|
|
||||||
|
|
||||||
// JSON to String (serializion)
|
|
||||||
String output;
|
|
||||||
serializeJson(doc, output);
|
|
||||||
|
|
||||||
// Send event
|
|
||||||
socketIO.sendEVENT(output);
|
|
||||||
|
|
||||||
// Print JSON for debugging
|
|
||||||
USE_SERIAL.println(output);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* WebSocketServerHooked.ino
|
|
||||||
*
|
|
||||||
* Created on: 22.05.2015
|
|
||||||
* Hooked on: 28.10.2020
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
|
||||||
#include <ESP8266WiFiMulti.h>
|
|
||||||
#include <WebSockets4WebServer.h>
|
|
||||||
#include <Hash.h>
|
|
||||||
#include <ESP8266mDNS.h>
|
|
||||||
|
|
||||||
ESP8266WiFiMulti WiFiMulti;
|
|
||||||
|
|
||||||
ESP8266WebServer server(80);
|
|
||||||
WebSockets4WebServer webSocket;
|
|
||||||
|
|
||||||
#define USE_SERIAL Serial
|
|
||||||
|
|
||||||
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case WStype_DISCONNECTED:
|
|
||||||
USE_SERIAL.printf("[%u] Disconnected!\n", num);
|
|
||||||
break;
|
|
||||||
case WStype_CONNECTED:
|
|
||||||
{
|
|
||||||
IPAddress ip = webSocket.remoteIP(num);
|
|
||||||
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
|
|
||||||
|
|
||||||
// send message to client
|
|
||||||
webSocket.sendTXT(num, "Connected");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WStype_TEXT:
|
|
||||||
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
|
|
||||||
|
|
||||||
// send message to client
|
|
||||||
// webSocket.sendTXT(num, "message here");
|
|
||||||
|
|
||||||
// send data to all connected clients
|
|
||||||
// webSocket.broadcastTXT("message here");
|
|
||||||
break;
|
|
||||||
case WStype_BIN:
|
|
||||||
USE_SERIAL.printf("[%u] get binary length: %u\n", num, length);
|
|
||||||
hexdump(payload, length);
|
|
||||||
|
|
||||||
// send message to client
|
|
||||||
// webSocket.sendBIN(num, payload, length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// USE_SERIAL.begin(921600);
|
|
||||||
USE_SERIAL.begin(115200);
|
|
||||||
|
|
||||||
//Serial.setDebugOutput(true);
|
|
||||||
USE_SERIAL.setDebugOutput(true);
|
|
||||||
|
|
||||||
USE_SERIAL.println();
|
|
||||||
USE_SERIAL.println();
|
|
||||||
USE_SERIAL.println();
|
|
||||||
|
|
||||||
for(uint8_t t = 4; t > 0; t--) {
|
|
||||||
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
|
|
||||||
USE_SERIAL.flush();
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFiMulti.addAP("SSID", "passpasspass");
|
|
||||||
|
|
||||||
while(WiFiMulti.run() != WL_CONNECTED) {
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
server.on("/", []() {
|
|
||||||
server.send(200, "text/plain", "I am a regular webserver on port 80!\r\n");
|
|
||||||
server.send(200, "text/plain", "I am also a websocket server on '/ws' on the same port 80\r\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
server.addHook(webSocket.hookForWebserver("/ws", webSocketEvent));
|
|
||||||
|
|
||||||
server.begin();
|
|
||||||
Serial.println("HTTP server started on port 80");
|
|
||||||
Serial.println("WebSocket server started on the same port");
|
|
||||||
Serial.printf("my network address is either 'arduinoWebsockets.local' (mDNS) or '%s'\n", WiFi.localIP().toString().c_str());
|
|
||||||
|
|
||||||
if (!MDNS.begin("arduinoWebsockets")) {
|
|
||||||
Serial.println("Error setting up MDNS responder!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
server.handleClient();
|
|
||||||
webSocket.loop();
|
|
||||||
MDNS.update();
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# linux script to compile&run arduinoWebSockets in a mock environment
|
|
||||||
|
|
||||||
if [ -z "$ESP8266ARDUINO" ]; then
|
|
||||||
echo "please set ESP8266ARDUINO env-var to where esp8266/arduino sits"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
where=$(pwd)
|
|
||||||
|
|
||||||
cd $ESP8266ARDUINO/tests/host/
|
|
||||||
|
|
||||||
make -j FORCE32=0 \
|
|
||||||
ULIBDIRS=../../libraries/Hash/:~/dev/proj/arduino/libraries/arduinoWebSockets \
|
|
||||||
${where}/WebSocketServerHooked
|
|
||||||
|
|
||||||
valgrind ./bin/WebSocketServerHooked/WebSocketServerHooked -b "$@"
|
|
@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# python websocket client to test with
|
|
||||||
# emulator: server is at ws://127.0.0.1:9080/ws
|
|
||||||
# esp8266: server is at ws:///ws
|
|
||||||
# (uncomment the right line below)
|
|
||||||
|
|
||||||
#uri = "ws://127.0.0.1:9080/ws"
|
|
||||||
uri = "ws://arduinoWebsockets.local/ws"
|
|
||||||
|
|
||||||
import websocket
|
|
||||||
try:
|
|
||||||
import thread
|
|
||||||
except ImportError:
|
|
||||||
import _thread as thread
|
|
||||||
import time
|
|
||||||
|
|
||||||
def on_message(ws, message):
|
|
||||||
print("message");
|
|
||||||
print(message)
|
|
||||||
|
|
||||||
def on_error(ws, error):
|
|
||||||
print("error")
|
|
||||||
print(error)
|
|
||||||
|
|
||||||
def on_close(ws):
|
|
||||||
print("### closed ###")
|
|
||||||
|
|
||||||
def on_open(ws):
|
|
||||||
print("opened")
|
|
||||||
def run(*args):
|
|
||||||
for i in range(3):
|
|
||||||
time.sleep(1)
|
|
||||||
ws.send("Hello %d" % i)
|
|
||||||
time.sleep(1)
|
|
||||||
ws.close()
|
|
||||||
print("thread terminating...")
|
|
||||||
thread.start_new_thread(run, ())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
websocket.enableTrace(True)
|
|
||||||
ws = websocket.WebSocketApp(uri, on_message = on_message, on_error = on_error, on_close = on_close)
|
|
||||||
ws.on_open = on_open
|
|
||||||
ws.run_forever()
|
|
@ -1,25 +1,25 @@
|
|||||||
{
|
{
|
||||||
|
"name": "WebSockets",
|
||||||
|
"description": "WebSocket Server and Client for Arduino based on RFC6455",
|
||||||
|
"keywords": "wifi, http, web, server, client, websocket",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"maintainer": true,
|
|
||||||
"name": "Markus Sattler",
|
"name": "Markus Sattler",
|
||||||
"url": "https://github.com/Links2004"
|
"url": "https://github.com/Links2004",
|
||||||
|
"maintainer": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "WebSocket Server and Client for Arduino based on RFC6455",
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Links2004/arduinoWebSockets.git"
|
||||||
|
},
|
||||||
|
"version": "2.1.4",
|
||||||
|
"license": "LGPL-2.1",
|
||||||
"export": {
|
"export": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"tests"
|
"tests"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"frameworks": "arduino",
|
"frameworks": "arduino",
|
||||||
"keywords": "wifi, http, web, server, client, websocket",
|
"platforms": "atmelavr, espressif8266, espressif32"
|
||||||
"license": "LGPL-2.1",
|
|
||||||
"name": "WebSockets",
|
|
||||||
"platforms": "atmelavr, espressif8266, espressif32",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/Links2004/arduinoWebSockets.git"
|
|
||||||
},
|
|
||||||
"version": "2.3.5"
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
name=WebSockets
|
name=WebSockets
|
||||||
version=2.3.5
|
version=2.1.4
|
||||||
author=Markus Sattler
|
author=Markus Sattler
|
||||||
maintainer=Markus Sattler
|
maintainer=Markus Sattler
|
||||||
sentence=WebSockets for Arduino (Server + Client)
|
sentence=WebSockets for Arduino (Server + Client)
|
||||||
|
@ -18,59 +18,11 @@ SocketIOclient::~SocketIOclient() {
|
|||||||
void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
|
void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
|
||||||
WebSocketsClient::beginSocketIO(host, port, url, protocol);
|
WebSocketsClient::beginSocketIO(host, port, url, protocol);
|
||||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
||||||
initClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
|
void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
|
||||||
WebSocketsClient::beginSocketIO(host, port, url, protocol);
|
WebSocketsClient::beginSocketIO(host, port, url, protocol);
|
||||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
||||||
initClient();
|
|
||||||
}
|
|
||||||
#if defined(HAS_SSL)
|
|
||||||
void SocketIOclient::beginSSL(const char * host, uint16_t port, const char * url, const char * protocol) {
|
|
||||||
WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
|
|
||||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
|
||||||
initClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketIOclient::beginSSL(String host, uint16_t port, String url, String protocol) {
|
|
||||||
WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
|
|
||||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
|
||||||
initClient();
|
|
||||||
}
|
|
||||||
#if defined(SSL_BARESSL)
|
|
||||||
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
|
||||||
WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
|
|
||||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
|
||||||
initClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
|
|
||||||
WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
|
|
||||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
|
||||||
initClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketIOclient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
|
|
||||||
WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketIOclient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
|
|
||||||
WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SocketIOclient::configureEIOping(bool disableHeartbeat) {
|
|
||||||
_disableHeartbeat = disableHeartbeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketIOclient::initClient(void) {
|
|
||||||
if(_client.cUrl.indexOf("EIO=4") != -1) {
|
|
||||||
DEBUG_WEBSOCKETS("[wsIOc] found EIO=4 disable EIO ping on client\n");
|
|
||||||
configureEIOping(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,24 +40,23 @@ bool SocketIOclient::isConnected(void) {
|
|||||||
/**
|
/**
|
||||||
* send text data to client
|
* send text data to client
|
||||||
* @param num uint8_t client id
|
* @param num uint8_t client id
|
||||||
* @param type socketIOmessageType_t
|
|
||||||
* @param payload uint8_t *
|
* @param payload uint8_t *
|
||||||
* @param length size_t
|
* @param length size_t
|
||||||
* @param headerToPayload bool (see sendFrame for more details)
|
* @param headerToPayload bool (see sendFrame for more details)
|
||||||
* @return true if ok
|
* @return true if ok
|
||||||
*/
|
*/
|
||||||
bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t length, bool headerToPayload) {
|
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if(length == 0) {
|
if(length == 0) {
|
||||||
length = strlen((const char *)payload);
|
length = strlen((const char *)payload);
|
||||||
}
|
}
|
||||||
if(clientIsConnected(&_client) && _client.status == WSC_CONNECTED) {
|
if(clientIsConnected(&_client)) {
|
||||||
if(!headerToPayload) {
|
if(!headerToPayload) {
|
||||||
// webSocket Header
|
// webSocket Header
|
||||||
ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true);
|
ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true);
|
||||||
// Engine.IO / Socket.IO Header
|
// Engine.IO / Socket.IO Header
|
||||||
if(ret) {
|
if(ret) {
|
||||||
uint8_t buf[3] = { eIOtype_MESSAGE, type, 0x00 };
|
uint8_t buf[3] = { eIOtype_MESSAGE, sIOtype_EVENT, 0x00 };
|
||||||
ret = WebSocketsClient::write(&_client, buf, 2);
|
ret = WebSocketsClient::write(&_client, buf, 2);
|
||||||
}
|
}
|
||||||
if(ret && payload && length > 0) {
|
if(ret && payload && length > 0) {
|
||||||
@ -115,38 +66,12 @@ bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t
|
|||||||
} else {
|
} else {
|
||||||
// TODO implement
|
// TODO implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return WebSocketsClient::sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketIOclient::send(socketIOmessageType_t type, const uint8_t * payload, size_t length) {
|
|
||||||
return send(type, (uint8_t *)payload, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SocketIOclient::send(socketIOmessageType_t type, char * payload, size_t length, bool headerToPayload) {
|
|
||||||
return send(type, (uint8_t *)payload, length, headerToPayload);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SocketIOclient::send(socketIOmessageType_t type, const char * payload, size_t length) {
|
|
||||||
return send(type, (uint8_t *)payload, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SocketIOclient::send(socketIOmessageType_t type, String & payload) {
|
|
||||||
return send(type, (uint8_t *)payload.c_str(), payload.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* send text data to client
|
|
||||||
* @param num uint8_t client id
|
|
||||||
* @param payload uint8_t *
|
|
||||||
* @param length size_t
|
|
||||||
* @param headerToPayload bool (see sendFrame for more details)
|
|
||||||
* @return true if ok
|
|
||||||
*/
|
|
||||||
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
|
|
||||||
return send(sIOtype_EVENT, payload, length, headerToPayload);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
|
bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
|
||||||
return sendEVENT((uint8_t *)payload, length);
|
return sendEVENT((uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
@ -166,8 +91,8 @@ bool SocketIOclient::sendEVENT(String & payload) {
|
|||||||
void SocketIOclient::loop(void) {
|
void SocketIOclient::loop(void) {
|
||||||
WebSocketsClient::loop();
|
WebSocketsClient::loop();
|
||||||
unsigned long t = millis();
|
unsigned long t = millis();
|
||||||
if(!_disableHeartbeat && (t - _lastHeartbeat) > EIO_HEARTBEAT_INTERVAL) {
|
if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) {
|
||||||
_lastHeartbeat = t;
|
_lastConnectionFail = t;
|
||||||
DEBUG_WEBSOCKETS("[wsIOc] send ping\n");
|
DEBUG_WEBSOCKETS("[wsIOc] send ping\n");
|
||||||
WebSocketsClient::sendTXT(eIOtype_PING);
|
WebSocketsClient::sendTXT(eIOtype_PING);
|
||||||
}
|
}
|
||||||
@ -183,7 +108,6 @@ void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t leng
|
|||||||
DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
|
DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
|
||||||
// send message to server when Connected
|
// send message to server when Connected
|
||||||
// Engine.io upgrade confirmation message (required)
|
// Engine.io upgrade confirmation message (required)
|
||||||
WebSocketsClient::sendTXT("2probe");
|
|
||||||
WebSocketsClient::sendTXT(eIOtype_UPGRADE);
|
WebSocketsClient::sendTXT(eIOtype_UPGRADE);
|
||||||
runIOCbEvent(sIOtype_CONNECT, payload, length);
|
runIOCbEvent(sIOtype_CONNECT, payload, length);
|
||||||
} break;
|
} break;
|
||||||
@ -214,8 +138,6 @@ void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t leng
|
|||||||
DEBUG_WEBSOCKETS("[wsIOc] get event (%d): %s\n", lData, data);
|
DEBUG_WEBSOCKETS("[wsIOc] get event (%d): %s\n", lData, data);
|
||||||
break;
|
break;
|
||||||
case sIOtype_CONNECT:
|
case sIOtype_CONNECT:
|
||||||
DEBUG_WEBSOCKETS("[wsIOc] connected (%d): %s\n", lData, data);
|
|
||||||
return;
|
|
||||||
case sIOtype_DISCONNECT:
|
case sIOtype_DISCONNECT:
|
||||||
case sIOtype_ACK:
|
case sIOtype_ACK:
|
||||||
case sIOtype_ERROR:
|
case sIOtype_ERROR:
|
||||||
@ -239,7 +161,7 @@ void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t leng
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case WStype_ERROR:
|
|
||||||
case WStype_BIN:
|
case WStype_BIN:
|
||||||
case WStype_FRAGMENT_TEXT_START:
|
case WStype_FRAGMENT_TEXT_START:
|
||||||
case WStype_FRAGMENT_BIN_START:
|
case WStype_FRAGMENT_BIN_START:
|
||||||
|
@ -49,16 +49,6 @@ class SocketIOclient : protected WebSocketsClient {
|
|||||||
void begin(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
void begin(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||||
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
||||||
|
|
||||||
#ifdef HAS_SSL
|
|
||||||
void beginSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
|
||||||
void beginSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
|
||||||
#ifndef SSL_AXTLS
|
|
||||||
void beginSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * CA_cert = NULL, const char * protocol = "arduino");
|
|
||||||
void beginSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino");
|
|
||||||
void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL);
|
|
||||||
void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
bool isConnected(void);
|
bool isConnected(void);
|
||||||
|
|
||||||
void onEvent(SocketIOclientEvent cbEvent);
|
void onEvent(SocketIOclientEvent cbEvent);
|
||||||
@ -69,18 +59,9 @@ class SocketIOclient : protected WebSocketsClient {
|
|||||||
bool sendEVENT(const char * payload, size_t length = 0);
|
bool sendEVENT(const char * payload, size_t length = 0);
|
||||||
bool sendEVENT(String & payload);
|
bool sendEVENT(String & payload);
|
||||||
|
|
||||||
bool send(socketIOmessageType_t type, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
|
|
||||||
bool send(socketIOmessageType_t type, const uint8_t * payload, size_t length = 0);
|
|
||||||
bool send(socketIOmessageType_t type, char * payload, size_t length = 0, bool headerToPayload = false);
|
|
||||||
bool send(socketIOmessageType_t type, const char * payload, size_t length = 0);
|
|
||||||
bool send(socketIOmessageType_t type, String & payload);
|
|
||||||
|
|
||||||
void loop(void);
|
void loop(void);
|
||||||
|
|
||||||
void configureEIOping(bool disableHeartbeat = false);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _disableHeartbeat = false;
|
|
||||||
uint64_t _lastHeartbeat = 0;
|
uint64_t _lastHeartbeat = 0;
|
||||||
SocketIOclientEvent _cbEvent;
|
SocketIOclientEvent _cbEvent;
|
||||||
virtual void runIOCbEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
|
virtual void runIOCbEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
|
||||||
@ -89,8 +70,6 @@ class SocketIOclient : protected WebSocketsClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initClient(void);
|
|
||||||
|
|
||||||
// Handeling events from websocket layer
|
// Handeling events from websocket layer
|
||||||
virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) {
|
virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) {
|
||||||
handleCbEvent(type, payload, length);
|
handleCbEvent(type, payload, length);
|
||||||
|
@ -39,14 +39,7 @@ extern "C" {
|
|||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#include <Hash.h>
|
#include <Hash.h>
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include <esp_system.h>
|
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 4
|
|
||||||
#include <esp32/sha.h>
|
|
||||||
#else
|
|
||||||
#include <hwcrypto/sha.h>
|
#include <hwcrypto/sha.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -501,7 +494,7 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
|
|||||||
reasonCode = payload[0] << 8 | payload[1];
|
reasonCode = payload[0] << 8 | payload[1];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get ask for close. Code: %d\n", client->num, reasonCode);
|
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get ask for close. Code: %d", client->num, reasonCode);
|
||||||
if(header->payloadLen > 2) {
|
if(header->payloadLen > 2) {
|
||||||
DEBUG_WEBSOCKETS(" (%s)\n", (payload + 2));
|
DEBUG_WEBSOCKETS(" (%s)\n", (payload + 2));
|
||||||
} else {
|
} else {
|
||||||
@ -510,7 +503,6 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
|
|||||||
clientDisconnect(client, 1000);
|
clientDisconnect(client, 1000);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] got unknown opcode: %d\n", client->num, header->opCode);
|
|
||||||
clientDisconnect(client, 1002);
|
clientDisconnect(client, 1002);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -603,7 +595,7 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
unsigned long t = millis();
|
unsigned long t = millis();
|
||||||
ssize_t len;
|
size_t len;
|
||||||
DEBUG_WEBSOCKETS("[readCb] n: %zu t: %lu\n", n, t);
|
DEBUG_WEBSOCKETS("[readCb] n: %zu t: %lu\n", n, t);
|
||||||
while(n > 0) {
|
while(n > 0) {
|
||||||
if(client->tcp == NULL) {
|
if(client->tcp == NULL) {
|
||||||
@ -631,12 +623,14 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!client->tcp->available()) {
|
if(!client->tcp->available()) {
|
||||||
WEBSOCKETS_YIELD_MORE();
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
|
delay(0);
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = client->tcp->read((uint8_t *)out, n);
|
len = client->tcp->read((uint8_t *)out, n);
|
||||||
if(len > 0) {
|
if(len) {
|
||||||
t = millis();
|
t = millis();
|
||||||
out += len;
|
out += len;
|
||||||
n -= len;
|
n -= len;
|
||||||
@ -644,14 +638,13 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
|||||||
} else {
|
} else {
|
||||||
//DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
|
//DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
|
||||||
}
|
}
|
||||||
if(n > 0) {
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
WEBSOCKETS_YIELD();
|
delay(0);
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
if(cb) {
|
if(cb) {
|
||||||
cb(client, true);
|
cb(client, true);
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -696,13 +689,12 @@ size_t WebSockets::write(WSclient_t * client, uint8_t * out, size_t n) {
|
|||||||
total += len;
|
total += len;
|
||||||
//DEBUG_WEBSOCKETS("write %d left %d!\n", len, n);
|
//DEBUG_WEBSOCKETS("write %d left %d!\n", len, n);
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBSOCKETS("WS write %d failed left %d!\n", len, n);
|
//DEBUG_WEBSOCKETS("write %d failed left %d!\n", len, n);
|
||||||
}
|
}
|
||||||
if(n > 0) {
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
WEBSOCKETS_YIELD();
|
delay(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,15 +40,9 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "WebSocketsVersion.h"
|
|
||||||
|
|
||||||
#ifndef NODEBUG_WEBSOCKETS
|
#ifndef NODEBUG_WEBSOCKETS
|
||||||
#ifdef DEBUG_ESP_PORT
|
#ifdef DEBUG_ESP_PORT
|
||||||
#define DEBUG_WEBSOCKETS(...) \
|
#define DEBUG_WEBSOCKETS(...) DEBUG_ESP_PORT.printf(__VA_ARGS__)
|
||||||
{ \
|
|
||||||
DEBUG_ESP_PORT.printf(__VA_ARGS__); \
|
|
||||||
DEBUG_ESP_PORT.flush(); \
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
//#define DEBUG_WEBSOCKETS(...) os_printf( __VA_ARGS__ )
|
//#define DEBUG_WEBSOCKETS(...) os_printf( __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
@ -56,10 +50,8 @@
|
|||||||
|
|
||||||
#ifndef DEBUG_WEBSOCKETS
|
#ifndef DEBUG_WEBSOCKETS
|
||||||
#define DEBUG_WEBSOCKETS(...)
|
#define DEBUG_WEBSOCKETS(...)
|
||||||
#ifndef NODEBUG_WEBSOCKETS
|
|
||||||
#define NODEBUG_WEBSOCKETS
|
#define NODEBUG_WEBSOCKETS
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ESP8266) || defined(ESP32)
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
|
||||||
@ -69,32 +61,22 @@
|
|||||||
// moves all Header strings to Flash (~300 Byte)
|
// moves all Header strings to Flash (~300 Byte)
|
||||||
//#define WEBSOCKETS_SAVE_RAM
|
//#define WEBSOCKETS_SAVE_RAM
|
||||||
|
|
||||||
#if defined(ESP8266)
|
|
||||||
#define WEBSOCKETS_YIELD() delay(0)
|
|
||||||
#define WEBSOCKETS_YIELD_MORE() delay(1)
|
|
||||||
#elif defined(ESP32)
|
|
||||||
#define WEBSOCKETS_YIELD() yield()
|
|
||||||
#define WEBSOCKETS_YIELD_MORE() delay(1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(STM32_DEVICE)
|
#elif defined(STM32_DEVICE)
|
||||||
|
|
||||||
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
|
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
|
||||||
#define WEBSOCKETS_USE_BIG_MEM
|
#define WEBSOCKETS_USE_BIG_MEM
|
||||||
#define GET_FREE_HEAP System.freeMemory()
|
#define GET_FREE_HEAP System.freeMemory()
|
||||||
#define WEBSOCKETS_YIELD()
|
|
||||||
#define WEBSOCKETS_YIELD_MORE()
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
//atmega328p has only 2KB ram!
|
//atmega328p has only 2KB ram!
|
||||||
#define WEBSOCKETS_MAX_DATA_SIZE (1024)
|
#define WEBSOCKETS_MAX_DATA_SIZE (1024)
|
||||||
// moves all Header strings to Flash
|
// moves all Header strings to Flash
|
||||||
#define WEBSOCKETS_SAVE_RAM
|
#define WEBSOCKETS_SAVE_RAM
|
||||||
#define WEBSOCKETS_YIELD()
|
|
||||||
#define WEBSOCKETS_YIELD_MORE()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WEBSOCKETS_TCP_TIMEOUT (5000)
|
#define WEBSOCKETS_TCP_TIMEOUT (2000)
|
||||||
|
|
||||||
#define NETWORK_ESP8266_ASYNC (0)
|
#define NETWORK_ESP8266_ASYNC (0)
|
||||||
#define NETWORK_ESP8266 (1)
|
#define NETWORK_ESP8266 (1)
|
||||||
@ -134,7 +116,6 @@
|
|||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#define SSL_AXTLS
|
|
||||||
#elif defined(ESP31B)
|
#elif defined(ESP31B)
|
||||||
#include <ESP31BWiFi.h>
|
#include <ESP31BWiFi.h>
|
||||||
#else
|
#else
|
||||||
@ -154,11 +135,6 @@
|
|||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#if defined(wificlientbearssl_h) && !defined(USING_AXTLS) && !defined(wificlientsecure_h)
|
|
||||||
#define SSL_BARESSL
|
|
||||||
#else
|
|
||||||
#define SSL_AXTLS
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#include <ESP31BWiFi.h>
|
#include <ESP31BWiFi.h>
|
||||||
#endif
|
#endif
|
||||||
@ -188,7 +164,6 @@
|
|||||||
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#define SSL_AXTLS
|
|
||||||
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
|
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
|
||||||
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
|
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
|
||||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
||||||
@ -217,7 +192,6 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
WSC_NOT_CONNECTED,
|
WSC_NOT_CONNECTED,
|
||||||
WSC_HEADER,
|
WSC_HEADER,
|
||||||
WSC_BODY,
|
|
||||||
WSC_CONNECTED
|
WSC_CONNECTED
|
||||||
} WSclientsStatus_t;
|
} WSclientsStatus_t;
|
||||||
|
|
||||||
@ -261,44 +235,34 @@ typedef struct {
|
|||||||
} WSMessageHeader_t;
|
} WSMessageHeader_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void init(uint8_t num,
|
uint8_t num; ///< connection number
|
||||||
uint32_t pingInterval,
|
|
||||||
uint32_t pongTimeout,
|
|
||||||
uint8_t disconnectTimeoutCount) {
|
|
||||||
this->num = num;
|
|
||||||
this->pingInterval = pingInterval;
|
|
||||||
this->pongTimeout = pongTimeout;
|
|
||||||
this->disconnectTimeoutCount = disconnectTimeoutCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t num = 0; ///< connection number
|
WSclientsStatus_t status;
|
||||||
|
|
||||||
WSclientsStatus_t status = WSC_NOT_CONNECTED;
|
WEBSOCKETS_NETWORK_CLASS * tcp;
|
||||||
|
|
||||||
WEBSOCKETS_NETWORK_CLASS * tcp = nullptr;
|
bool isSocketIO; ///< client for socket.io server
|
||||||
|
|
||||||
bool isSocketIO = false; ///< client for socket.io server
|
|
||||||
|
|
||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
bool isSSL = false; ///< run in ssl mode
|
bool isSSL; ///< run in ssl mode
|
||||||
WEBSOCKETS_NETWORK_SSL_CLASS * ssl;
|
WEBSOCKETS_NETWORK_SSL_CLASS * ssl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
String cUrl; ///< http url
|
String cUrl; ///< http url
|
||||||
uint16_t cCode = 0; ///< http code
|
uint16_t cCode; ///< http code
|
||||||
|
|
||||||
bool cIsClient = false; ///< will be used for masking
|
bool cIsClient = false; ///< will be used for masking
|
||||||
bool cIsUpgrade = false; ///< Connection == Upgrade
|
bool cIsUpgrade; ///< Connection == Upgrade
|
||||||
bool cIsWebsocket = false; ///< Upgrade == websocket
|
bool cIsWebsocket; ///< Upgrade == websocket
|
||||||
|
|
||||||
String cSessionId; ///< client Set-Cookie (session id)
|
String cSessionId; ///< client Set-Cookie (session id)
|
||||||
String cKey; ///< client Sec-WebSocket-Key
|
String cKey; ///< client Sec-WebSocket-Key
|
||||||
String cAccept; ///< client Sec-WebSocket-Accept
|
String cAccept; ///< client Sec-WebSocket-Accept
|
||||||
String cProtocol; ///< client Sec-WebSocket-Protocol
|
String cProtocol; ///< client Sec-WebSocket-Protocol
|
||||||
String cExtensions; ///< client Sec-WebSocket-Extensions
|
String cExtensions; ///< client Sec-WebSocket-Extensions
|
||||||
uint16_t cVersion = 0; ///< client Sec-WebSocket-Version
|
uint16_t cVersion; ///< client Sec-WebSocket-Version
|
||||||
|
|
||||||
uint8_t cWsRXsize = 0; ///< State of the RX
|
uint8_t cWsRXsize; ///< State of the RX
|
||||||
uint8_t cWsHeader[WEBSOCKETS_MAX_HEADER_SIZE]; ///< RX WS Message buffer
|
uint8_t cWsHeader[WEBSOCKETS_MAX_HEADER_SIZE]; ///< RX WS Message buffer
|
||||||
WSMessageHeader_t cWsHeaderDecode;
|
WSMessageHeader_t cWsHeaderDecode;
|
||||||
|
|
||||||
@ -307,15 +271,15 @@ typedef struct {
|
|||||||
|
|
||||||
String extraHeaders;
|
String extraHeaders;
|
||||||
|
|
||||||
bool cHttpHeadersValid = false; ///< non-websocket http header validity indicator
|
bool cHttpHeadersValid; ///< non-websocket http header validity indicator
|
||||||
size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count
|
size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count
|
||||||
|
|
||||||
bool pongReceived = false;
|
bool pongReceived;
|
||||||
uint32_t pingInterval = 0; // how often ping will be sent, 0 means "heartbeat is not active"
|
uint32_t pingInterval; // how often ping will be sent, 0 means "heartbeat is not active"
|
||||||
uint32_t lastPing = 0; // millis when last pong has been received
|
uint32_t lastPing; // millis when last pong has been received
|
||||||
uint32_t pongTimeout = 0; // interval in millis after which pong is considered to timeout
|
uint32_t pongTimeout; // interval in millis after which pong is considered to timeout
|
||||||
uint8_t disconnectTimeoutCount = 0; // after how many subsequent pong timeouts discconnect will happen, 0 means "do not disconnect"
|
uint8_t disconnectTimeoutCount; // after how many subsequent pong timeouts discconnect will happen, 0 means "do not disconnect"
|
||||||
uint8_t pongTimeoutCount = 0; // current pong timeout count
|
uint8_t pongTimeoutCount; // current pong timeout count
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
String cHttpLine; ///< HTTP header lines
|
String cHttpLine; ///< HTTP header lines
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file WebSocketsServer.cpp
|
|
||||||
* @date 28.10.2020
|
|
||||||
* @author Markus Sattler & esp8266/arduino community
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Markus Sattler. All rights reserved.
|
|
||||||
* This file is part of the WebSockets for Arduino.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __WEBSOCKETS4WEBSERVER_H
|
|
||||||
#define __WEBSOCKETS4WEBSERVER_H
|
|
||||||
|
|
||||||
#include <WebSocketsServer.h>
|
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
|
|
||||||
#if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK
|
|
||||||
|
|
||||||
class WebSockets4WebServer : public WebSocketsServerCore {
|
|
||||||
public:
|
|
||||||
WebSockets4WebServer(const String & origin = "", const String & protocol = "arduino")
|
|
||||||
: WebSocketsServerCore(origin, protocol) {
|
|
||||||
begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP8266WebServer::HookFunction hookForWebserver(const String & wsRootDir, WebSocketServerEvent event) {
|
|
||||||
onEvent(event);
|
|
||||||
|
|
||||||
return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, ESP8266WebServer::ContentTypeFunction contentType) {
|
|
||||||
(void)contentType;
|
|
||||||
|
|
||||||
if(!(method == "GET" && url.indexOf(wsRootDir) == 0)) {
|
|
||||||
return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate a WiFiClient copy (like in WebSocketsServer::handleNewClients())
|
|
||||||
WEBSOCKETS_NETWORK_CLASS * newTcpClient = new WEBSOCKETS_NETWORK_CLASS(*tcpClient);
|
|
||||||
|
|
||||||
// Then initialize a new WSclient_t (like in WebSocketsServer::handleNewClient())
|
|
||||||
WSclient_t * client = handleNewClient(newTcpClient);
|
|
||||||
|
|
||||||
if(client) {
|
|
||||||
// give "GET <url>"
|
|
||||||
String headerLine;
|
|
||||||
headerLine.reserve(url.length() + 5);
|
|
||||||
headerLine = "GET ";
|
|
||||||
headerLine += url;
|
|
||||||
handleHeader(client, &headerLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tell webserver to not close but forget about this client
|
|
||||||
return ESP8266WebServer::CLIENT_IS_GIVEN;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#else // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK
|
|
||||||
|
|
||||||
#ifndef WEBSERVER_HAS_HOOK
|
|
||||||
#error Your current Framework / Arduino core version does not support Webserver Hook Functions
|
|
||||||
#else
|
|
||||||
#error Your Hardware Platform does not support Webserver Hook Functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK
|
|
||||||
|
|
||||||
#endif // __WEBSOCKETS4WEBSERVER_H
|
|
@ -30,9 +30,6 @@ WebSocketsClient::WebSocketsClient() {
|
|||||||
_client.num = 0;
|
_client.num = 0;
|
||||||
_client.cIsClient = true;
|
_client.cIsClient = true;
|
||||||
_client.extraHeaders = WEBSOCKETS_STRING("Origin: file://");
|
_client.extraHeaders = WEBSOCKETS_STRING("Origin: file://");
|
||||||
_reconnectInterval = 500;
|
|
||||||
_port = 0;
|
|
||||||
_host = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketsClient::~WebSocketsClient() {
|
WebSocketsClient::~WebSocketsClient() {
|
||||||
@ -46,7 +43,7 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
|
|||||||
_host = host;
|
_host = host;
|
||||||
_port = port;
|
_port = port;
|
||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
_fingerprint = "";
|
||||||
_CA_cert = NULL;
|
_CA_cert = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -85,9 +82,7 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
_lastConnectionFail = 0;
|
_lastConnectionFail = 0;
|
||||||
_lastHeaderSent = 0;
|
_reconnectInterval = 500;
|
||||||
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client] Websocket Version: " WEBSOCKETS_VERSION "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketsClient::begin(String host, uint16_t port, String url, String protocol) {
|
void WebSocketsClient::begin(String host, uint16_t port, String url, String protocol) {
|
||||||
@ -99,7 +94,6 @@ void WebSocketsClient::begin(IPAddress host, uint16_t port, const char * url, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
#if defined(SSL_AXTLS)
|
|
||||||
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const char * fingerprint, const char * protocol) {
|
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const char * fingerprint, const char * protocol) {
|
||||||
begin(host, port, url, protocol);
|
begin(host, port, url, protocol);
|
||||||
_client.isSSL = true;
|
_client.isSSL = true;
|
||||||
@ -114,39 +108,10 @@ void WebSocketsClient::beginSSL(String host, uint16_t port, String url, String f
|
|||||||
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
||||||
begin(host, port, url, protocol);
|
begin(host, port, url, protocol);
|
||||||
_client.isSSL = true;
|
_client.isSSL = true;
|
||||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
_fingerprint = "";
|
||||||
_CA_cert = CA_cert;
|
_CA_cert = CA_cert;
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const uint8_t * fingerprint, const char * protocol) {
|
|
||||||
begin(host, port, url, protocol);
|
|
||||||
_client.isSSL = true;
|
|
||||||
_fingerprint = fingerprint;
|
|
||||||
_CA_cert = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
|
|
||||||
begin(host, port, url, protocol);
|
|
||||||
_client.isSSL = true;
|
|
||||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
|
||||||
_CA_cert = CA_cert;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
|
||||||
beginSslWithCA(host, port, url, new BearSSL::X509List(CA_cert), protocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebSocketsClient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
|
|
||||||
_client_cert = clientCert;
|
|
||||||
_client_key = clientPrivateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebSocketsClient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
|
|
||||||
setSSLClientCertKey(new BearSSL::X509List(clientCert), new BearSSL::PrivateKey(clientPrivateKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SSL_AXTLS
|
|
||||||
#endif // HAS_SSL
|
|
||||||
|
|
||||||
void WebSocketsClient::beginSocketIO(const char * host, uint16_t port, const char * url, const char * protocol) {
|
void WebSocketsClient::beginSocketIO(const char * host, uint16_t port, const char * url, const char * protocol) {
|
||||||
begin(host, port, url, protocol);
|
begin(host, port, url, protocol);
|
||||||
@ -162,35 +127,20 @@ void WebSocketsClient::beginSocketIOSSL(const char * host, uint16_t port, const
|
|||||||
begin(host, port, url, protocol);
|
begin(host, port, url, protocol);
|
||||||
_client.isSocketIO = true;
|
_client.isSocketIO = true;
|
||||||
_client.isSSL = true;
|
_client.isSSL = true;
|
||||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
_fingerprint = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketsClient::beginSocketIOSSL(String host, uint16_t port, String url, String protocol) {
|
void WebSocketsClient::beginSocketIOSSL(String host, uint16_t port, String url, String protocol) {
|
||||||
beginSocketIOSSL(host.c_str(), port, url.c_str(), protocol.c_str());
|
beginSocketIOSSL(host.c_str(), port, url.c_str(), protocol.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SSL_BARESSL)
|
|
||||||
void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
|
|
||||||
begin(host, port, url, protocol);
|
|
||||||
_client.isSocketIO = true;
|
|
||||||
_client.isSSL = true;
|
|
||||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
|
||||||
_CA_cert = CA_cert;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
||||||
begin(host, port, url, protocol);
|
begin(host, port, url, protocol);
|
||||||
_client.isSocketIO = true;
|
_client.isSocketIO = true;
|
||||||
_client.isSSL = true;
|
_client.isSSL = true;
|
||||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
_fingerprint = "";
|
||||||
#if defined(SSL_BARESSL)
|
|
||||||
_CA_cert = new BearSSL::X509List(CA_cert);
|
|
||||||
#else
|
|
||||||
_CA_cert = CA_cert;
|
_CA_cert = CA_cert;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
@ -198,10 +148,6 @@ void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, uint16_t port,
|
|||||||
* called in arduino loop
|
* called in arduino loop
|
||||||
*/
|
*/
|
||||||
void WebSocketsClient::loop(void) {
|
void WebSocketsClient::loop(void) {
|
||||||
if(_port == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
if(!clientIsConnected(&_client)) {
|
if(!clientIsConnected(&_client)) {
|
||||||
// do not flood the server
|
// do not flood the server
|
||||||
if((millis() - _lastConnectionFail) < _reconnectInterval) {
|
if((millis() - _lastConnectionFail) < _reconnectInterval) {
|
||||||
@ -222,25 +168,10 @@ void WebSocketsClient::loop(void) {
|
|||||||
DEBUG_WEBSOCKETS("[WS-Client] setting CA certificate");
|
DEBUG_WEBSOCKETS("[WS-Client] setting CA certificate");
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
_client.ssl->setCACert(_CA_cert);
|
_client.ssl->setCACert(_CA_cert);
|
||||||
#elif defined(ESP8266) && defined(SSL_AXTLS)
|
#elif defined(ESP8266)
|
||||||
_client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1);
|
_client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1);
|
||||||
#elif defined(ESP8266) && defined(SSL_BARESSL)
|
|
||||||
_client.ssl->setTrustAnchors(_CA_cert);
|
|
||||||
#else
|
#else
|
||||||
#error setCACert not implemented
|
#error setCACert not implemented
|
||||||
#endif
|
|
||||||
#if defined(ESP32)
|
|
||||||
} else if(!SSL_FINGERPRINT_IS_SET) {
|
|
||||||
_client.ssl->setInsecure();
|
|
||||||
#elif defined(SSL_BARESSL)
|
|
||||||
} else if(SSL_FINGERPRINT_IS_SET) {
|
|
||||||
_client.ssl->setFingerprint(_fingerprint);
|
|
||||||
} else {
|
|
||||||
_client.ssl->setInsecure();
|
|
||||||
}
|
|
||||||
if(_client_cert && _client_key) {
|
|
||||||
_client.ssl->setClientRSACert(_client_cert, _client_key);
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client] setting client certificate and key");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -259,7 +190,6 @@ void WebSocketsClient::loop(void) {
|
|||||||
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
|
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
if(_client.tcp->connect(_host.c_str(), _port, WEBSOCKETS_TCP_TIMEOUT)) {
|
if(_client.tcp->connect(_host.c_str(), _port, WEBSOCKETS_TCP_TIMEOUT)) {
|
||||||
#else
|
#else
|
||||||
@ -273,7 +203,7 @@ void WebSocketsClient::loop(void) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleClientData();
|
handleClientData();
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
if(_client.status == WSC_CONNECTED) {
|
if(_client.status == WSC_CONNECTED) {
|
||||||
handleHBPing();
|
handleHBPing();
|
||||||
handleHBTimeout(&_client);
|
handleHBTimeout(&_client);
|
||||||
@ -511,7 +441,6 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
|
|||||||
client->cSessionId = "";
|
client->cSessionId = "";
|
||||||
|
|
||||||
client->status = WSC_NOT_CONNECTED;
|
client->status = WSC_NOT_CONNECTED;
|
||||||
_lastConnectionFail = millis();
|
|
||||||
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client] client disconnected.\n");
|
DEBUG_WEBSOCKETS("[WS-Client] client disconnected.\n");
|
||||||
if(event) {
|
if(event) {
|
||||||
@ -554,13 +483,6 @@ bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
|
|||||||
* Handel incomming data from Client
|
* Handel incomming data from Client
|
||||||
*/
|
*/
|
||||||
void WebSocketsClient::handleClientData(void) {
|
void WebSocketsClient::handleClientData(void) {
|
||||||
if((_client.status == WSC_HEADER || _client.status == WSC_BODY) && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) {
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleClientData] header response timeout.. disconnecting!\n");
|
|
||||||
clientDisconnect(&_client);
|
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int len = _client.tcp->available();
|
int len = _client.tcp->available();
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
switch(_client.status) {
|
switch(_client.status) {
|
||||||
@ -568,12 +490,6 @@ void WebSocketsClient::handleClientData(void) {
|
|||||||
String headerLine = _client.tcp->readStringUntil('\n');
|
String headerLine = _client.tcp->readStringUntil('\n');
|
||||||
handleHeader(&_client, &headerLine);
|
handleHeader(&_client, &headerLine);
|
||||||
} break;
|
} break;
|
||||||
case WSC_BODY: {
|
|
||||||
char buf[256] = { 0 };
|
|
||||||
_client.tcp->readBytes(&buf[0], std::min((size_t)len, sizeof(buf)));
|
|
||||||
String bodyLine = buf;
|
|
||||||
handleHeader(&_client, &bodyLine);
|
|
||||||
} break;
|
|
||||||
case WSC_CONNECTED:
|
case WSC_CONNECTED:
|
||||||
WebSockets::handleWebsocket(&_client);
|
WebSockets::handleWebsocket(&_client);
|
||||||
break;
|
break;
|
||||||
@ -582,7 +498,9 @@ void WebSocketsClient::handleClientData(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
|
delay(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -649,7 +567,7 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add extra headers; by default this includes "Origin: file://"
|
// add extra headers; by default this includes "Origin: file://"
|
||||||
if(client->extraHeaders.length() > 0) {
|
if(client->extraHeaders) {
|
||||||
handshake += client->extraHeaders + NEW_LINE;
|
handshake += client->extraHeaders + NEW_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +593,6 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header... Done (%luus).\n", (micros() - start));
|
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header... Done (%luus).\n", (micros() - start));
|
||||||
_lastHeaderSent = millis();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -685,22 +602,6 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
|
|||||||
void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||||
headerLine->trim(); // remove \r
|
headerLine->trim(); // remove \r
|
||||||
|
|
||||||
// this code handels the http body for Socket.IO V3 requests
|
|
||||||
if(headerLine->length() > 0 && client->isSocketIO && client->status == WSC_BODY && client->cSessionId.length() == 0) {
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] socket.io json: %s\n", headerLine->c_str());
|
|
||||||
String sid_begin = WEBSOCKETS_STRING("\"sid\":\"");
|
|
||||||
if(headerLine->indexOf(sid_begin) > -1) {
|
|
||||||
int start = headerLine->indexOf(sid_begin) + sid_begin.length();
|
|
||||||
int end = headerLine->indexOf('"', start);
|
|
||||||
client->cSessionId = headerLine->substring(start, end);
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cSessionId: %s\n", client->cSessionId.c_str());
|
|
||||||
|
|
||||||
// Trigger websocket connection code path
|
|
||||||
*headerLine = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// headle HTTP header
|
|
||||||
if(headerLine->length() > 0) {
|
if(headerLine->length() > 0) {
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] RX: %s\n", headerLine->c_str());
|
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] RX: %s\n", headerLine->c_str());
|
||||||
|
|
||||||
@ -734,7 +635,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
|
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
|
||||||
client->cVersion = headerValue.toInt();
|
client->cVersion = headerValue.toInt();
|
||||||
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) {
|
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) {
|
||||||
if(headerValue.indexOf(';') > -1) {
|
if(headerValue.indexOf(WEBSOCKETS_STRING("HttpOnly")) > -1) {
|
||||||
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";"));
|
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";"));
|
||||||
} else {
|
} else {
|
||||||
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1);
|
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1);
|
||||||
@ -765,14 +666,6 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cVersion: %d\n", client->cVersion);
|
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cVersion: %d\n", client->cVersion);
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cSessionId: %s\n", client->cSessionId.c_str());
|
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cSessionId: %s\n", client->cSessionId.c_str());
|
||||||
|
|
||||||
if(client->isSocketIO && client->cSessionId.length() == 0 && clientIsConnected(client)) {
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still missing cSessionId try socket.io V3\n");
|
|
||||||
client->status = WSC_BODY;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
client->status = WSC_HEADER;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = (client->cIsUpgrade && client->cIsWebsocket);
|
bool ok = (client->cIsUpgrade && client->cIsWebsocket);
|
||||||
|
|
||||||
if(ok) {
|
if(ok) {
|
||||||
@ -813,11 +706,8 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
headerDone(client);
|
headerDone(client);
|
||||||
|
|
||||||
runCbEvent(WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length());
|
runCbEvent(WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length());
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
|
||||||
} else if(client->isSocketIO) {
|
if(_client.tcp->available()) {
|
||||||
if(client->cSessionId.length() > 0) {
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] found cSessionId\n");
|
|
||||||
if(clientIsConnected(client) && _client.tcp->available()) {
|
|
||||||
// read not needed data
|
// read not needed data
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available());
|
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available());
|
||||||
while(_client.tcp->available() > 0) {
|
while(_client.tcp->available() > 0) {
|
||||||
@ -825,8 +715,6 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendHeader(client);
|
sendHeader(client);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
|
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
|
||||||
_lastConnectionFail = millis();
|
_lastConnectionFail = millis();
|
||||||
@ -867,18 +755,14 @@ void WebSocketsClient::connectedCb() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
#if defined(SSL_AXTLS) || defined(ESP32)
|
if(_client.isSSL && _fingerprint.length()) {
|
||||||
if(_client.isSSL && SSL_FINGERPRINT_IS_SET) {
|
|
||||||
if(!_client.ssl->verify(_fingerprint.c_str(), _host.c_str())) {
|
if(!_client.ssl->verify(_fingerprint.c_str(), _host.c_str())) {
|
||||||
DEBUG_WEBSOCKETS("[WS-Client] certificate mismatch\n");
|
DEBUG_WEBSOCKETS("[WS-Client] certificate mismatch\n");
|
||||||
WebSockets::clientDisconnect(&_client, 1000);
|
WebSockets::clientDisconnect(&_client, 1000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if(_client.isSSL && SSL_FINGERPRINT_IS_SET) {
|
|
||||||
#endif
|
|
||||||
} else if(_client.isSSL && !_CA_cert) {
|
} else if(_client.isSSL && !_CA_cert) {
|
||||||
#if defined(SSL_BARESSL)
|
#if defined(wificlientbearssl_h) && !defined(USING_AXTLS) && !defined(wificlientsecure_h)
|
||||||
_client.ssl->setInsecure();
|
_client.ssl->setInsecure();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -948,9 +832,6 @@ void WebSocketsClient::handleHBPing() {
|
|||||||
if(sendPing()) {
|
if(sendPing()) {
|
||||||
_client.lastPing = millis();
|
_client.lastPing = millis();
|
||||||
_client.pongReceived = false;
|
_client.pongReceived = false;
|
||||||
} else {
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Client] sending HB ping failed\n");
|
|
||||||
WebSockets::clientDisconnect(&_client, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,15 +43,8 @@ class WebSocketsClient : protected WebSockets {
|
|||||||
void begin(IPAddress host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
void begin(IPAddress host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||||
|
|
||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
#ifdef SSL_AXTLS
|
void beginSSL(const char * host, uint16_t port, const char * url = "/", const char * = "", const char * protocol = "arduino");
|
||||||
void beginSSL(const char * host, uint16_t port, const char * url = "/", const char * fingerprint = "", const char * protocol = "arduino");
|
|
||||||
void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino");
|
void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino");
|
||||||
#else
|
|
||||||
void beginSSL(const char * host, uint16_t port, const char * url = "/", const uint8_t * fingerprint = NULL, const char * protocol = "arduino");
|
|
||||||
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino");
|
|
||||||
void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL);
|
|
||||||
void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL);
|
|
||||||
#endif
|
|
||||||
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino");
|
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -61,11 +54,7 @@ class WebSocketsClient : protected WebSockets {
|
|||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
void beginSocketIOSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
void beginSocketIOSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||||
void beginSocketIOSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
void beginSocketIOSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
||||||
|
|
||||||
void beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * CA_cert = NULL, const char * protocol = "arduino");
|
void beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * CA_cert = NULL, const char * protocol = "arduino");
|
||||||
#if defined(SSL_BARESSL)
|
|
||||||
void beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino");
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
@ -102,27 +91,15 @@ class WebSocketsClient : protected WebSockets {
|
|||||||
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
|
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
|
||||||
void disableHeartbeat();
|
void disableHeartbeat();
|
||||||
|
|
||||||
bool isConnected(void);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
String _host;
|
String _host;
|
||||||
uint16_t _port;
|
uint16_t _port;
|
||||||
|
|
||||||
|
bool isConnected(void);
|
||||||
|
|
||||||
#if defined(HAS_SSL)
|
#if defined(HAS_SSL)
|
||||||
#ifdef SSL_AXTLS
|
|
||||||
String _fingerprint;
|
String _fingerprint;
|
||||||
const char * _CA_cert;
|
const char * _CA_cert;
|
||||||
#define SSL_FINGERPRINT_IS_SET (_fingerprint.length())
|
|
||||||
#define SSL_FINGERPRINT_NULL ""
|
|
||||||
#else
|
|
||||||
const uint8_t * _fingerprint;
|
|
||||||
BearSSL::X509List * _CA_cert;
|
|
||||||
BearSSL::X509List * _client_cert;
|
|
||||||
BearSSL::PrivateKey * _client_key;
|
|
||||||
#define SSL_FINGERPRINT_IS_SET (_fingerprint != NULL)
|
|
||||||
#define SSL_FINGERPRINT_NULL NULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
WSclient_t _client;
|
WSclient_t _client;
|
||||||
|
|
||||||
@ -130,7 +107,6 @@ class WebSocketsClient : protected WebSockets {
|
|||||||
|
|
||||||
unsigned long _lastConnectionFail;
|
unsigned long _lastConnectionFail;
|
||||||
unsigned long _reconnectInterval;
|
unsigned long _reconnectInterval;
|
||||||
unsigned long _lastHeaderSent;
|
|
||||||
|
|
||||||
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
|
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
|
||||||
|
|
||||||
|
@ -25,36 +25,31 @@
|
|||||||
#include "WebSockets.h"
|
#include "WebSockets.h"
|
||||||
#include "WebSocketsServer.h"
|
#include "WebSocketsServer.h"
|
||||||
|
|
||||||
WebSocketsServerCore::WebSocketsServerCore(const String & origin, const String & protocol) {
|
WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol) {
|
||||||
|
_port = port;
|
||||||
_origin = origin;
|
_origin = origin;
|
||||||
_protocol = protocol;
|
_protocol = protocol;
|
||||||
_runnning = false;
|
_runnning = false;
|
||||||
_pingInterval = 0;
|
|
||||||
_pongTimeout = 0;
|
_server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
|
||||||
_disconnectTimeoutCount = 0;
|
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
|
_server->onClient([](void * s, AsyncClient * c) {
|
||||||
|
((WebSocketsServer *)s)->newClient(new AsyncTCPbuffer(c));
|
||||||
|
},
|
||||||
|
this);
|
||||||
|
#endif
|
||||||
|
|
||||||
_cbEvent = NULL;
|
_cbEvent = NULL;
|
||||||
|
|
||||||
_httpHeaderValidationFunc = NULL;
|
_httpHeaderValidationFunc = NULL;
|
||||||
_mandatoryHttpHeaders = NULL;
|
_mandatoryHttpHeaders = NULL;
|
||||||
_mandatoryHttpHeaderCount = 0;
|
_mandatoryHttpHeaderCount = 0;
|
||||||
|
|
||||||
|
memset(&_clients[0], 0x00, (sizeof(WSclient_t) * WEBSOCKETS_SERVER_CLIENT_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketsServer::WebSocketsServer(uint16_t port, const String & origin, const String & protocol)
|
WebSocketsServer::~WebSocketsServer() {
|
||||||
: WebSocketsServerCore(origin, protocol) {
|
|
||||||
_port = port;
|
|
||||||
|
|
||||||
_server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
|
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
|
||||||
_server->onClient([](void * s, AsyncClient * c) {
|
|
||||||
((WebSocketsServerCore *)s)->newClient(new AsyncTCPbuffer(c));
|
|
||||||
},
|
|
||||||
this);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
WebSocketsServerCore::~WebSocketsServerCore() {
|
|
||||||
// disconnect all clients
|
// disconnect all clients
|
||||||
close();
|
close();
|
||||||
|
|
||||||
@ -64,20 +59,38 @@ WebSocketsServerCore::~WebSocketsServerCore() {
|
|||||||
_mandatoryHttpHeaderCount = 0;
|
_mandatoryHttpHeaderCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketsServer::~WebSocketsServer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called to initialize the Websocket server
|
* called to initialize the Websocket server
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::begin(void) {
|
void WebSocketsServer::begin(void) {
|
||||||
// adjust clients storage:
|
WSclient_t * client;
|
||||||
// _clients[i]'s constructor are already called,
|
|
||||||
// all its members are initialized to their default value,
|
// init client storage
|
||||||
// except the ones explicitly detailed in WSclient_t() constructor.
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
// Then we need to initialize some members to non-trivial values:
|
client = &_clients[i];
|
||||||
for(int i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
|
||||||
_clients[i].init(i, _pingInterval, _pongTimeout, _disconnectTimeoutCount);
|
client->num = i;
|
||||||
|
client->status = WSC_NOT_CONNECTED;
|
||||||
|
client->tcp = NULL;
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
|
client->isSSL = false;
|
||||||
|
client->ssl = NULL;
|
||||||
|
#endif
|
||||||
|
client->cUrl = "";
|
||||||
|
client->cCode = 0;
|
||||||
|
client->cKey = "";
|
||||||
|
client->cProtocol = "";
|
||||||
|
client->cVersion = 0;
|
||||||
|
client->cIsUpgrade = false;
|
||||||
|
client->cIsWebsocket = false;
|
||||||
|
|
||||||
|
client->base64Authorization = "";
|
||||||
|
|
||||||
|
client->cWsRXsize = 0;
|
||||||
|
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
|
client->cHttpLine = "";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
@ -91,26 +104,41 @@ void WebSocketsServerCore::begin(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
_runnning = true;
|
_runnning = true;
|
||||||
|
_server->begin();
|
||||||
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Server] Websocket Version: " WEBSOCKETS_VERSION "\n");
|
DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketsServerCore::close(void) {
|
void WebSocketsServer::close(void) {
|
||||||
_runnning = false;
|
_runnning = false;
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|
||||||
// restore _clients[] to their initial state
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
// before next call to ::begin()
|
_server->close();
|
||||||
for(int i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
_clients[i] = WSclient_t();
|
_server->end();
|
||||||
|
#else
|
||||||
|
// TODO how to close server?
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
|
/**
|
||||||
|
* called in arduino loop
|
||||||
|
*/
|
||||||
|
void WebSocketsServer::loop(void) {
|
||||||
|
if(_runnning) {
|
||||||
|
handleNewClients();
|
||||||
|
handleClientData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set callback function
|
* set callback function
|
||||||
* @param cbEvent WebSocketServerEvent
|
* @param cbEvent WebSocketServerEvent
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::onEvent(WebSocketServerEvent cbEvent) {
|
void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) {
|
||||||
_cbEvent = cbEvent;
|
_cbEvent = cbEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +148,7 @@ void WebSocketsServerCore::onEvent(WebSocketServerEvent cbEvent) {
|
|||||||
* @param mandatoryHttpHeaders[] const char* ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed
|
* @param mandatoryHttpHeaders[] const char* ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed
|
||||||
* @param mandatoryHttpHeaderCount size_t ///< the number of items in the mandatoryHttpHeaders array
|
* @param mandatoryHttpHeaderCount size_t ///< the number of items in the mandatoryHttpHeaders array
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::onValidateHttpHeader(
|
void WebSocketsServer::onValidateHttpHeader(
|
||||||
WebSocketServerHttpHeaderValFunc validationFunc,
|
WebSocketServerHttpHeaderValFunc validationFunc,
|
||||||
const char * mandatoryHttpHeaders[],
|
const char * mandatoryHttpHeaders[],
|
||||||
size_t mandatoryHttpHeaderCount) {
|
size_t mandatoryHttpHeaderCount) {
|
||||||
@ -145,7 +173,7 @@ void WebSocketsServerCore::onValidateHttpHeader(
|
|||||||
* @param headerToPayload bool (see sendFrame for more details)
|
* @param headerToPayload bool (see sendFrame for more details)
|
||||||
* @return true if ok
|
* @return true if ok
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
|
bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
|
||||||
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -159,19 +187,19 @@ bool WebSocketsServerCore::sendTXT(uint8_t num, uint8_t * payload, size_t length
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::sendTXT(uint8_t num, const uint8_t * payload, size_t length) {
|
bool WebSocketsServer::sendTXT(uint8_t num, const uint8_t * payload, size_t length) {
|
||||||
return sendTXT(num, (uint8_t *)payload, length);
|
return sendTXT(num, (uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) {
|
bool WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) {
|
||||||
return sendTXT(num, (uint8_t *)payload, length, headerToPayload);
|
return sendTXT(num, (uint8_t *)payload, length, headerToPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::sendTXT(uint8_t num, const char * payload, size_t length) {
|
bool WebSocketsServer::sendTXT(uint8_t num, const char * payload, size_t length) {
|
||||||
return sendTXT(num, (uint8_t *)payload, length);
|
return sendTXT(num, (uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::sendTXT(uint8_t num, String & payload) {
|
bool WebSocketsServer::sendTXT(uint8_t num, String & payload) {
|
||||||
return sendTXT(num, (uint8_t *)payload.c_str(), payload.length());
|
return sendTXT(num, (uint8_t *)payload.c_str(), payload.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +210,7 @@ bool WebSocketsServerCore::sendTXT(uint8_t num, String & payload) {
|
|||||||
* @param headerToPayload bool (see sendFrame for more details)
|
* @param headerToPayload bool (see sendFrame for more details)
|
||||||
* @return true if ok
|
* @return true if ok
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) {
|
bool WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if(length == 0) {
|
if(length == 0) {
|
||||||
@ -196,24 +224,26 @@ bool WebSocketsServerCore::broadcastTXT(uint8_t * payload, size_t length, bool h
|
|||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
|
delay(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::broadcastTXT(const uint8_t * payload, size_t length) {
|
bool WebSocketsServer::broadcastTXT(const uint8_t * payload, size_t length) {
|
||||||
return broadcastTXT((uint8_t *)payload, length);
|
return broadcastTXT((uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::broadcastTXT(char * payload, size_t length, bool headerToPayload) {
|
bool WebSocketsServer::broadcastTXT(char * payload, size_t length, bool headerToPayload) {
|
||||||
return broadcastTXT((uint8_t *)payload, length, headerToPayload);
|
return broadcastTXT((uint8_t *)payload, length, headerToPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::broadcastTXT(const char * payload, size_t length) {
|
bool WebSocketsServer::broadcastTXT(const char * payload, size_t length) {
|
||||||
return broadcastTXT((uint8_t *)payload, length);
|
return broadcastTXT((uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::broadcastTXT(String & payload) {
|
bool WebSocketsServer::broadcastTXT(String & payload) {
|
||||||
return broadcastTXT((uint8_t *)payload.c_str(), payload.length());
|
return broadcastTXT((uint8_t *)payload.c_str(), payload.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +255,7 @@ bool WebSocketsServerCore::broadcastTXT(String & payload) {
|
|||||||
* @param headerToPayload bool (see sendFrame for more details)
|
* @param headerToPayload bool (see sendFrame for more details)
|
||||||
* @return true if ok
|
* @return true if ok
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
|
bool WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
|
||||||
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -236,7 +266,7 @@ bool WebSocketsServerCore::sendBIN(uint8_t num, uint8_t * payload, size_t length
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::sendBIN(uint8_t num, const uint8_t * payload, size_t length) {
|
bool WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t length) {
|
||||||
return sendBIN(num, (uint8_t *)payload, length);
|
return sendBIN(num, (uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +277,7 @@ bool WebSocketsServerCore::sendBIN(uint8_t num, const uint8_t * payload, size_t
|
|||||||
* @param headerToPayload bool (see sendFrame for more details)
|
* @param headerToPayload bool (see sendFrame for more details)
|
||||||
* @return true if ok
|
* @return true if ok
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) {
|
bool WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
@ -257,12 +287,14 @@ bool WebSocketsServerCore::broadcastBIN(uint8_t * payload, size_t length, bool h
|
|||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
|
delay(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::broadcastBIN(const uint8_t * payload, size_t length) {
|
bool WebSocketsServer::broadcastBIN(const uint8_t * payload, size_t length) {
|
||||||
return broadcastBIN((uint8_t *)payload, length);
|
return broadcastBIN((uint8_t *)payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +305,7 @@ bool WebSocketsServerCore::broadcastBIN(const uint8_t * payload, size_t length)
|
|||||||
* @param length size_t
|
* @param length size_t
|
||||||
* @return true if ping is send out
|
* @return true if ping is send out
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::sendPing(uint8_t num, uint8_t * payload, size_t length) {
|
bool WebSocketsServer::sendPing(uint8_t num, uint8_t * payload, size_t length) {
|
||||||
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -284,7 +316,7 @@ bool WebSocketsServerCore::sendPing(uint8_t num, uint8_t * payload, size_t lengt
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::sendPing(uint8_t num, String & payload) {
|
bool WebSocketsServer::sendPing(uint8_t num, String & payload) {
|
||||||
return sendPing(num, (uint8_t *)payload.c_str(), payload.length());
|
return sendPing(num, (uint8_t *)payload.c_str(), payload.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +326,7 @@ bool WebSocketsServerCore::sendPing(uint8_t num, String & payload) {
|
|||||||
* @param length size_t
|
* @param length size_t
|
||||||
* @return true if ping is send out
|
* @return true if ping is send out
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::broadcastPing(uint8_t * payload, size_t length) {
|
bool WebSocketsServer::broadcastPing(uint8_t * payload, size_t length) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
@ -304,19 +336,21 @@ bool WebSocketsServerCore::broadcastPing(uint8_t * payload, size_t length) {
|
|||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
|
delay(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketsServerCore::broadcastPing(String & payload) {
|
bool WebSocketsServer::broadcastPing(String & payload) {
|
||||||
return broadcastPing((uint8_t *)payload.c_str(), payload.length());
|
return broadcastPing((uint8_t *)payload.c_str(), payload.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* disconnect all clients
|
* disconnect all clients
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::disconnect(void) {
|
void WebSocketsServer::disconnect(void) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
client = &_clients[i];
|
client = &_clients[i];
|
||||||
@ -330,7 +364,7 @@ void WebSocketsServerCore::disconnect(void) {
|
|||||||
* disconnect one client
|
* disconnect one client
|
||||||
* @param num uint8_t client id
|
* @param num uint8_t client id
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::disconnect(uint8_t num) {
|
void WebSocketsServer::disconnect(uint8_t num) {
|
||||||
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -345,7 +379,7 @@ void WebSocketsServerCore::disconnect(uint8_t num) {
|
|||||||
* @param user const char *
|
* @param user const char *
|
||||||
* @param password const char *
|
* @param password const char *
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::setAuthorization(const char * user, const char * password) {
|
void WebSocketsServer::setAuthorization(const char * user, const char * password) {
|
||||||
if(user && password) {
|
if(user && password) {
|
||||||
String auth = user;
|
String auth = user;
|
||||||
auth += ":";
|
auth += ":";
|
||||||
@ -358,7 +392,7 @@ void WebSocketsServerCore::setAuthorization(const char * user, const char * pass
|
|||||||
* set the Authorizatio for the http request
|
* set the Authorizatio for the http request
|
||||||
* @param auth const char * base64
|
* @param auth const char * base64
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::setAuthorization(const char * auth) {
|
void WebSocketsServer::setAuthorization(const char * auth) {
|
||||||
if(auth) {
|
if(auth) {
|
||||||
_base64Authorization = auth;
|
_base64Authorization = auth;
|
||||||
}
|
}
|
||||||
@ -368,7 +402,7 @@ void WebSocketsServerCore::setAuthorization(const char * auth) {
|
|||||||
* count the connected clients (optional ping them)
|
* count the connected clients (optional ping them)
|
||||||
* @param ping bool ping the connected clients
|
* @param ping bool ping the connected clients
|
||||||
*/
|
*/
|
||||||
int WebSocketsServerCore::connectedClients(bool ping) {
|
int WebSocketsServer::connectedClients(bool ping) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
@ -382,25 +416,13 @@ int WebSocketsServerCore::connectedClients(bool ping) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* see if one client is connected
|
|
||||||
* @param num uint8_t client id
|
|
||||||
*/
|
|
||||||
bool WebSocketsServerCore::clientIsConnected(uint8_t num) {
|
|
||||||
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
WSclient_t * client = &_clients[num];
|
|
||||||
return clientIsConnected(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
/**
|
/**
|
||||||
* get an IP for a client
|
* get an IP for a client
|
||||||
* @param num uint8_t client id
|
* @param num uint8_t client id
|
||||||
* @return IPAddress
|
* @return IPAddress
|
||||||
*/
|
*/
|
||||||
IPAddress WebSocketsServerCore::remoteIP(uint8_t num) {
|
IPAddress WebSocketsServer::remoteIP(uint8_t num) {
|
||||||
if(num < WEBSOCKETS_SERVER_CLIENT_MAX) {
|
if(num < WEBSOCKETS_SERVER_CLIENT_MAX) {
|
||||||
WSclient_t * client = &_clients[num];
|
WSclient_t * client = &_clients[num];
|
||||||
if(clientIsConnected(client)) {
|
if(clientIsConnected(client)) {
|
||||||
@ -420,7 +442,7 @@ IPAddress WebSocketsServerCore::remoteIP(uint8_t num) {
|
|||||||
* handle new client connection
|
* handle new client connection
|
||||||
* @param client
|
* @param client
|
||||||
*/
|
*/
|
||||||
WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
|
bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
// search free list entry for client
|
// search free list entry for client
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
@ -440,16 +462,14 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
|
|||||||
#endif
|
#endif
|
||||||
client->status = WSC_HEADER;
|
client->status = WSC_HEADER;
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
#ifndef NODEBUG_WEBSOCKETS
|
|
||||||
IPAddress ip = client->tcp->remoteIP();
|
IPAddress ip = client->tcp->remoteIP();
|
||||||
#endif
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d] new client from %d.%d.%d.%d\n", client->num, ip[0], ip[1], ip[2], ip[3]);
|
DEBUG_WEBSOCKETS("[WS-Server][%d] new client from %d.%d.%d.%d\n", client->num, ip[0], ip[1], ip[2], ip[3]);
|
||||||
#else
|
#else
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d] new client\n", client->num);
|
DEBUG_WEBSOCKETS("[WS-Server][%d] new client\n", client->num);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
client->tcp->onDisconnect(std::bind([](WebSocketsServerCore * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
|
client->tcp->onDisconnect(std::bind([](WebSocketsServer * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
|
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
|
||||||
|
|
||||||
AsyncTCPbuffer ** sl = &server->_clients[client->num].tcp;
|
AsyncTCPbuffer ** sl = &server->_clients[client->num].tcp;
|
||||||
@ -461,20 +481,14 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
|
|||||||
},
|
},
|
||||||
this, std::placeholders::_1, client));
|
this, std::placeholders::_1, client));
|
||||||
|
|
||||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, this, client, &(client->cHttpLine)));
|
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
client->pingInterval = _pingInterval;
|
return true;
|
||||||
client->pongTimeout = _pongTimeout;
|
|
||||||
client->disconnectTimeoutCount = _disconnectTimeoutCount;
|
|
||||||
client->lastPing = millis();
|
|
||||||
client->pongReceived = false;
|
|
||||||
|
|
||||||
return client;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -484,7 +498,7 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
|
|||||||
* @param payload uint8_t *
|
* @param payload uint8_t *
|
||||||
* @param length size_t
|
* @param length size_t
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) {
|
void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) {
|
||||||
WStype_t type = WStype_ERROR;
|
WStype_t type = WStype_ERROR;
|
||||||
|
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
@ -511,32 +525,11 @@ void WebSocketsServerCore::messageReceived(WSclient_t * client, WSopcode_t opcod
|
|||||||
runCbEvent(client->num, type, payload, length);
|
runCbEvent(client->num, type, payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Discard a native client
|
|
||||||
* @param client WSclient_t * ptr to the client struct contaning the native client "->tcp"
|
|
||||||
*/
|
|
||||||
void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
|
|
||||||
if(client->tcp) {
|
|
||||||
if(client->tcp->connected()) {
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32)
|
|
||||||
client->tcp->flush();
|
|
||||||
#endif
|
|
||||||
client->tcp->stop();
|
|
||||||
}
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
|
||||||
client->status = WSC_NOT_CONNECTED;
|
|
||||||
#else
|
|
||||||
delete client->tcp;
|
|
||||||
#endif
|
|
||||||
client->tcp = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnect an client
|
* Disconnect an client
|
||||||
* @param client WSclient_t * ptr to the client struct
|
* @param client WSclient_t * ptr to the client struct
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
|
void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
if(client->isSSL && client->ssl) {
|
if(client->isSSL && client->ssl) {
|
||||||
if(client->ssl->connected()) {
|
if(client->ssl->connected()) {
|
||||||
@ -549,7 +542,20 @@ void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dropNativeClient(client);
|
if(client->tcp) {
|
||||||
|
if(client->tcp->connected()) {
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
|
client->tcp->flush();
|
||||||
|
#endif
|
||||||
|
client->tcp->stop();
|
||||||
|
}
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
|
client->status = WSC_NOT_CONNECTED;
|
||||||
|
#else
|
||||||
|
delete client->tcp;
|
||||||
|
#endif
|
||||||
|
client->tcp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
client->cUrl = "";
|
client->cUrl = "";
|
||||||
client->cKey = "";
|
client->cKey = "";
|
||||||
@ -576,7 +582,7 @@ void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
|
|||||||
* @param client WSclient_t * ptr to the client struct
|
* @param client WSclient_t * ptr to the client struct
|
||||||
* @return true = connected
|
* @return true = connected
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::clientIsConnected(WSclient_t * client) {
|
bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
|
||||||
if(!client->tcp) {
|
if(!client->tcp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -603,30 +609,6 @@ bool WebSocketsServerCore::clientIsConnected(WSclient_t * client) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
/**
|
|
||||||
* Handle incoming Connection Request
|
|
||||||
*/
|
|
||||||
WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient) {
|
|
||||||
WSclient_t * client = newClient(tcpClient);
|
|
||||||
|
|
||||||
if(!client) {
|
|
||||||
// no free space to handle client
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
|
||||||
#ifndef NODEBUG_WEBSOCKETS
|
|
||||||
IPAddress ip = tcpClient->remoteIP();
|
|
||||||
#endif
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
|
|
||||||
#else
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n");
|
|
||||||
#endif
|
|
||||||
dropNativeClient(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle incoming Connection Request
|
* Handle incoming Connection Request
|
||||||
*/
|
*/
|
||||||
@ -634,17 +616,35 @@ void WebSocketsServer::handleNewClients(void) {
|
|||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
while(_server->hasClient()) {
|
while(_server->hasClient()) {
|
||||||
#endif
|
#endif
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
// store new connection
|
// store new connection
|
||||||
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
|
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
|
||||||
|
#else
|
||||||
|
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!tcpClient) {
|
if(!tcpClient) {
|
||||||
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
|
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNewClient(tcpClient);
|
ok = newClient(tcpClient);
|
||||||
|
|
||||||
|
if(!ok) {
|
||||||
|
// no free space to handle client
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
|
IPAddress ip = tcpClient->remoteIP();
|
||||||
|
DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
|
||||||
|
#else
|
||||||
|
DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n");
|
||||||
|
#endif
|
||||||
|
tcpClient->stop();
|
||||||
|
}
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
|
delay(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -652,7 +652,7 @@ void WebSocketsServer::handleNewClients(void) {
|
|||||||
/**
|
/**
|
||||||
* Handel incomming data from Client
|
* Handel incomming data from Client
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::handleClientData(void) {
|
void WebSocketsServer::handleClientData(void) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||||
client = &_clients[i];
|
client = &_clients[i];
|
||||||
@ -669,16 +669,14 @@ void WebSocketsServerCore::handleClientData(void) {
|
|||||||
WebSockets::handleWebsocket(client);
|
WebSockets::handleWebsocket(client);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleClientData] unknown client status %d\n", client->num, client->status);
|
|
||||||
WebSockets::clientDisconnect(client, 1002);
|
WebSockets::clientDisconnect(client, 1002);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHBPing(client);
|
|
||||||
handleHBTimeout(client);
|
|
||||||
}
|
}
|
||||||
WEBSOCKETS_YIELD();
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||||
|
delay(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -687,7 +685,7 @@ void WebSocketsServerCore::handleClientData(void) {
|
|||||||
* returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
|
* returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
|
||||||
* @param headerName String ///< the name of the header being checked
|
* @param headerName String ///< the name of the header being checked
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServerCore::hasMandatoryHeader(String headerName) {
|
bool WebSocketsServer::hasMandatoryHeader(String headerName) {
|
||||||
for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
||||||
if(_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName))
|
if(_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName))
|
||||||
return true;
|
return true;
|
||||||
@ -700,7 +698,7 @@ bool WebSocketsServerCore::hasMandatoryHeader(String headerName) {
|
|||||||
* @param client WSclient_t * ///< pointer to the client struct
|
* @param client WSclient_t * ///< pointer to the client struct
|
||||||
* @param headerLine String ///< the header being read / processed
|
* @param headerLine String ///< the header being read / processed
|
||||||
*/
|
*/
|
||||||
void WebSocketsServerCore::handleHeader(WSclient_t * client, String * headerLine) {
|
void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||||
static const char * NEW_LINE = "\r\n";
|
static const char * NEW_LINE = "\r\n";
|
||||||
|
|
||||||
headerLine->trim(); // remove \r
|
headerLine->trim(); // remove \r
|
||||||
@ -759,7 +757,7 @@ void WebSocketsServerCore::handleHeader(WSclient_t * client, String * headerLine
|
|||||||
|
|
||||||
(*headerLine) = "";
|
(*headerLine) = "";
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, this, client, &(client->cHttpLine)));
|
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num);
|
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num);
|
||||||
@ -852,97 +850,3 @@ void WebSocketsServerCore::handleHeader(WSclient_t * client, String * headerLine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* send heartbeat ping to server in set intervals
|
|
||||||
*/
|
|
||||||
void WebSocketsServerCore::handleHBPing(WSclient_t * client) {
|
|
||||||
if(client->pingInterval == 0)
|
|
||||||
return;
|
|
||||||
uint32_t pi = millis() - client->lastPing;
|
|
||||||
if(pi > client->pingInterval) {
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d] sending HB ping\n", client->num);
|
|
||||||
if(sendPing(client->num)) {
|
|
||||||
client->lastPing = millis();
|
|
||||||
client->pongReceived = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* enable ping/pong heartbeat process
|
|
||||||
* @param pingInterval uint32_t how often ping will be sent
|
|
||||||
* @param pongTimeout uint32_t millis after which pong should timout if not received
|
|
||||||
* @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect
|
|
||||||
*/
|
|
||||||
void WebSocketsServerCore::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
|
|
||||||
_pingInterval = pingInterval;
|
|
||||||
_pongTimeout = pongTimeout;
|
|
||||||
_disconnectTimeoutCount = disconnectTimeoutCount;
|
|
||||||
|
|
||||||
WSclient_t * client;
|
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
|
||||||
client = &_clients[i];
|
|
||||||
WebSockets::enableHeartbeat(client, pingInterval, pongTimeout, disconnectTimeoutCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* disable ping/pong heartbeat process
|
|
||||||
*/
|
|
||||||
void WebSocketsServerCore::disableHeartbeat() {
|
|
||||||
_pingInterval = 0;
|
|
||||||
|
|
||||||
WSclient_t * client;
|
|
||||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
|
||||||
client = &_clients[i];
|
|
||||||
client->pingInterval = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
// WebSocketServer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called to initialize the Websocket server
|
|
||||||
*/
|
|
||||||
void WebSocketsServer::begin(void) {
|
|
||||||
WebSocketsServerCore::begin();
|
|
||||||
_server->begin();
|
|
||||||
|
|
||||||
DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebSocketsServer::close(void) {
|
|
||||||
WebSocketsServerCore::close();
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
|
||||||
_server->close();
|
|
||||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
|
||||||
_server->end();
|
|
||||||
#else
|
|
||||||
// TODO how to close server?
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
|
||||||
/**
|
|
||||||
* called in arduino loop
|
|
||||||
*/
|
|
||||||
void WebSocketsServerCore::loop(void) {
|
|
||||||
if(_runnning) {
|
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
handleClientData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called in arduino loop
|
|
||||||
*/
|
|
||||||
void WebSocketsServer::loop(void) {
|
|
||||||
if(_runnning) {
|
|
||||||
WEBSOCKETS_YIELD();
|
|
||||||
handleNewClients();
|
|
||||||
WebSocketsServerCore::loop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -31,14 +31,8 @@
|
|||||||
#define WEBSOCKETS_SERVER_CLIENT_MAX (5)
|
#define WEBSOCKETS_SERVER_CLIENT_MAX (5)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class WebSocketsServerCore : protected WebSockets {
|
class WebSocketsServer : protected WebSockets {
|
||||||
public:
|
public:
|
||||||
WebSocketsServerCore(const String & origin = "", const String & protocol = "arduino");
|
|
||||||
virtual ~WebSocketsServerCore(void);
|
|
||||||
|
|
||||||
void begin(void);
|
|
||||||
void close(void);
|
|
||||||
|
|
||||||
#ifdef __AVR__
|
#ifdef __AVR__
|
||||||
typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
|
typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
|
||||||
typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue);
|
typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue);
|
||||||
@ -47,6 +41,19 @@ class WebSocketsServerCore : protected WebSockets {
|
|||||||
typedef std::function<bool(String headerName, String headerValue)> WebSocketServerHttpHeaderValFunc;
|
typedef std::function<bool(String headerName, String headerValue)> WebSocketServerHttpHeaderValFunc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino");
|
||||||
|
virtual ~WebSocketsServer(void);
|
||||||
|
|
||||||
|
void begin(void);
|
||||||
|
void close(void);
|
||||||
|
|
||||||
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
|
void loop(void);
|
||||||
|
#else
|
||||||
|
// Async interface not need a loop call
|
||||||
|
void loop(void) __attribute__((deprecated)) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void onEvent(WebSocketServerEvent cbEvent);
|
void onEvent(WebSocketServerEvent cbEvent);
|
||||||
void onValidateHttpHeader(
|
void onValidateHttpHeader(
|
||||||
WebSocketServerHttpHeaderValFunc validationFunc,
|
WebSocketServerHttpHeaderValFunc validationFunc,
|
||||||
@ -85,28 +92,20 @@ class WebSocketsServerCore : protected WebSockets {
|
|||||||
|
|
||||||
int connectedClients(bool ping = false);
|
int connectedClients(bool ping = false);
|
||||||
|
|
||||||
bool clientIsConnected(uint8_t num);
|
|
||||||
|
|
||||||
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
|
|
||||||
void disableHeartbeat();
|
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||||
IPAddress remoteIP(uint8_t num);
|
IPAddress remoteIP(uint8_t num);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
|
||||||
void loop(void); // handle client data only
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WSclient_t * newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
uint16_t _port;
|
||||||
String _origin;
|
String _origin;
|
||||||
String _protocol;
|
String _protocol;
|
||||||
String _base64Authorization; ///< Base64 encoded Auth request
|
String _base64Authorization; ///< Base64 encoded Auth request
|
||||||
String * _mandatoryHttpHeaders;
|
String * _mandatoryHttpHeaders;
|
||||||
size_t _mandatoryHttpHeaderCount;
|
size_t _mandatoryHttpHeaderCount;
|
||||||
|
|
||||||
|
WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
|
||||||
|
|
||||||
WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX];
|
WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX];
|
||||||
|
|
||||||
WebSocketServerEvent _cbEvent;
|
WebSocketServerEvent _cbEvent;
|
||||||
@ -114,9 +113,7 @@ class WebSocketsServerCore : protected WebSockets {
|
|||||||
|
|
||||||
bool _runnning;
|
bool _runnning;
|
||||||
|
|
||||||
uint32_t _pingInterval;
|
bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
|
||||||
uint32_t _pongTimeout;
|
|
||||||
uint8_t _disconnectTimeoutCount;
|
|
||||||
|
|
||||||
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
|
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
|
||||||
|
|
||||||
@ -124,13 +121,12 @@ class WebSocketsServerCore : protected WebSockets {
|
|||||||
bool clientIsConnected(WSclient_t * client);
|
bool clientIsConnected(WSclient_t * client);
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
|
void handleNewClients(void);
|
||||||
void handleClientData(void);
|
void handleClientData(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handleHeader(WSclient_t * client, String * headerLine);
|
void handleHeader(WSclient_t * client, String * headerLine);
|
||||||
|
|
||||||
void handleHBPing(WSclient_t * client); // send ping in specified intervals
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called if a non Websocket connection is coming in.
|
* called if a non Websocket connection is coming in.
|
||||||
* Note: can be override
|
* Note: can be override
|
||||||
@ -199,15 +195,6 @@ class WebSocketsServerCore : protected WebSockets {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
|
||||||
WSclient_t * handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* drop native tcp connection (client->tcp)
|
|
||||||
*/
|
|
||||||
void dropNativeClient(WSclient_t * client);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
* returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
|
* returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
|
||||||
@ -216,28 +203,4 @@ class WebSocketsServerCore : protected WebSockets {
|
|||||||
bool hasMandatoryHeader(String headerName);
|
bool hasMandatoryHeader(String headerName);
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebSocketsServer : public WebSocketsServerCore {
|
|
||||||
public:
|
|
||||||
WebSocketsServer(uint16_t port, const String & origin = "", const String & protocol = "arduino");
|
|
||||||
virtual ~WebSocketsServer(void);
|
|
||||||
|
|
||||||
void begin(void);
|
|
||||||
void close(void);
|
|
||||||
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
|
||||||
void loop(void); // handle incoming client and client data
|
|
||||||
#else
|
|
||||||
// Async interface not need a loop call
|
|
||||||
void loop(void) __attribute__((deprecated)) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
|
||||||
void handleNewClients(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t _port;
|
|
||||||
WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* WEBSOCKETSSERVER_H_ */
|
#endif /* WEBSOCKETSSERVER_H_ */
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file WebSocketsVersion.h
|
|
||||||
* @date 09.02.2021
|
|
||||||
* @author Markus Sattler
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
|
||||||
* This file is part of the WebSockets for Arduino.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBSOCKETSVERSION_H_
|
|
||||||
#define WEBSOCKETSVERSION_H_
|
|
||||||
|
|
||||||
#define WEBSOCKETS_VERSION "2.3.5"
|
|
||||||
|
|
||||||
#define WEBSOCKETS_VERSION_MAJOR 2
|
|
||||||
#define WEBSOCKETS_VERSION_MINOR 3
|
|
||||||
#define WEBSOCKETS_VERSION_PATCH 5
|
|
||||||
|
|
||||||
#define WEBSOCKETS_VERSION_INT 2003005
|
|
||||||
|
|
||||||
#endif /* WEBSOCKETSVERSION_H_ */
|
|
@ -27,64 +27,6 @@ function build_sketches()
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_sketch()
|
|
||||||
{
|
|
||||||
local arduino=$1
|
|
||||||
local sketch=$2
|
|
||||||
$arduino --verify $sketch;
|
|
||||||
local result=$?
|
|
||||||
if [ $result -ne 0 ]; then
|
|
||||||
echo "Build failed ($sketch) build verbose..."
|
|
||||||
$arduino --verify --verbose --preserve-temp-files $sketch
|
|
||||||
result=$?
|
|
||||||
fi
|
|
||||||
if [ $result -ne 0 ]; then
|
|
||||||
echo "Build failed ($1) $sketch"
|
|
||||||
return $result
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_sketches_json()
|
|
||||||
{
|
|
||||||
local arduino=$1
|
|
||||||
local srcpath=$2
|
|
||||||
local platform=$3
|
|
||||||
local sketches=($(find $srcpath -name *.ino))
|
|
||||||
echo -en "["
|
|
||||||
for sketch in "${sketches[@]}" ; do
|
|
||||||
local sketchdir=$(dirname $sketch)
|
|
||||||
if [[ -f "$sketchdir/.$platform.skip" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
echo -en "\"$sketch\""
|
|
||||||
if [[ $sketch != ${sketches[-1]} ]] ; then
|
|
||||||
echo -en ","
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
echo -en "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_sketches_json_matrix()
|
|
||||||
{
|
|
||||||
local arduino=$1
|
|
||||||
local srcpath=$2
|
|
||||||
local platform=$3
|
|
||||||
local ideversion=$4
|
|
||||||
local board=$5
|
|
||||||
local sketches=($(find $srcpath -name *.ino))
|
|
||||||
for sketch in "${sketches[@]}" ; do
|
|
||||||
local sketchdir=$(dirname $sketch)
|
|
||||||
local sketchname=$(basename $sketch)
|
|
||||||
if [[ -f "$sketchdir/.$platform.skip" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
echo -en "{\"name\":\"$sketchname\",\"board\":\"$board\",\"ideversion\":\"$ideversion\",\"cpu\":\"$platform\",\"sketch\":\"$sketch\"}"
|
|
||||||
if [[ $sketch != ${sketches[-1]} ]] ; then
|
|
||||||
echo -en ","
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_core()
|
function get_core()
|
||||||
{
|
{
|
||||||
@ -95,37 +37,17 @@ function get_core()
|
|||||||
if [ "$1" = "esp8266" ] ; then
|
if [ "$1" = "esp8266" ] ; then
|
||||||
mkdir esp8266com
|
mkdir esp8266com
|
||||||
cd esp8266com
|
cd esp8266com
|
||||||
git clone --depth 1 https://github.com/esp8266/Arduino.git esp8266
|
git clone https://github.com/esp8266/Arduino.git esp8266
|
||||||
cd esp8266/
|
cd esp8266/tools
|
||||||
rm -rf .git
|
|
||||||
cd tools
|
|
||||||
python get.py
|
python get.py
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$1" = "esp32" ] ; then
|
if [ "$1" = "esp32" ] ; then
|
||||||
mkdir espressif
|
mkdir espressif
|
||||||
cd espressif
|
cd espressif
|
||||||
git clone --depth 1 https://github.com/espressif/arduino-esp32.git esp32
|
git clone https://github.com/espressif/arduino-esp32.git esp32
|
||||||
cd esp32/
|
cd esp32/tools
|
||||||
rm -rf .git
|
|
||||||
cd tools
|
|
||||||
python get.py
|
python get.py
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clone_library() {
|
|
||||||
local url=$1
|
|
||||||
echo clone $(basename $url)
|
|
||||||
mkdir -p $HOME/Arduino/libraries
|
|
||||||
cd $HOME/Arduino/libraries
|
|
||||||
git clone --depth 1 $url
|
|
||||||
rm -rf */.git
|
|
||||||
rm -rf */.github
|
|
||||||
rm -rf */examples
|
|
||||||
}
|
|
||||||
|
|
||||||
function hash_library_names() {
|
|
||||||
cd $HOME/Arduino/libraries
|
|
||||||
ls | sha1sum -z | cut -c1-5
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
import json
|
|
||||||
import configparser
|
|
||||||
import argparse
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
travis_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
base_dir = os.path.abspath(travis_dir + "/../")
|
|
||||||
|
|
||||||
def write_header_file(version):
|
|
||||||
hvs = version.split('.')
|
|
||||||
intversion = int(hvs[0]) * 1000000 + int(hvs[1]) * 1000 + int(hvs[2])
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
|
|
||||||
text = f'''/**
|
|
||||||
* @file WebSocketsVersion.h
|
|
||||||
* @date {now.strftime("%d.%m.%Y")}
|
|
||||||
* @author Markus Sattler
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
|
||||||
* This file is part of the WebSockets for Arduino.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBSOCKETSVERSION_H_
|
|
||||||
#define WEBSOCKETSVERSION_H_
|
|
||||||
|
|
||||||
#define WEBSOCKETS_VERSION "{version}"
|
|
||||||
|
|
||||||
#define WEBSOCKETS_VERSION_MAJOR {hvs[0]}
|
|
||||||
#define WEBSOCKETS_VERSION_MINOR {hvs[1]}
|
|
||||||
#define WEBSOCKETS_VERSION_PATCH {hvs[2]}
|
|
||||||
|
|
||||||
#define WEBSOCKETS_VERSION_INT {intversion}
|
|
||||||
|
|
||||||
#endif /* WEBSOCKETSVERSION_H_ */
|
|
||||||
'''
|
|
||||||
with open(f'{base_dir}/src/WebSocketsVersion.h', 'w') as f:
|
|
||||||
f.write(text)
|
|
||||||
|
|
||||||
|
|
||||||
def get_library_properties_version():
|
|
||||||
library_properties = {}
|
|
||||||
with open(f'{base_dir}/library.properties', 'r') as f:
|
|
||||||
library_properties = configparser.ConfigParser()
|
|
||||||
library_properties.read_string('[root]\n' + f.read())
|
|
||||||
return library_properties['root']['version']
|
|
||||||
|
|
||||||
|
|
||||||
def get_library_json_version():
|
|
||||||
library_json = {}
|
|
||||||
with open(f'{base_dir}/library.json', 'r') as f:
|
|
||||||
library_json = json.load(f)
|
|
||||||
return library_json['version']
|
|
||||||
|
|
||||||
|
|
||||||
def get_header_versions():
|
|
||||||
data = {}
|
|
||||||
define = re.compile('^#define WEBSOCKETS_VERSION_?(.*) "?([0-9\.]*)"?$')
|
|
||||||
with open(f'{base_dir}/src/WebSocketsVersion.h', 'r') as f:
|
|
||||||
for line in f:
|
|
||||||
m = define.match(line)
|
|
||||||
if m:
|
|
||||||
name = m[1]
|
|
||||||
if name == "":
|
|
||||||
name = "VERSION"
|
|
||||||
data[name] = m[2]
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Checks and update Version files')
|
|
||||||
parser.add_argument(
|
|
||||||
'--update', action='store_true', default=False)
|
|
||||||
parser.add_argument(
|
|
||||||
'--check', action='store_true', default=True)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.update:
|
|
||||||
library_properties_version = get_library_properties_version()
|
|
||||||
|
|
||||||
with open(f'{base_dir}/library.json', 'r') as f:
|
|
||||||
library_json = json.load(f)
|
|
||||||
|
|
||||||
library_json['version'] = library_properties_version
|
|
||||||
|
|
||||||
with open(f'{base_dir}/library.json', 'w') as f:
|
|
||||||
json.dump(library_json, f, indent=4, sort_keys=True)
|
|
||||||
|
|
||||||
write_header_file(library_properties_version)
|
|
||||||
|
|
||||||
|
|
||||||
library_json_version = get_library_json_version()
|
|
||||||
library_properties_version = get_library_properties_version()
|
|
||||||
header_version = get_header_versions()
|
|
||||||
|
|
||||||
print("WebSocketsVersion.h", header_version)
|
|
||||||
print(f"library.json: {library_json_version}")
|
|
||||||
print(f"library.properties: {library_properties_version}")
|
|
||||||
|
|
||||||
if args.check:
|
|
||||||
if library_json_version != library_properties_version or header_version['VERSION'] != library_properties_version:
|
|
||||||
raise Exception('versions did not match!')
|
|
||||||
|
|
||||||
hvs = header_version['VERSION'].split('.')
|
|
||||||
if header_version['MAJOR'] != hvs[0]:
|
|
||||||
raise Exception('header MAJOR version wrong!')
|
|
||||||
if header_version['MINOR'] != hvs[1]:
|
|
||||||
raise Exception('header MINOR version wrong!')
|
|
||||||
if header_version['PATCH'] != hvs[2]:
|
|
||||||
raise Exception('header PATCH version wrong!')
|
|
||||||
|
|
||||||
intversion = int(hvs[0]) * 1000000 + int(hvs[1]) * 1000 + int(hvs[2])
|
|
||||||
if int(header_version['INT']) != intversion:
|
|
||||||
raise Exception('header INT version wrong!')
|
|
Loading…
Reference in New Issue
Block a user