Rewrite interpreter, can handle brokers now

This commit is contained in:
hsaturn
2021-03-22 00:28:05 +01:00
parent 52690ec7e7
commit 620dbf31af

View File

@@ -3,7 +3,7 @@
#include <map> #include <map>
/** /**
* Local broker that accept connections * Console allowing to make any kind of test.
* *
* pros - Reduces internal latency (when publish is received by the same ESP) * pros - Reduces internal latency (when publish is received by the same ESP)
* - Reduces wifi traffic * - Reduces wifi traffic
@@ -25,11 +25,13 @@
std::string topic="sensor/temperature"; std::string topic="sensor/temperature";
MqttBroker broker(1883);
void onPublish(const MqttClient* srce, const Topic& topic, const char* payload, size_t length) void onPublish(const MqttClient* srce, const Topic& topic, const char* payload, size_t length)
{ Serial << "--> " << srce->id().c_str() << ": ======> received " << topic.c_str() << endl; } { Serial << "--> " << srce->id().c_str() << ": ======> received " << topic.c_str() << endl; }
std::map<std::string, MqttClient*> clients;
std::map<std::string, MqttBroker*> brokers;
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
@@ -46,7 +48,21 @@ void setup()
Serial << "Connected to " << ssid << "IP address: " << WiFi.localIP() << endl; Serial << "Connected to " << ssid << "IP address: " << WiFi.localIP() << endl;
broker.begin(); MqttBroker* broker = new MqttBroker(1883);
broker->begin();
brokers["broker"] = broker;
}
int getint(std::string& str, const int if_empty=0, char sep=' ')
{
std::string sword;
while(str.length() && str[0]!=sep)
{
sword += str[0]; str.erase(0,1);
}
while(str[0]==sep) str.erase(0,1);
if (if_empty and sword.length()==0) sword=if_empty;
return atoi(sword.c_str());
} }
std::string getword(std::string& str, const char* if_empty=nullptr, char sep=' ') std::string getword(std::string& str, const char* if_empty=nullptr, char sep=' ')
@@ -128,7 +144,7 @@ class automatic
autop->bon=false; autop->bon=false;
else if (s=="interval") else if (s=="interval")
{ {
int32_t i=atol(getword(cmd).c_str()); int32_t i=getint(cmd);
if (i) if (i)
autop->interval(atol(s.c_str())); autop->interval(atol(s.c_str()));
else else
@@ -181,35 +197,12 @@ bool compare(std::string s, const char* cmd)
return strncmp(cmd, s.c_str(), s.length())==0; return strncmp(cmd, s.c_str(), s.length())==0;
} }
std::map<std::string, MqttClient*> clients;
using ClientFunction = void(*)(std::string& cmd, MqttClient* publish); using ClientFunction = void(*)(std::string& cmd, MqttClient* publish);
void clientCommand(std::string& cmd, ClientFunction func, bool canBeNull=false)
{
std::string s=getword(cmd);
bool found = clients.find(s) != clients.end();
if (canBeNull && found==false)
{
cmd += ' ' + s;
}
if (found or canBeNull)
{
MqttClient* publish = publish = clients[s];
func(cmd, publish);
}
else
{
Serial << "client not found (" << s.c_str() << ")" << endl;
cmd="";
}
}
void loop() void loop()
{ {
broker.loop(); for(auto it: brokers)
it.second->loop();
for(auto it: clients) for(auto it: clients)
it.second->loop(); it.second->loop();
@@ -223,7 +216,7 @@ void loop()
if (c==10 or c==14) if (c==10 or c==14)
{ {
Serial << "------------------------------------------------------" << endl; Serial << "----------------[ " << cmd.c_str() << " ]--------------" << endl;
static std::string last_cmd; static std::string last_cmd;
if (cmd=="!") if (cmd=="!")
cmd=last_cmd; cmd=last_cmd;
@@ -232,93 +225,169 @@ void loop()
while(cmd.length()) while(cmd.length())
{ {
std::string s; std::string s;
MqttBroker* broker = nullptr;
MqttClient* client = nullptr;
// client.function notation // client.function notation
// ("a.fun " becomes "fun a ") // ("a.fun " becomes "fun a ")
if (cmd.find('.') != std::string::npos) if (cmd.find('.') != std::string::npos)
{ {
std::string copy(cmd); s=getword(cmd, nullptr, '.');
s=getword(copy, nullptr, '.');
if (clients.find(s) != clients.end()) if (clients.find(s) != clients.end())
{ {
std::string s2 = getword(copy); client = clients[s];
cmd=s2+' '+s+' '+copy; }
else if (brokers.find(s) != brokers.end())
{
broker = brokers[s];
} }
else else
{ {
Serial << "Unknown client (" << s.c_str() << ")" << endl; Serial << "Unknown class (" << s.c_str() << ")" << endl;
cmd=""; cmd="";
} }
} }
s = getword(cmd); s = getword(cmd);
if (broker)
{
if (compare(s,"connect")) if (compare(s,"connect"))
{ {
clientCommand(cmd, [](std::string& cmd, MqttClient* publish) Serial << "NYI" << endl;
{ publish->connect(getword(cmd,"192.168.1.40").c_str(), 1883);
Serial << (publish->connected() ? "connected." : "not connected") << endl;
});
}
else if (compare(s,"publish"))
{
clientCommand(cmd, [](std::string& cmd, MqttClient* publish)
{ publish->publish(getword(cmd, topic.c_str())); });
}
else if (compare(s,"subscribe"))
{
clientCommand(cmd, [](std::string& cmd, MqttClient* publish)
{ publish->subscribe(getword(cmd, topic.c_str())); });
} }
else if (compare(s, "view")) else if (compare(s, "view"))
{ {
clientCommand(cmd, [](std::string& cmd, MqttClient* publish) broker->dump();
{ publish->dump(); }); }
}
else if (client)
{
if (compare(s,"connect"))
{
client->connect(getword(cmd,"192.168.1.40").c_str(), 1883);
Serial << (client->connected() ? "connected." : "not connected") << endl;
}
else if (compare(s,"publish"))
{
client->publish(getword(cmd, topic.c_str()));
}
else if (compare(s,"subscribe"))
{
client->subscribe(getword(cmd, topic.c_str()));
}
else if (compare(s, "view"))
{
client->dump();
}
}
if (compare(s, "delete"))
{
if (client==nullptr && broker==nullptr)
{
s = getword(cmd);
if (clients.find(s) != clients.end())
{
client = clients[s];
}
else if (brokers.find(s) != brokers.end())
{
broker = brokers[s];
}
else
Serial << "Unable to find (" << s.c_str() << ")" << endl;
}
if (client)
{
clients.erase(s);
for (auto it: clients)
{
if (it.second != client) continue;
Serial << "deleted" << endl;
clients.erase(it.first);
break;
}
cmd += " ls";
}
else if (broker)
{
for(auto it: brokers)
{
Serial << (int32_t)it.second << '/' << (int32_t)broker << endl;
if (broker != it.second) continue;
Serial << "deleted" << endl;
brokers.erase(it.first);
break;
}
cmd += " ls";
}
else
Serial << "Nothing to delete" << endl;
} }
else if (compare(s, "auto")) else if (compare(s, "auto"))
{ {
clientCommand(cmd, [](std::string& cmd, MqttClient* publish) automatic::command(client, cmd);
{ automatic::command(publish, cmd); if (client == nullptr)
if (publish == nullptr)
cmd.clear(); cmd.clear();
}, true);
} }
else if (compare(s, "new")) else if (compare(s, "broker"))
{ {
std::string id=getword(cmd); std::string id=getword(cmd);
if (id.length()) if (id.length() or brokers.find(id)!=brokers.end())
{ {
MqttClient* client = new MqttClient(&broker); int port=getint(cmd, 0);
if (port)
{
MqttBroker* broker = new MqttBroker(port);
broker->begin();
brokers[id] = broker;
Serial << "new broker (" << id.c_str() << ")" << endl;
}
else
Serial << "Missing port" << endl;
}
else
Serial << "Missing or existing broker name (" << id.c_str() << ")" << endl;
cmd+=" ls";
}
else if (compare(s, "client"))
{
std::string id=getword(cmd);
if (id.length() or clients.find(id)!=clients.end())
{
MqttBroker* broker = nullptr;
// TODO cmd line broker name
if (brokers.size()==1) broker = brokers.begin()->second;
Serial << "broker=" << (int32_t)broker << endl;
delay(500);
MqttClient* client = new MqttClient(broker);
client->id(id); client->id(id);
clients[id]=client; clients[id]=client;
client->setCallback(onPublish); client->setCallback(onPublish);
client->subscribe(topic); client->subscribe(topic);
Serial << "new client (" << id.c_str() << ")" << endl;
} }
else else
Serial << "missing id" << endl; Serial << "Missing or existing client name" << endl;
cmd+=" ls"; cmd+=" ls";
} }
else if (compare(s, "delete")) else if (compare(s, "ls") or compare(s, "view"))
{ {
s = getword(cmd); Serial << "--< " << clients.size() << " client/s. >--" << endl;
auto it=clients.find(s);
if (it != clients.end())
{
delete it->second;
clients.erase(it);
cmd+=" ls";
}
else
Serial << "Unknown client (" << s.c_str() << ")" << endl;
}
else if (compare(s, "ls"))
{
Serial << "main : " << clients.size() << " client/s." << endl;
for(auto it: clients) for(auto it: clients)
{ {
Serial << " "; it.second->dump(); Serial << " "; it.second->dump();
} }
broker.dump();
Serial << "--< " << brokers.size() << " brokers/s. >--" << endl;
for(auto it: brokers)
{
Serial << " ==[ Broker: " << it.first.c_str() << " ]== ";
it.second->dump();
}
} }
else if (compare(s, "reset")) else if (compare(s, "reset"))
ESP.restart(); ESP.restart();
@@ -327,11 +396,17 @@ void loop()
else if (compare(s,"help")) else if (compare(s,"help"))
{ {
Serial << "syntax:" << endl; Serial << "syntax:" << endl;
Serial << " new/delete $id" << endl; Serial << " MqttBroker:" << endl;
Serial << " connect $id [ip]" << endl; Serial << " broker {name} {port} : create a new broker" << endl;
Serial << " subscribe $id [topic]" << endl; Serial << endl;
Serial << " publish $id [topic]" << endl; Serial << " MqttClient:" << endl;
Serial << " view $id " << endl; Serial << " client {name} : create a client then" << endl;
Serial << " name.connect [ip]" << endl;
Serial << " name.subscribe [topic]" << endl;
Serial << " name.publish [topic]" << endl;
Serial << " name.view" << endl;
Serial << " name.delete" << endl;
automatic::help(); automatic::help();
Serial << endl; Serial << endl;
Serial << " help" << endl; Serial << " help" << endl;
@@ -341,8 +416,6 @@ void loop()
Serial << " $id : name of the client." << endl; Serial << " $id : name of the client." << endl;
Serial << " default topic is '" << topic.c_str() << "'" << endl; Serial << " default topic is '" << topic.c_str() << "'" << endl;
Serial << endl; Serial << endl;
Serial << " 'function client args' can be written 'client.function args'" << endl;
Serial << endl;
} }
else else
{ {