Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
883f1e27e6 | ||
|
|
e7fc147424 | ||
|
|
2147b147fc | ||
|
|
f5e9a43461 | ||
|
|
cabb56fc8c | ||
|
|
58786eb6d9 | ||
|
|
776242b259 | ||
|
|
a9d19c3218 | ||
|
|
7bd299ec07 | ||
|
|
107469cd78 | ||
|
|
709e1fd567 | ||
|
|
4eb8f18ebf | ||
|
|
d5d27c8020 |
52
.github/workflows/superlinter.yml
vendored
52
.github/workflows/superlinter.yml
vendored
@@ -1,26 +1,52 @@
|
||||
name: Super-Linter
|
||||
---
|
||||
#################################
|
||||
#################################
|
||||
## Super Linter GitHub Actions ##
|
||||
#################################
|
||||
#################################
|
||||
name: Lint Code Base
|
||||
|
||||
# Run this workflow every time a new commit pushed to your repository
|
||||
#
|
||||
# Documentation:
|
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions
|
||||
#
|
||||
|
||||
#############################
|
||||
# Start the job on all push #
|
||||
#############################
|
||||
on: push
|
||||
|
||||
###############
|
||||
# Set the Job #
|
||||
###############
|
||||
jobs:
|
||||
# Set the job key. The key is displayed as the job name
|
||||
# when a job name is not provided
|
||||
super-lint:
|
||||
build:
|
||||
# Name the Job
|
||||
name: Lint code base
|
||||
# Set the type of machine to run on
|
||||
name: Lint Code Base
|
||||
# Set the agent to run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
##################
|
||||
# Load all steps #
|
||||
##################
|
||||
steps:
|
||||
# Checks out a copy of your repository on the ubuntu-latest machine
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
##########################
|
||||
# Checkout the code base #
|
||||
##########################
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Full git history is needed to get a proper
|
||||
# list of changed files within `super-linter`
|
||||
fetch-depth: 0
|
||||
|
||||
# Runs the Super-Linter action
|
||||
- name: Run Super-Linter
|
||||
uses: github/super-linter@v3
|
||||
################################
|
||||
# Run Linter against code base #
|
||||
################################
|
||||
- name: Lint Code Base
|
||||
uses: github/super-linter/slim@v4
|
||||
env:
|
||||
VALIDATE_ALL_CODEBASE: false
|
||||
# Change to 'master' if your main branch differs
|
||||
DEFAULT_BRANCH: main
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -22,6 +22,12 @@ TinyMqtt is a small, fast and capable Mqtt Broker and Client for Esp8266 / Esp32
|
||||
proxy for clients that are connected to it.
|
||||
- zeroconf, this is a strange but very powerful mode where
|
||||
all brokers tries to connect together on the same local network.
|
||||
- small memory footprint (very efficient topic storage)
|
||||
|
||||
## Limitations
|
||||
|
||||
- Max of 255 different topics can be stored (change index_t type to allow more)
|
||||
- No Qos because messages are not queued but immediately sent to clients
|
||||
|
||||
## Quickstart
|
||||
|
||||
|
||||
18
library.json
18
library.json
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "TinyMqtt",
|
||||
"keywords": "ethernet, mqtt, m2m, iot",
|
||||
"description": "MQTT is a lightweight messaging protocol ideal for small devices. This library allows to send and receive and host a broker for MQTT. It does support MQTT 3.1.1 with QOS=0 on ESP8266 and ESP32 WROOM platfrms.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hsaturn/TinyMqtt.git"
|
||||
},
|
||||
"version": "0.8.0",
|
||||
"exclude": "",
|
||||
"examples": "examples/*/*.ino",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
name=TinyMqtt
|
||||
version=0.8.0
|
||||
version=0.9.3
|
||||
author=Francois BIOT, HSaturn, <hsaturn@gmail.com>
|
||||
maintainer=Francois BIOT, HSaturn, <hsaturn@gmail.com>
|
||||
sentence=A tiny broker and client library for MQTT messaging.
|
||||
@@ -8,4 +8,3 @@ category=Communication
|
||||
url=https://github.com/hsaturn/TinyMqtt
|
||||
architectures=*
|
||||
includes=TinyMqtt.h
|
||||
depends=AsyncTCP
|
||||
|
||||
@@ -28,29 +28,6 @@ class StringIndexer
|
||||
public:
|
||||
using index_t = uint8_t;
|
||||
|
||||
static index_t strToIndex(const char* str, uint8_t len)
|
||||
{
|
||||
for(auto it=strings.begin(); it!=strings.end(); it++)
|
||||
{
|
||||
if (strncmp(it->second.str.c_str(), str, len)==0)
|
||||
{
|
||||
it->second.used++;
|
||||
return it->first;
|
||||
}
|
||||
}
|
||||
for(index_t index=1; index; index++)
|
||||
{
|
||||
if (strings.find(index)==strings.end())
|
||||
{
|
||||
strings[index].str = std::string(str, len);
|
||||
strings[index].used++;
|
||||
// Serial << "Creating index " << index << " for (" << strings[index].str.c_str() << ") len=" << len << endl;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return 0; // TODO out of indexes
|
||||
}
|
||||
|
||||
static const std::string& str(const index_t& index)
|
||||
{
|
||||
static std::string dummy;
|
||||
@@ -82,6 +59,32 @@ class StringIndexer
|
||||
static uint16_t count() { return strings.size(); }
|
||||
|
||||
private:
|
||||
friend class IndexedString;
|
||||
|
||||
// increment use of str or create a new index
|
||||
static index_t strToIndex(const char* str, uint8_t len)
|
||||
{
|
||||
for(auto it=strings.begin(); it!=strings.end(); it++)
|
||||
{
|
||||
if (it->second.str.length() == len && strcmp(it->second.str.c_str(), str)==0)
|
||||
{
|
||||
it->second.used++;
|
||||
return it->first;
|
||||
}
|
||||
}
|
||||
for(index_t index=1; index; index++)
|
||||
{
|
||||
if (strings.find(index)==strings.end())
|
||||
{
|
||||
strings[index].str = std::string(str, len);
|
||||
strings[index].used++;
|
||||
// Serial << "Creating index " << index << " for (" << strings[index].str.c_str() << ") len=" << len << endl;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return 0; // TODO out of indexes
|
||||
}
|
||||
|
||||
static std::map<index_t, StringCounter> strings;
|
||||
};
|
||||
|
||||
|
||||
@@ -771,9 +771,18 @@ void MqttMessage::encodeLength()
|
||||
if (state != Complete)
|
||||
{
|
||||
int length = buffer.size()-3; // 3 = 1 byte for header + 2 bytes for pre-reserved length field.
|
||||
if (length <= 0x7F)
|
||||
{
|
||||
buffer.erase(1,1);
|
||||
buffer[1] = length;
|
||||
vheader = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[1] = 0x80 | (length & 0x7F);
|
||||
buffer[2] = (length >> 7);
|
||||
vheader = 3;
|
||||
}
|
||||
|
||||
// We could check that buffer[2] < 128 (end of length encoding)
|
||||
state = Complete;
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
#else
|
||||
#define dbg_ptr uint32_t
|
||||
#endif
|
||||
|
||||
#ifdef WIO_TERMINAL
|
||||
// Uncommon board handling
|
||||
// If you have a problem with this line, just remove it.
|
||||
// Note: https://github.com/hsaturn/TinyMqtt/issues/41
|
||||
#include <rpcWiFi.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# See https://github.com/bxparks/EpoxyDuino for documentation about this
|
||||
# Makefile to compile and run Arduino programs natively on Linux or MacOS.
|
||||
|
||||
EXTRA_CXXFLAGS=-g3 -O0
|
||||
|
||||
APP_NAME := length-tests
|
||||
ARDUINO_LIBS := AUnit AceCommon AceTime TinyMqtt EspMock ESP8266WiFi ESPAsyncTCP
|
||||
ARDUINO_LIB_DIRS := ../../../EspMock/libraries
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#include <AUnit.h>
|
||||
#include <TinyMqtt.h>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* TinyMqtt network unit tests.
|
||||
@@ -10,7 +14,60 @@
|
||||
* Checks with a local broker. Clients must connect to the local broker
|
||||
**/
|
||||
|
||||
using namespace std;
|
||||
// if ascii_pos = 0, no ascii dump, else ascii dump starts after column ascii_pos
|
||||
std::string bufferToHexa(const uint8_t* buffer, size_t length, char sep = 0, size_t ascii_pos = 0)
|
||||
{
|
||||
std::stringstream out;
|
||||
std::string ascii;
|
||||
std::string h("0123456789ABCDEF");
|
||||
for(size_t i=0; i<length; i++)
|
||||
{
|
||||
uint8_t c = buffer[i];
|
||||
out << h[ c >> 4] << h[ c & 0x0F ];
|
||||
if (sep) out << sep;
|
||||
if (ascii_pos)
|
||||
{
|
||||
if (c>=32)
|
||||
ascii += c;
|
||||
else
|
||||
ascii +='.';
|
||||
}
|
||||
}
|
||||
std::string ret(out.str());
|
||||
if (ascii_pos)
|
||||
{
|
||||
while(ret.length() < ascii_pos)
|
||||
ret += ' ';
|
||||
ret +='[' + ascii + ']';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dumpMqttMessage(const uint8_t* buffer, size_t length)
|
||||
{
|
||||
std::map<int, std::string> pkt =
|
||||
{ { MqttMessage::Unknown , "Unknown " },
|
||||
{ MqttMessage::Connect , "Connect " },
|
||||
{ MqttMessage::ConnAck , "ConnAck " },
|
||||
{ MqttMessage::Publish , "Publish " },
|
||||
{ MqttMessage::PubAck , "PubAck " },
|
||||
{ MqttMessage::Subscribe , "Subscribe " },
|
||||
{ MqttMessage::SubAck , "SubAck " },
|
||||
{ MqttMessage::UnSubscribe , "Unsubscribe " },
|
||||
{ MqttMessage::UnSuback , "UnSubAck " },
|
||||
{ MqttMessage::PingReq , "PingReq " },
|
||||
{ MqttMessage::PingResp , "PingResp " },
|
||||
{ MqttMessage::Disconnect , "Disconnect " } };
|
||||
|
||||
std::cout << " | data sent " << std::setw(3) << length << " : ";
|
||||
auto it = pkt.find(buffer[0] & 0xF0);
|
||||
if (it == pkt.end())
|
||||
std::cout << pkt[MqttMessage::Unknown];
|
||||
else
|
||||
std::cout << it->second;
|
||||
|
||||
std::cout << bufferToHexa(buffer, length, ' ', 60) << std::endl;
|
||||
}
|
||||
|
||||
String toString(const IPAddress& ip)
|
||||
{
|
||||
@@ -299,7 +356,7 @@ test(network_hudge_payload)
|
||||
|
||||
MqttClient subscriber(&broker);
|
||||
subscriber.setCallback(onPublish);
|
||||
subscriber.subscribe("a/b");
|
||||
subscriber.subscribe("a/b"); // Note -> this does not send any byte .... (nowhere to send)
|
||||
|
||||
MqttClient publisher(&broker);
|
||||
publisher.publish("a/b", payload); // This publish is received
|
||||
@@ -310,6 +367,47 @@ test(network_hudge_payload)
|
||||
assertEqual(strcmp(payload, lastPayload), 0);
|
||||
}
|
||||
|
||||
test(connack)
|
||||
{
|
||||
const bool view = false;
|
||||
|
||||
NetworkObserver check(
|
||||
[this](const WiFiClient*, const uint8_t* buffer, size_t length)
|
||||
{
|
||||
if (view) dumpMqttMessage(buffer, length);
|
||||
if (buffer[0] == MqttMessage::ConnAck)
|
||||
{
|
||||
std::string hex = bufferToHexa(buffer, length);
|
||||
assertStringCaseEqual(hex.c_str(), "20020000");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
start_servers(2, true);
|
||||
assertEqual(WiFi.status(), WL_CONNECTED);
|
||||
|
||||
MqttBroker broker(1883);
|
||||
broker.begin();
|
||||
IPAddress broker_ip = WiFi.localIP();
|
||||
|
||||
ESP8266WiFiClass::selectInstance(2);
|
||||
MqttClient client;
|
||||
client.connect(broker_ip.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
|
||||
assertTrue(broker.clientsCount() == 1);
|
||||
assertTrue(client.connected());
|
||||
|
||||
MqttClient::counters[MqttMessage::Type::SubAck] = 0;
|
||||
client.subscribe("a/b");
|
||||
|
||||
// TODO how to avoid these loops ???
|
||||
broker.loop();
|
||||
client.loop();
|
||||
|
||||
assertEqual(MqttClient::counters[MqttMessage::Type::SubAck], 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// setup() and loop()
|
||||
void setup() {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# See https://github.com/bxparks/EpoxyDuino for documentation about this
|
||||
# Makefile to compile and run Arduino programs natively on Linux or MacOS.
|
||||
|
||||
EXTRA_CXXFLAGS=-g3 -O0
|
||||
|
||||
APP_NAME := string-indexer-tests
|
||||
ARDUINO_LIBS := AUnit AceCommon AceTime TinyMqtt EspMock ESP8266WiFi ESPAsync
|
||||
ARDUINO_LIB_DIRS := ../../../EspMock/libraries
|
||||
|
||||
@@ -62,6 +62,14 @@ test(indexer_same_strings_should_equal)
|
||||
assertTrue(one == two);
|
||||
}
|
||||
|
||||
test(indexer_compare_strings_with_same_beginning)
|
||||
{
|
||||
IndexedString two("one_two");
|
||||
IndexedString one("one");
|
||||
|
||||
assertNotEqual(one.getIndex(), two.getIndex());
|
||||
}
|
||||
|
||||
test(indexer_indexed_operator_eq)
|
||||
{
|
||||
IndexedString one("one");
|
||||
|
||||
Reference in New Issue
Block a user