use espMqttClient, qos2 fixed

This commit is contained in:
MichaelDvP
2023-06-03 16:36:53 +02:00
parent d9c2fe0fb9
commit 7865ddc51f
43 changed files with 3749 additions and 230 deletions

View File

@@ -0,0 +1,58 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include "ClientAsync.h"
namespace espMqttClientInternals {
ClientAsync::ClientAsync()
: client()
, availableData(0)
, bufData(nullptr) {
// empty
}
bool ClientAsync::connect(IPAddress ip, uint16_t port) {
return client.connect(ip, port);
}
bool ClientAsync::connect(const char* host, uint16_t port) {
return client.connect(host, port);
}
size_t ClientAsync::write(const uint8_t* buf, size_t size) {
return client.write(reinterpret_cast<const char*>(buf), size);
}
int ClientAsync::read(uint8_t* buf, size_t size) {
size_t willRead = std::min(size, availableData);
memcpy(buf, bufData, std::min(size, availableData));
if (availableData > size) {
emc_log_w("Buffer is smaller than available data: %zu - %zu", size, availableData);
}
availableData = 0;
return willRead;
}
void ClientAsync::stop() {
client.close(false);
}
bool ClientAsync::connected() {
return client.connected();
}
bool ClientAsync::disconnected() {
return client.disconnected();
}
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,44 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#pragma once
#if defined(ARDUINO_ARCH_ESP32)
#include "freertos/FreeRTOS.h"
#include <AsyncTCP.h>
#elif defined(ARDUINO_ARCH_ESP8266)
#include <ESPAsyncTCP.h>
#endif
#include "Transport.h"
#include "../Config.h"
#include "../Logging.h"
namespace espMqttClientInternals {
class ClientAsync : public Transport {
public:
ClientAsync();
bool connect(IPAddress ip, uint16_t port) override;
bool connect(const char* host, uint16_t port) override;
size_t write(const uint8_t* buf, size_t size) override;
int read(uint8_t* buf, size_t size) override;
void stop() override;
bool connected() override;
bool disconnected() override;
AsyncClient client;
size_t availableData;
uint8_t* bufData;
};
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,92 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#include "ClientPosix.h"
#if defined(__linux__)
namespace espMqttClientInternals {
ClientPosix::ClientPosix()
: _sockfd(-1)
, _host() {
// empty
}
ClientPosix::~ClientPosix() {
ClientPosix::stop();
}
bool ClientPosix::connect(IPAddress ip, uint16_t port) {
if (connected()) stop();
_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
if (_sockfd < 0) {
emc_log_e("Error %d opening socket", errno);
}
int flag = 1;
if (setsockopt(_sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)) < 0) {
emc_log_e("Error %d disabling nagle", errno);
}
memset(&_host, 0, sizeof(_host));
_host.sin_family = AF_INET;
_host.sin_addr.s_addr = htonl(uint32_t(ip));
_host.sin_port = ::htons(port);
int ret = ::connect(_sockfd, (struct sockaddr *)&_host, sizeof(_host));
if (ret < 0) {
emc_log_e("Error connecting: %d - (%d) %s", ret, errno, strerror(errno));
return false;
}
emc_log_i("Connected");
return true;
}
bool ClientPosix::connect(const char* host, uint16_t port) {
// tbi
(void) host;
(void) port;
return false;
}
size_t ClientPosix::write(const uint8_t* buf, size_t size) {
return ::send(_sockfd, buf, size, 0);
}
int ClientPosix::read(uint8_t* buf, size_t size) {
int ret = ::recv(_sockfd, buf, size, MSG_DONTWAIT);
/*
if (ret < 0) {
emc_log_e("Error reading: %s", strerror(errno));
}
*/
return ret;
}
void ClientPosix::stop() {
if (_sockfd >= 0) {
::close(_sockfd);
_sockfd = -1;
}
}
bool ClientPosix::connected() {
return _sockfd >= 0;
}
bool ClientPosix::disconnected() {
return _sockfd < 0;
}
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,51 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#pragma once
#if defined(__linux__)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include "Transport.h" // includes IPAddress
#include "../Logging.h"
#ifndef EMC_POSIX_PEEK_SIZE
#define EMC_POSIX_PEEK_SIZE 1500
#endif
namespace espMqttClientInternals {
class ClientPosix : public Transport {
public:
ClientPosix();
~ClientPosix();
bool connect(IPAddress ip, uint16_t port) override;
bool connect(const char* host, uint16_t port) override;
size_t write(const uint8_t* buf, size_t size) override;
int read(uint8_t* buf, size_t size) override;
void stop() override;
bool connected() override;
bool disconnected() override;
protected:
int _sockfd;
struct sockaddr_in _host;
};
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include "ClientSecureSync.h"
#include <lwip/sockets.h> // socket options
namespace espMqttClientInternals {
ClientSecureSync::ClientSecureSync()
: client() {
// empty
}
bool ClientSecureSync::connect(IPAddress ip, uint16_t port) {
bool ret = client.connect(ip, port); // implicit conversion of return code int --> bool
if (ret) {
#if defined(ARDUINO_ARCH_ESP8266)
client.setNoDelay(true);
#elif defined(ARDUINO_ARCH_ESP32)
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
int val = true;
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
#endif
}
return ret;
}
bool ClientSecureSync::connect(const char* host, uint16_t port) {
bool ret = client.connect(host, port); // implicit conversion of return code int --> bool
if (ret) {
#if defined(ARDUINO_ARCH_ESP8266)
client.setNoDelay(true);
#elif defined(ARDUINO_ARCH_ESP32)
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
int val = true;
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
#endif
}
return ret;
}
size_t ClientSecureSync::write(const uint8_t* buf, size_t size) {
return client.write(buf, size);
}
int ClientSecureSync::read(uint8_t* buf, size_t size) {
return client.read(buf, size);
}
void ClientSecureSync::stop() {
client.stop();
}
bool ClientSecureSync::connected() {
return client.connected();
}
bool ClientSecureSync::disconnected() {
return !client.connected();
}
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#pragma once
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include <WiFiClientSecure.h> // includes IPAddress
#include "Transport.h"
namespace espMqttClientInternals {
class ClientSecureSync : public Transport {
public:
ClientSecureSync();
bool connect(IPAddress ip, uint16_t port) override;
bool connect(const char* host, uint16_t port) override;
size_t write(const uint8_t* buf, size_t size) override;
int read(uint8_t* buf, size_t size) override;
void stop() override;
bool connected() override;
bool disconnected() override;
WiFiClientSecure client;
};
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include "ClientSync.h"
#include <lwip/sockets.h> // socket options
namespace espMqttClientInternals {
ClientSync::ClientSync()
: client() {
// empty
}
bool ClientSync::connect(IPAddress ip, uint16_t port) {
bool ret = client.connect(ip, port); // implicit conversion of return code int --> bool
if (ret) {
#if defined(ARDUINO_ARCH_ESP8266)
client.setNoDelay(true);
#elif defined(ARDUINO_ARCH_ESP32)
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure (for consistency also here)
int val = true;
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
#endif
}
return ret;
}
bool ClientSync::connect(const char* host, uint16_t port) {
bool ret = client.connect(host, port); // implicit conversion of return code int --> bool
if (ret) {
#if defined(ARDUINO_ARCH_ESP8266)
client.setNoDelay(true);
#elif defined(ARDUINO_ARCH_ESP32)
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure (for consistency also here)
int val = true;
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
#endif
}
return ret;
}
size_t ClientSync::write(const uint8_t* buf, size_t size) {
return client.write(buf, size);
}
int ClientSync::read(uint8_t* buf, size_t size) {
return client.read(buf, size);
}
void ClientSync::stop() {
client.stop();
}
bool ClientSync::connected() {
return client.connected();
}
bool ClientSync::disconnected() {
return !client.connected();
}
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#pragma once
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include <WiFiClient.h> // includes IPAddress
#include "Transport.h"
namespace espMqttClientInternals {
class ClientSync : public Transport {
public:
ClientSync();
bool connect(IPAddress ip, uint16_t port) override;
bool connect(const char* host, uint16_t port) override;
size_t write(const uint8_t* buf, size_t size) override;
int read(uint8_t* buf, size_t size) override;
void stop() override;
bool connected() override;
bool disconnected() override;
WiFiClient client;
};
} // namespace espMqttClientInternals
#endif

View File

@@ -0,0 +1,32 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#if defined(__linux__)
#include "IPAddress.h"
IPAddress::IPAddress()
: _address(0) {
// empty
}
IPAddress::IPAddress(uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3)
: _address(0) {
_address = (uint32_t)p0 << 24 | (uint32_t)p1 << 16 | (uint32_t)p2 << 8 | p3;
}
IPAddress::IPAddress(uint32_t address)
: _address(address) {
// empty
}
IPAddress::operator uint32_t() {
return _address;
}
#endif

View File

@@ -0,0 +1,28 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#pragma once
#if defined(ARDUINO)
#include <IPAddress.h>
#else
#include <stdint.h>
class IPAddress {
public:
IPAddress();
IPAddress(uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3);
explicit IPAddress(uint32_t address);
operator uint32_t();
protected:
uint32_t _address;
};
#endif

View File

@@ -0,0 +1,28 @@
/*
Copyright (c) 2022 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/
#pragma once
#include <stddef.h> // size_t
#include "IPAddress.h"
namespace espMqttClientInternals {
class Transport {
public:
virtual bool connect(IPAddress ip, uint16_t port) = 0;
virtual bool connect(const char* host, uint16_t port) = 0;
virtual size_t write(const uint8_t* buf, size_t size) = 0;
virtual int read(uint8_t* buf, size_t size) = 0;
virtual void stop() = 0;
virtual bool connected() = 0;
virtual bool disconnected() = 0;
};
} // namespace espMqttClientInternals