Compare commits

..

53 Commits
0.7.0 ... 0.7.2

Author SHA1 Message Date
hsaturn
7c8d71262f Fix test (not yet finished) 2021-04-02 18:59:07 +02:00
hsaturn
138ce973f2 Typos in libraries 2021-04-02 18:48:37 +02:00
hsaturn
bf499117b7 Merge branch 'main' of github.com:hsaturn/TinyMqtt into main 2021-03-31 19:12:28 +02:00
hsaturn
4ed6f72602 Merge branch 'test' into main 2021-03-31 19:11:24 +02:00
hsaturn
87a78c549f Fix crash at end of unit tests 2021-03-31 19:09:43 +02:00
hsaturn
5211360b91 Local tests added 2021-03-31 19:09:05 +02:00
hsaturn
549a23ffb7 Fix delete was not really deleting in tinytest 2021-03-31 10:40:06 +02:00
hsaturn
3a1af655d7 Fix compilation problem 2021-03-31 00:33:15 +02:00
hsaturn
e71ffefc5a Fixed a useless test and modified MqttClient constructors 2021-03-31 00:22:31 +02:00
hsaturn
b6a0dde2b1 json 2021-03-30 08:52:46 +02:00
hsaturn
babc391632 Added json 2021-03-30 08:52:10 +02:00
hsaturn
27bdbb9a0b str 2021-03-30 08:41:30 +02:00
hsaturn
6a9e158428 results 2021-03-30 08:39:02 +02:00
hsaturn
6fc6794dc3 result0.yaml 2021-03-30 08:37:25 +02:00
hsaturn
1eaa514579 result.yaml 2021-03-30 08:35:33 +02:00
hsaturn
7af4c2ca69 Added .o to gitignore 2021-03-30 08:21:56 +02:00
hsaturn
a340558460 Fix tests 2021-03-30 08:21:33 +02:00
hsaturn
9a7db237d3 Renamed local to nowifi as local will be used for local (127.0.0.1) tests 2021-03-30 08:15:13 +02:00
hsaturn
91e083e7b0 Merge branch 'linter' into main 2021-03-29 23:58:00 +02:00
hsaturn
97adc985e6 Code clean 2021-03-29 23:56:36 +02:00
hsaturn
6fcfc9dfc0 ptr 2021-03-29 23:20:49 +02:00
hsaturn
a6596ffc89 Fix ptr 2021-03-29 23:06:40 +02:00
hsaturn
533ab0c70d Try to mock Esp 2021-03-29 21:47:14 +02:00
hsaturn
d5dd896b45 MqttClient::unsubscribe implemented 2021-03-29 20:48:45 +02:00
hsaturn
bd7fa8f39c Update readme.md 2021-03-29 20:47:14 +02:00
hsaturn
6395e931ce refix EspWifi 2021-03-29 20:47:14 +02:00
hsaturn
635fee6f7c ESP8266WiFi lib added for aunit 2021-03-29 20:47:14 +02:00
hsaturn
dc2420d88e Fix makefile 2021-03-29 20:47:14 +02:00
hsaturn
2fbc46cbe2 Revert auint 2021-03-29 20:47:14 +02:00
hsaturn
a003156ae1 Fix aunit 2021-03-29 20:47:14 +02:00
hsaturn
913e1aa7ae Fixed make target 2021-03-29 20:46:59 +02:00
hsaturn
8272515bd7 Fixed make target 2021-03-29 20:46:46 +02:00
hsaturn
9a7f6a3020 Fixed make target 2021-03-29 20:46:46 +02:00
hsaturn
fead702d9f Added makefile for aunit 2021-03-29 20:46:46 +02:00
hsaturn
eaf938f2fd Test aunit 2021-03-29 20:46:46 +02:00
hsaturn
8eefa63f45 Lint fixes 2021-03-29 20:46:46 +02:00
hsaturn
9d48c436d8 test 2021-03-29 20:46:46 +02:00
hsaturn
792a28e831 deleted 2021-03-29 20:45:33 +02:00
hsaturn
9407193454 MqttClient::unsubscribe implemented 2021-03-29 20:39:10 +02:00
hsaturn
602050f309 Update readme.md 2021-03-29 11:45:51 +02:00
hsaturn
1a70c90af2 refix EspWifi 2021-03-29 00:01:32 +02:00
hsaturn
ed4091c53e ESP8266WiFi lib added for aunit 2021-03-28 23:57:06 +02:00
hsaturn
f2a805f724 Fix makefile 2021-03-28 23:50:50 +02:00
hsaturn
3083bcf071 Revert auint 2021-03-28 23:44:11 +02:00
hsaturn
d01f46dbc1 Fix aunit 2021-03-28 23:42:57 +02:00
hsaturn
39b2257619 Merge branch 'linter' of github.com:hsaturn/TinyMqtt into linter 2021-03-28 23:39:50 +02:00
hsaturn
60d385189b Fixed make target 2021-03-28 23:39:37 +02:00
hsaturn
3f2c1c57e1 Fixed make target 2021-03-28 23:30:19 +02:00
hsaturn
e550197d0a Fixed make target 2021-03-28 23:28:48 +02:00
hsaturn
253bc9b3f5 Added makefile for aunit 2021-03-28 23:26:53 +02:00
hsaturn
96d8018960 Test aunit 2021-03-28 23:16:07 +02:00
hsaturn
505cacc2df Lint fixes 2021-03-28 23:09:10 +02:00
hsaturn
62848056a2 test 2021-03-28 23:01:14 +02:00
17 changed files with 304 additions and 52 deletions

