Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f12ecfd6d | ||
|
|
3ae1afec27 | ||
|
|
9608ed9fdf | ||
|
|
220e904ae9 | ||
|
|
49b696315c | ||
|
|
a9ebf31e6f | ||
|
|
4b4eb0b684 |
134
examples/advanced/mqtt_class_binder/mqtt_class_binder.ino
Normal file
134
examples/advanced/mqtt_class_binder/mqtt_class_binder.ino
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <TinyMqtt.h> // https://github.com/hsaturn/TinyMqtt
|
||||
#include <MqttClassBinder.h>
|
||||
|
||||
/**
|
||||
* Example on how to bind a class:onPublish function
|
||||
*
|
||||
* Local broker that accept connections and two local clients
|
||||
*
|
||||
*
|
||||
* +-----------------------------+
|
||||
* | ESP |
|
||||
* | +--------+ | 1883 <--- External client/s
|
||||
* | +-------->| broker | | 1883 <--- External client/s
|
||||
* | | +--------+ |
|
||||
* | | ^ |
|
||||
* | | | |
|
||||
* | | | | -----
|
||||
* | v v | ---
|
||||
* | +----------+ +----------+ | -
|
||||
* | | internal | | internal | +-------* Wifi
|
||||
* | | client | | client | |
|
||||
* | +----------+ +----------+ |
|
||||
* | |
|
||||
* +-----------------------------+
|
||||
*
|
||||
* pros - Reduces internal latency (when publish is received by the same ESP)
|
||||
* - Reduces wifi traffic
|
||||
* - No need to have an external broker
|
||||
* - can still report to a 'main' broker (TODO see documentation that have to be written)
|
||||
* - accepts external clients
|
||||
* - MqttClassBinder allows to mix together many mqtt sources
|
||||
*
|
||||
* cons - Takes more memory (48 more bytes for the one MqttClassBinder<Class>
|
||||
* - a bit hard to understand
|
||||
*
|
||||
*/
|
||||
|
||||
const char *ssid = "";
|
||||
const char *password = "";
|
||||
|
||||
std::string topic_b="sensor/btemp";
|
||||
std::string topic_sender= "sensor/counter";
|
||||
|
||||
MqttBroker broker(1883);
|
||||
|
||||
MqttClient mqtt_a(&broker);
|
||||
MqttClient mqtt_b(&broker);
|
||||
MqttClient mqtt_sender(&broker);
|
||||
|
||||
class MqttReceiver: public MqttClassBinder<MqttReceiver>
|
||||
{
|
||||
public:
|
||||
|
||||
void onPublish(const MqttClient* source, const Topic& topic, const char* payload, size_t /* length */)
|
||||
{
|
||||
Serial
|
||||
<< " * MqttReceiver received topic (" << topic.c_str() << ")"
|
||||
<< " from (" << source->id() << "), "
|
||||
<< " payload: (" << payload << ')' << endl;
|
||||
}
|
||||
};
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
delay(500);
|
||||
Serial << "Clients with wifi " << endl;
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial << '-'; delay(500);
|
||||
if (strlen(ssid)==0)
|
||||
Serial << "****** PLEASE EDIT THE EXAMPLE AND MODIFY ssid/password *************" << endl;
|
||||
}
|
||||
|
||||
Serial << "Connected to " << ssid << "IP address: " << WiFi.localIP() << endl;
|
||||
|
||||
broker.begin();
|
||||
|
||||
MqttReceiver* receiver = new MqttReceiver;
|
||||
|
||||
// receiver will receive both publication from two MqttClient
|
||||
// (that could be connected to two different brokers)
|
||||
MqttClassBinder<MqttReceiver>::onPublish(&mqtt_a, receiver);
|
||||
MqttClassBinder<MqttReceiver>::onPublish(&mqtt_b, receiver);
|
||||
|
||||
mqtt_a.id("mqtt_a");
|
||||
mqtt_b.id("mqtt_b");
|
||||
mqtt_sender.id("sender");
|
||||
|
||||
mqtt_a.subscribe(topic_b);
|
||||
mqtt_b.subscribe(topic_sender);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
broker.loop(); // Don't forget to add loop for every broker and clients
|
||||
|
||||
mqtt_a.loop();
|
||||
mqtt_b.loop();
|
||||
mqtt_sender.loop();
|
||||
|
||||
// ============= client A publish ================
|
||||
{
|
||||
static const int interval = 5000; // publishes every 5s (please avoid usage of delay())
|
||||
static uint32_t timer = millis() + interval;
|
||||
|
||||
if (millis() > timer)
|
||||
{
|
||||
static int counter = 0;
|
||||
Serial << "Sender is publishing " << topic_sender.c_str() << endl;
|
||||
timer += interval;
|
||||
mqtt_sender.publish(topic_sender, "sent by Sender, message #"+std::string(String(counter++).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// ============= client B publish ================
|
||||
{
|
||||
static const int interval = 7000; // will send topic each 7s
|
||||
static uint32_t timer = millis() + interval;
|
||||
static int temperature;
|
||||
|
||||
if (millis() > timer)
|
||||
{
|
||||
Serial << "B is publishing " << topic_b.c_str() << endl;
|
||||
timer += interval;
|
||||
mqtt_b.publish(topic_b, "sent by B: temp="+std::string(String(16+temperature++%6).c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
name=TinyMqtt
|
||||
version=0.9.7
|
||||
version=0.9.10
|
||||
author=Francois BIOT, HSaturn, <hsaturn@gmail.com>
|
||||
maintainer=Francois BIOT, HSaturn, <hsaturn@gmail.com>
|
||||
sentence=A tiny broker and client library for MQTT messaging.
|
||||
|
||||
72
src/MqttClassBinder.h
Normal file
72
src/MqttClassBinder.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// MqttReceiver must implement onPublish(...)
|
||||
template <class MqttReceiver>
|
||||
class MqttClassBinder
|
||||
{
|
||||
public:
|
||||
MqttClassBinder()
|
||||
{
|
||||
unregister(this);
|
||||
}
|
||||
~MqttClassBinder() { unregister(this); }
|
||||
|
||||
static void onUnpublished(MqttClient::CallBack handler)
|
||||
{
|
||||
unrouted_handler = handler;
|
||||
}
|
||||
|
||||
static void onPublish(MqttClient* client, MqttReceiver* dest)
|
||||
{
|
||||
routes.insert(std::pair<MqttClient*, MqttReceiver*>(client, dest));
|
||||
client->setCallback(onRoutePublish);
|
||||
}
|
||||
|
||||
void onPublish(const MqttClient* client, const Topic& topic, const char* payload, size_t length)
|
||||
{
|
||||
static_cast<MqttReceiver*>(this)->MqttReceiver::onPublish(client, topic, payload, length);
|
||||
}
|
||||
|
||||
static size_t size() { return routes.size(); }
|
||||
|
||||
static void reset() { routes.clear(); }
|
||||
|
||||
private:
|
||||
|
||||
static void onRoutePublish(const MqttClient* client, const Topic& topic, const char* payload, size_t length)
|
||||
{
|
||||
bool unrouted = true;
|
||||
auto receivers = routes.equal_range(client);
|
||||
for(auto it = receivers.first; it != receivers.second; ++it)
|
||||
{
|
||||
it->second->onPublish(client, topic, payload, length);
|
||||
unrouted = false;
|
||||
}
|
||||
|
||||
if (unrouted and unrouted_handler)
|
||||
{
|
||||
unrouted_handler(client, topic, payload, length);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void unregister(MqttClassBinder<MqttReceiver>* which)
|
||||
{
|
||||
if (routes.size()==0) return; // bug in map stl
|
||||
for(auto it=routes.begin(); it!=routes.end(); it++)
|
||||
if (it->second == which)
|
||||
{
|
||||
routes.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static std::multimap<const MqttClient*, MqttClassBinder<MqttReceiver>*> routes;
|
||||
static MqttClient::CallBack unrouted_handler;
|
||||
|
||||
};
|
||||
|
||||
template<class MqttReceiver>
|
||||
std::multimap<const MqttClient*, MqttClassBinder<MqttReceiver>*> MqttClassBinder<MqttReceiver>::routes;
|
||||
|
||||
template<class MqttReceiver>
|
||||
MqttClient::CallBack MqttClassBinder<MqttReceiver>::unrouted_handler = nullptr;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// vim: ts=2 sw=2 expandtab
|
||||
#pragma once
|
||||
|
||||
#ifndef TINY_MQTT_DEBUG
|
||||
#define TINY_MQTT_DEBUG 0
|
||||
#endif
|
||||
|
||||
// TODO Should add a AUnit with both TINY_MQTT_ASYNC and not TINY_MQTT_ASYNC
|
||||
// #define TINY_MQTT_ASYNC // Uncomment this to use ESPAsyncTCP instead of normal cnx
|
||||
@@ -37,9 +40,9 @@
|
||||
|
||||
#define TINY_MQTT_DEFAULT_CLIENT_ID "Tiny"
|
||||
|
||||
#if TINY_MQTT_DEBUG
|
||||
#include <TinyStreaming.h>
|
||||
#include <TinyConsole.h> // https://github.com/hsaturn/TinyConsole
|
||||
#if TINY_MQTT_DEBUG
|
||||
#include <TinyConsole.h> // https://github.com/hsaturn/TinyConsole
|
||||
struct TinyMqtt
|
||||
{
|
||||
static int debug;
|
||||
@@ -162,7 +165,6 @@ class MqttMessage
|
||||
class MqttBroker;
|
||||
class MqttClient
|
||||
{
|
||||
using CallBack = void (*)(const MqttClient* source, const Topic& topic, const char* payload, size_t payload_length);
|
||||
enum __attribute__((packed)) Flags
|
||||
{
|
||||
FlagUserName = 128,
|
||||
@@ -174,6 +176,9 @@ class MqttClient
|
||||
FlagReserved = 1
|
||||
};
|
||||
public:
|
||||
|
||||
using CallBack = void (*)(const MqttClient* source, const Topic& topic, const char* payload, size_t payload_length);
|
||||
|
||||
/** Constructor. Broker is the adress of a local broker if not null
|
||||
If you want to connect elsewhere, leave broker null and use connect() **/
|
||||
MqttClient(MqttBroker* broker = nullptr, const std::string& id = TINY_MQTT_DEFAULT_CLIENT_ID);
|
||||
|
||||
351
tests/classbind-tests/classbind-tests.ino
Normal file
351
tests/classbind-tests/classbind-tests.ino
Normal file
@@ -0,0 +1,351 @@
|
||||
// vim: ts=2 sw=2 expandtab
|
||||
#include <Arduino.h>
|
||||
#include <AUnit.h>
|
||||
#include <TinyMqtt.h>
|
||||
#include <MqttClassBinder.h>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
// --------------------- CUT HERE - MQTT MESSAGE ROUTER FILE ----------------------------
|
||||
|
||||
class TestReceiver : public MqttClassBinder<TestReceiver>
|
||||
{
|
||||
public:
|
||||
TestReceiver(const char* name) : MqttClassBinder(), name_(name) {}
|
||||
|
||||
void onPublish(const MqttClient* /* source */, const Topic& topic, const char* payload, size_t /* length */)
|
||||
{
|
||||
Serial << "--> routed message received by " << name_ << ':' << topic.c_str() << " = " << payload << endl;
|
||||
messages[name_]++;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string name_;
|
||||
|
||||
public:
|
||||
static std::map<std::string, int> messages;
|
||||
};
|
||||
|
||||
std::map<std::string, int> TestReceiver::messages;
|
||||
|
||||
static int unrouted = 0;
|
||||
void onUnrouted(const MqttClient*, const Topic& topic, const char*, size_t)
|
||||
{
|
||||
Serial << "--> unrouted: " << topic.c_str() << endl;
|
||||
unrouted++;
|
||||
}
|
||||
|
||||
|
||||
static std::string topic="sensor/temperature";
|
||||
|
||||
/**
|
||||
* TinyMqtt network unit tests.
|
||||
*
|
||||
* No wifi connection unit tests.
|
||||
* Checks with a local broker. Clients must connect to the local broker
|
||||
**/
|
||||
|
||||
// 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)
|
||||
{
|
||||
return String(ip[0])+'.'+String(ip[1])+'.'+String(ip[2])+'.'+String(ip[3]);
|
||||
}
|
||||
|
||||
MqttBroker broker(1883);
|
||||
|
||||
void reset_and_start_servers(int n, bool early_accept = true)
|
||||
{
|
||||
MqttClassBinder<TestReceiver>::reset();
|
||||
TestReceiver::messages.clear();
|
||||
unrouted = 0;
|
||||
|
||||
ESP8266WiFiClass::resetInstances();
|
||||
ESP8266WiFiClass::earlyAccept = early_accept;
|
||||
while(n)
|
||||
{
|
||||
ESP8266WiFiClass::selectInstance(n--);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin("fake_ssid", "fake_pwd");
|
||||
}
|
||||
}
|
||||
|
||||
test(classbind_one_client_receives_the_message)
|
||||
{
|
||||
reset_and_start_servers(2, true);
|
||||
assertEqual(WiFi.status(), WL_CONNECTED);
|
||||
|
||||
MqttBroker broker(1883);
|
||||
broker.begin();
|
||||
IPAddress ip_broker = WiFi.localIP();
|
||||
|
||||
// We have a 2nd ESP in order to test through wifi (opposed to local)
|
||||
ESP8266WiFiClass::selectInstance(2);
|
||||
MqttClient client;
|
||||
client.connect(ip_broker.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
assertTrue(client.connected());
|
||||
|
||||
TestReceiver receiver("receiver");
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client, &receiver);
|
||||
|
||||
client.subscribe("a/b");
|
||||
client.publish("a/b", "ab");
|
||||
|
||||
for (int i =0; i<10; i++)
|
||||
{
|
||||
client.loop();
|
||||
broker.loop();
|
||||
}
|
||||
|
||||
assertEqual(TestReceiver::messages["receiver"], 1);
|
||||
assertEqual(unrouted, 0);
|
||||
}
|
||||
|
||||
test(classbind_routes_should_be_empty_when_receiver_goes_out_of_scope)
|
||||
{
|
||||
reset_and_start_servers(2, true);
|
||||
assertEqual(WiFi.status(), WL_CONNECTED);
|
||||
|
||||
MqttBroker broker(1883);
|
||||
broker.begin();
|
||||
IPAddress ip_broker = WiFi.localIP();
|
||||
|
||||
// We have a 2nd ESP in order to test through wifi (opposed to local)
|
||||
ESP8266WiFiClass::selectInstance(2);
|
||||
MqttClient client;
|
||||
client.connect(ip_broker.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
assertTrue(client.connected());
|
||||
|
||||
// Make a receiver going out of scope
|
||||
{
|
||||
TestReceiver receiver("receiver");
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client, &receiver);
|
||||
assertEqual(MqttClassBinder<TestReceiver>::size(), (size_t)1);
|
||||
}
|
||||
|
||||
client.subscribe("a/b");
|
||||
client.publish("a/b", "ab");
|
||||
|
||||
for (int i =0; i<10; i++)
|
||||
{
|
||||
client.loop();
|
||||
broker.loop();
|
||||
}
|
||||
|
||||
assertEqual(TestReceiver::messages["receiver"], 0);
|
||||
assertEqual(MqttClassBinder<TestReceiver>::size(), (size_t)0);
|
||||
}
|
||||
|
||||
test(classbind_publish_should_be_dispatched_to_many_receivers)
|
||||
{
|
||||
reset_and_start_servers(2, true);
|
||||
assertEqual(WiFi.status(), WL_CONNECTED);
|
||||
|
||||
MqttBroker broker(1883);
|
||||
broker.begin();
|
||||
IPAddress ip_broker = WiFi.localIP();
|
||||
|
||||
// We have a 2nd ESP in order to test through wifi (opposed to local)
|
||||
ESP8266WiFiClass::selectInstance(2);
|
||||
MqttClient client;
|
||||
client.connect(ip_broker.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
assertTrue(client.connected());
|
||||
|
||||
TestReceiver receiver_1("receiver_1");
|
||||
TestReceiver receiver_2("receiver_2");
|
||||
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client, &receiver_1);
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client, &receiver_2);
|
||||
client.subscribe("a/b");
|
||||
client.publish("a/b", "ab");
|
||||
|
||||
for (int i =0; i<10; i++)
|
||||
{
|
||||
client.loop();
|
||||
broker.loop();
|
||||
}
|
||||
|
||||
assertEqual(TestReceiver::messages["receiver_1"], 1);
|
||||
assertEqual(TestReceiver::messages["receiver_2"], 1);
|
||||
}
|
||||
|
||||
test(classbind_register_to_many_clients)
|
||||
{
|
||||
reset_and_start_servers(2, true);
|
||||
assertEqual(WiFi.status(), WL_CONNECTED);
|
||||
|
||||
MqttBroker broker(1883);
|
||||
broker.begin();
|
||||
IPAddress ip_broker = WiFi.localIP();
|
||||
|
||||
// We have a 2nd ESP in order to test through wifi (opposed to local)
|
||||
ESP8266WiFiClass::selectInstance(2);
|
||||
MqttClient client_1;
|
||||
client_1.connect(ip_broker.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
|
||||
MqttClient client_2;
|
||||
client_2.connect(ip_broker.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
|
||||
assertTrue(client_1.connected());
|
||||
assertTrue(client_2.connected());
|
||||
|
||||
TestReceiver receiver("receiver");
|
||||
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client_1, &receiver);
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client_2, &receiver);
|
||||
|
||||
auto loop = [&client_1, &client_2, &broker]()
|
||||
{
|
||||
client_1.loop();
|
||||
client_2.loop();
|
||||
broker.loop();
|
||||
};
|
||||
|
||||
client_1.subscribe("a/b");
|
||||
client_2.subscribe("a/b");
|
||||
|
||||
// Ensure subscribptions are passed
|
||||
for (int i =0; i<5; i++) loop();
|
||||
|
||||
client_1.publish("a/b", "from 1");
|
||||
client_2.publish("a/b", "from 2");
|
||||
|
||||
// Ensure publishes are processed
|
||||
for (int i =0; i<5; i++) loop();
|
||||
|
||||
assertEqual(TestReceiver::messages["receiver"], 4);
|
||||
}
|
||||
|
||||
test(classbind_unrouted_fallback)
|
||||
{
|
||||
reset_and_start_servers(2, true);
|
||||
assertEqual(WiFi.status(), WL_CONNECTED);
|
||||
|
||||
MqttBroker broker(1883);
|
||||
broker.begin();
|
||||
IPAddress ip_broker = WiFi.localIP();
|
||||
|
||||
// We have a 2nd ESP in order to test through wifi (opposed to local)
|
||||
ESP8266WiFiClass::selectInstance(2);
|
||||
MqttClient client;
|
||||
client.connect(ip_broker.toString().c_str(), 1883);
|
||||
broker.loop();
|
||||
|
||||
assertTrue(client.connected());
|
||||
|
||||
MqttClassBinder<TestReceiver>::onUnpublished(onUnrouted);
|
||||
{
|
||||
TestReceiver receiver("receiver");
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client, &receiver);
|
||||
}
|
||||
|
||||
client.subscribe("a/b");
|
||||
client.publish("a/b", "from 2");
|
||||
|
||||
// Ensure subscribptions are passed
|
||||
for (int i =0; i<5; i++)
|
||||
{
|
||||
client.loop();
|
||||
broker.loop();
|
||||
}
|
||||
|
||||
assertEqual(TestReceiver::messages["receiver"], 0);
|
||||
assertEqual(unrouted, 1);
|
||||
}
|
||||
|
||||
test(classbind_should_cleanup_when_MqttClient_dies)
|
||||
{
|
||||
reset_and_start_servers(2, true);
|
||||
TestReceiver receiver("receiver");
|
||||
|
||||
{
|
||||
MqttClient client;
|
||||
|
||||
MqttClassBinder<TestReceiver>::onPublish(&client, &receiver);
|
||||
assertEqual(MqttClassBinder<TestReceiver>::size(), (size_t)1);
|
||||
}
|
||||
assertEqual(MqttClassBinder<TestReceiver>::size(), (size_t)1);
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// setup() and loop()
|
||||
void setup() {
|
||||
/* delay(1000);
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
*/
|
||||
|
||||
Serial.println("=============[ FAKE NETWORK TinyMqtt TESTS ]========================");
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin("network", "password");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
aunit::TestRunner::run();
|
||||
|
||||
if (Serial.available()) ESP.reset();
|
||||
}
|
||||
Reference in New Issue
Block a user