28
.github/workflows/aunit.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# See https://docs.github.com/en/actions/guides for documentation about GitHub
# Actions.
name: AUnit Tests
# Run on all branches.
on: [push]
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Setup
run: |
cd ..
git clone https://github.com/bxparks/EpoxyDuino
git clone https://github.com/bxparks/AceRoutine
git clone https://github.com/bxparks/AUnit
git clone https://github.com/bxparks/AceCommon
git clone https://github.com/hsaturn/EspMock
- name: Verify tests
run: |
make -C tests
make -C tests runtests

View File

@@ -1,6 +1,7 @@
name: Super-Linter
# Run this workflow every time a new commit pushed to your repository
#
on: push
jobs:

3
.gitignore vendored
View File

@@ -1,2 +1,5 @@
*~
src/my_credentials.h
*.o
*.swp
*.out

View File

@@ -1,10 +1,10 @@
# TinyMqtt
![](https://img.shields.io/github/v/release/hsaturn/TinyMqtt)
![](https://img.shields.io/github/issues/hsaturn/TinyMqtt)
![](https://img.shields.io/badge/platform-ESP8266-green)
![](https://img.shields.io/github/license/hsaturn/TinyMqtt)
![](https://img.shields.io/badge/Mqtt-%203.1.1-yellow)
![Release](https://img.shields.io/github/v/release/hsaturn/TinyMqtt)
![Issues](https://img.shields.io/github/issues/hsaturn/TinyMqtt)
![Esp8266](https://img.shields.io/badge/platform-ESP8266-green)
![Gpl 3.0](https://img.shields.io/github/license/hsaturn/TinyMqtt)
![Mqtt 3.1.1](https://img.shields.io/badge/Mqtt-%203.1.1-yellow)
ESP 8266 is a small, fast and capable Mqtt Broker and Client
@@ -26,6 +26,7 @@ ESP 8266 is a small, fast and capable Mqtt Broker and Client
* Implement zeroconf mode (needs async)
* Add a max_clients in MqttBroker. Used with zeroconf, there will be
no need for having tons of clients (also RAM is the problem with many clients)
* Why not a 'global' TinyMqtt::loop() instead of having to call loop for all broker/clients instances
* Test what is the real max number of clients for broker. As far as I saw, 1k is needed per client which would make more than 30 clients critical.
* ~~MqttMessage uses a buffer 256 bytes which is usually far than needed.~~
* ~~MqttClient does not support more than one subscription at time~~

View File

@@ -40,6 +40,7 @@ std::map<std::string, MqttBroker*> brokers;
void setup()
{
WiFi.persistent(false); // https://github.com/esp8266/Arduino/issues/1054
Serial.begin(115200);
delay(500);
Serial << endl << endl << endl
@@ -399,11 +400,11 @@ void loop()
}
if (client)
{
clients.erase(s);
for (auto it: clients)
{
if (it.second != client) continue;
Serial << "deleted" << endl;
delete (it.second);
clients.erase(it.first);
break;
}
@@ -413,9 +414,9 @@ void loop()
{
for(auto it: brokers)
{
Serial << (int32_t)it.second << '/' << (int32_t)broker << endl;
if (broker != it.second) continue;
Serial << "deleted" << endl;
delete (it.second);
brokers.erase(it.first);
break;
}

View File

@@ -1,12 +1,12 @@
{
"name": "TinyMqtt",
"keywords": "ethernet, mqtt, m2m, iot",
"description": "MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages. It does support MQTT 3.1.1 without any QOS.",
"description": "MQTT is a lightweight messaging protocol ideal for small devices. This library allows to send and receive MQTT messages. It does support MQTT 3.1.1 without QOS=0.",
"repository": {
"type": "git",
"url": "https://github.com/hsaturn/TinyMqtt.git"
},
"version": "0.7.0",
"version": "0.7.2",
"exclude": "",
"examples": "examples/*/*.ino",
"frameworks": "arduino",

View File

@@ -1,10 +1,11 @@
name=TinyMqtt
version=0.7.0
version=0.7.2
author=Francois BIOT, HSaturn, <hsaturn@gmail.com>
maintainer=Francois BIOT, HSaturn, <hsaturn@gmail.com>
sentence=A tiny broker and client library for MQTT messaging.
paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages and to jhost a broker in your ESP. It does support MQTT 3.1.1 without any QOS.
paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This library allows to send and receive MQTT messages and to host a broker in your ESP. It does support MQTT 3.1.1 without QoS=0.
category=Communication
url=https://github.com/hsaturn/TinyMqtt
architectures=*
includes=TinyMqtt.h
depends=

View File

@@ -15,6 +15,16 @@ class StringIndexer
std::string str;
uint8_t used=0;
friend class StringIndexer;
#if EPOXY_DUINO
public:
// Workaround to avoid coredump in Indexer::release
// when destroying a Topic after the deletion of
// StringIndexer::strings map (which can occurs only with AUnit,
// never in the ESP itself, because ESP never ends)
// (I hate static vars)
~StringCounter() { used=255; }
#endif
};
public:
using index_t=uint8_t;

View File

@@ -19,6 +19,7 @@ MqttBroker::~MqttBroker()
{
delete clients[0];
}
server.close();
}
// private constructor used by broker only
@@ -29,8 +30,8 @@ MqttClient::MqttClient(MqttBroker* parent, WiFiClient& new_client)
alive = millis()+5000; // client expires after 5s if no CONNECT msg
}
MqttClient::MqttClient(MqttBroker* parent)
: parent(parent)
MqttClient::MqttClient(MqttBroker* parent, const std::string& id)
: parent(parent), clientId(id)
{
client = nullptr;
@@ -41,7 +42,6 @@ MqttClient::~MqttClient()
{
close();
delete client;
Serial << "Client deleted" << endl;
}
void MqttClient::close(bool bSendDisconnect)
@@ -269,10 +269,30 @@ MqttError MqttClient::subscribe(Topic topic, uint8_t qos)
subscriptions.insert(topic);
if (parent==nullptr) // remote broker ?
if (parent==nullptr) // remote broker
{
debug("remote subscribe");
MqttMessage msg(MqttMessage::Type::Subscribe, 2);
return sendTopic(topic, MqttMessage::Type::Subscribe, qos);
}
return ret;
}
MqttError MqttClient::unsubscribe(Topic topic)
{
auto it=subscriptions.find(topic);
if (it != subscriptions.end())
{
subscriptions.erase(it);
if (parent==nullptr) // remote broker
{
return sendTopic(topic, MqttMessage::Type::UnSubscribe, 0);
}
}
return MqttOk;
}
MqttError MqttClient::sendTopic(const Topic& topic, MqttMessage::Type type, uint8_t qos)
{
MqttMessage msg(type, 2);
// TODO manage packet identifier
msg.add(0);
@@ -280,11 +300,9 @@ MqttError MqttClient::subscribe(Topic topic, uint8_t qos)
msg.add(topic);
msg.add(qos);
ret = msg.sendTo(this);
// TODO we should wait (state machine) for SUBACK
}
return ret;
// TODO instead we should wait (state machine) for SUBACK / UNSUBACK ?
return msg.sendTo(this);
}
long MqttClient::counter=0;

View File

@@ -120,9 +120,8 @@ class MqttClient
FlagReserved = 1
};
public:
MqttClient(MqttBroker*);
MqttClient(MqttBroker* brk, const std::string& id) : MqttClient(brk) { clientId=id; }
MqttClient() : MqttClient(nullptr) {};
MqttClient(MqttBroker* brk = nullptr, const std::string& id="");
MqttClient(const std::string& id) : MqttClient(nullptr, id){}
~MqttClient();
@@ -149,7 +148,7 @@ class MqttClient
MqttError publish(const Topic& t) { return publish(t, nullptr, 0);};
MqttError subscribe(Topic topic, uint8_t qos=0);
MqttError unsubscribe(Topic& topic);
MqttError unsubscribe(Topic topic);
// connected to local broker
// TODO seems to be useless
@@ -158,9 +157,8 @@ class MqttClient
void dump()
{
uint32_t ms=millis();
Serial << "MqttClient (" << clientId.c_str() << ") p=" << (int32_t) parent
<< " c=" << (int32_t)client << (connected() ? " ON " : " OFF");
Serial << ", alive=" << (uint32_t)alive << '/' << ms << ", ka=" << keep_alive;
Serial << "MqttClient (" << clientId.c_str() << ") " << (connected() ? " ON " : " OFF");
Serial << ", alive=" << alive << '/' << ms << ", ka=" << keep_alive;
Serial << (client && client->connected() ? "" : "dis") << "connected";
message.hexdump("entrant msg");
bool c=false;
@@ -178,6 +176,7 @@ class MqttClient
static long counter; // Number of messages sent
private:
MqttError sendTopic(const Topic& topic, MqttMessage::Type type, uint8_t qos);
void resubscribe();
friend class MqttBroker;
@@ -221,9 +220,9 @@ class MqttBroker
void begin() { server.begin(); }
void loop();
uint8_t port() const { return server.port(); }
uint16_t port() const { return server.port(); }
void connect(std::string host, uint32_t port=1883);
void connect(std::string host, uint16_t port=1883);
bool connected() const { return state == Connected; }
size_t clientsCount() const { return clients.size(); }

20
tests/Makefile Normal file
View File

@@ -0,0 +1,20 @@
tests:
set -e; \
for i in *-tests/Makefile; do \
echo '==== Making:' $$(dirname $$i); \
$(MAKE) -C $$(dirname $$i) -j; \
done
runtests:
set -e; \
for i in *-tests/Makefile; do \
echo '==== Running:' $$(dirname $$i); \
$$(dirname $$i)/$$(dirname $$i).out; \
done
clean:
set -e; \
for i in *-tests/Makefile; do \
echo '==== Cleaning:' $$(dirname $$i); \
$(MAKE) -C $$(dirname $$i) clean; \
done

View File

@@ -0,0 +1,6 @@
# See https://github.com/bxparks/EpoxyDuino for documentation about this
# Makefile to compile and run Arduino programs natively on Linux or MacOS.
APP_NAME := local-tests
ARDUINO_LIBS := AUnit AceCommon AceTime TinyMqtt EspMock
include ../../../EpoxyDuino/EpoxyDuino.mk

View File

@@ -0,0 +1,147 @@
#include <AUnit.h>
#include <TinyMqtt.h>
#include <map>
/**
* TinyMqtt local unit tests.
*
* Clients are connected to pseudo remote broker
* The remote will be 127.0.0.1:1883
* We are using 127.0.0.1 because this is simpler to test with a single ESP
* Also, this will allow to mock and thus run Action on github
**/
using namespace std;
MqttBroker broker(1883);
std::map<std::string, std::map<Topic, int>> published; // map[client_id] => map[topic] = count
void onPublish(const MqttClient* srce, const Topic& topic, const char* payload, size_t length)
{
if (srce)
published[srce->id()][topic]++;
}
test(local_client_should_unregister_when_destroyed)
{
return;
assertEqual(broker.clientsCount(), (size_t)0);
{
MqttClient client;
assertEqual(broker.clientsCount(), (size_t)0); // Ensure client is not yet connected
client.connect("127.0.0.1", 1883);
assertEqual(broker.clientsCount(), (size_t)1); // Ensure client is now connected
}
assertEqual(broker.clientsCount(), (size_t)0);
}
#if 0
test(local_connect)
{
assertEqual(broker.clientsCount(), (size_t)0);
MqttClient client;
assertTrue(client.connected());
assertEqual(broker.clientsCount(), (size_t)1);
}
test(local_publish_should_be_dispatched)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
MqttClient subscriber;
subscriber.subscribe("a/b");
subscriber.subscribe("a/c");
subscriber.setCallback(onPublish);
MqttClient publisher;
publisher.publish("a/b");
publisher.publish("a/c");
publisher.publish("a/c");
assertEqual(published.size(), (size_t)1); // 1 client has received something
assertTrue(published[""]["a/b"] == 1);
assertTrue(published[""]["a/c"] == 2);
}
test(local_publish_should_be_dispatched_to_local_clients)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
MqttClient subscriber_a("A");
subscriber_a.setCallback(onPublish);
subscriber_a.subscribe("a/b");
subscriber_a.subscribe("a/c");
MqttClient subscriber_b("B");
subscriber_b.setCallback(onPublish);
subscriber_b.subscribe("a/b");
MqttClient publisher;
publisher.publish("a/b");
publisher.publish("a/c");
assertEqual(published.size(), (size_t)2); // 2 clients have received something
assertTrue(published["A"]["a/b"] == 1);
assertTrue(published["A"]["a/c"] == 1);
assertTrue(published["B"]["a/b"] == 1);
assertTrue(published["B"]["a/c"] == 0);
}
test(local_unsubscribe)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
MqttClient subscriber;
subscriber.setCallback(onPublish);
subscriber.subscribe("a/b");
MqttClient publisher;
publisher.publish("a/b");
subscriber.unsubscribe("a/b");
publisher.publish("a/b");
publisher.publish("a/b");
assertTrue(published[""]["a/b"] == 1); // Only one publish has been received
}
test(local_nocallback_when_destroyed)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
MqttClient publisher;
{
MqttClient subscriber;
subscriber.setCallback(onPublish);
subscriber.subscribe("a/b");
publisher.publish("a/b");
}
publisher.publish("a/b");
assertEqual(published.size(), (size_t)1); // Only one publish has been received
}
#endif
//----------------------------------------------------------------------------
// setup() and loop()
void setup() {
delay(1000);
Serial.begin(115200);
while(!Serial);
Serial.println("=============[ NO WIFI CONNECTION TinyMqtt TESTS ]========================");
}
void loop() {
aunit::TestRunner::run();
if (Serial.available()) ESP.reset();
}

View File

@@ -0,0 +1,6 @@
# See https://github.com/bxparks/EpoxyDuino for documentation about this
# Makefile to compile and run Arduino programs natively on Linux or MacOS.
APP_NAME := nowifi-tests
ARDUINO_LIBS := AUnit AceCommon AceTime TinyMqtt EspMock
include ../../../EpoxyDuino/EpoxyDuino.mk

View File

@@ -3,9 +3,10 @@
#include <map>
/**
* TinyMqtt local unit tests.
* TinyMqtt nowifi unit tests.
*
* No wifi connection unit tests.
* Checks with a local broker. Clients must connect to the local client
**/
using namespace std;
@@ -20,7 +21,7 @@ void onPublish(const MqttClient* srce, const Topic& topic, const char* payload,
published[srce->id()][topic]++;
}
test(local_client_should_unregister_when_destroyed)
test(nowifi_client_should_unregister_when_destroyed)
{
assertEqual(broker.clientsCount(), (size_t)0);
{
@@ -30,7 +31,7 @@ test(local_client_should_unregister_when_destroyed)
assertEqual(broker.clientsCount(), (size_t)0);
}
test(local_connect)
test(nowifi_connect)
{
assertEqual(broker.clientsCount(), (size_t)0);
@@ -39,7 +40,7 @@ test(local_connect)
assertEqual(broker.clientsCount(), (size_t)1);
}
test(local_publish_should_be_dispatched)
test(nowifi_publish_should_be_dispatched)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
@@ -59,7 +60,7 @@ test(local_publish_should_be_dispatched)
assertTrue(published[""]["a/c"] == 2);
}
test(local_publish_should_be_dispatched_to_local_clients)
test(nowifi_publish_should_be_dispatched_to_nowifi_clients)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
@@ -84,7 +85,7 @@ test(local_publish_should_be_dispatched_to_local_clients)
assertTrue(published["B"]["a/c"] == 0);
}
test(local_unsubscribe)
test(nowifi_unsubscribe)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
@@ -96,31 +97,33 @@ test(local_unsubscribe)
MqttClient publisher(&broker);
publisher.publish("a/b");
// subscriber.unsubscribe("a/b"); TODO not yet implemented
subscriber.unsubscribe("a/b");
publisher.publish("a/b");
publisher.publish("a/b");
assertTrue(published[""]["a/b"] == 1); // Only one publish has been received
}
test(local_nocallback_when_destroyed)
test(nowifi_nocallback_when_destroyed)
{
published.clear();
assertEqual(broker.clientsCount(), (size_t)0);
MqttClient publisher(&broker);
{
MqttClient subscriber(&broker);
subscriber.setCallback(onPublish);
subscriber.subscribe("a/b");
publisher.publish("a/b");
}
MqttClient publisher(&broker);
publisher.publish("a/b");
assertEqual(published.size(), (size_t)0); // Only one publish has been received
assertEqual(published.size(), (size_t)1); // Only one publish has been received
}
//----------------------------------------------------------------------------
// setup() and loop()
void setup() {

6
tests/result.json Normal file
View File

@@ -0,0 +1,6 @@
{
"schemaVersion" : 1,
"label" : "tests",
"message" : "Message content",
"color": "red"
}

2
tests/result.yaml Normal file
View File

@@ -0,0 +1,2 @@
result: 1
insert: "passed"