Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f122d5e902 | ||
|
|
d63793cf77 | ||
|
|
8386779e92 | ||
|
|
1b988a06a2 |
@@ -2,10 +2,33 @@
|
||||
Exemple of commands that can be sent via the serial monitor to tinymqtt-test
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Commands can usually be abbreviated to their first letters.
|
||||
ex: cl for client, a / a.con / a.sub / a.p for publish.
|
||||
|
||||
set name value set variable name to value (later replaced)
|
||||
set name if no value, then var is erased
|
||||
set view all vars
|
||||
reserved keywords are forbidden
|
||||
|
||||
|
||||
client a starts a client (not connected no internal broker)
|
||||
a.connect [server][port][alive] connects the client, default port=1883
|
||||
a.publish topic [payload] send a topic with a payload
|
||||
a.subscribe topic subscribes to a topic
|
||||
delete a destroy the client
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
example:
|
||||
|
||||
client c
|
||||
c.connect broker.emqx.io
|
||||
set topic sensor/temperature
|
||||
|
||||
c.subscribe topic
|
||||
c.publish topic 15
|
||||
c.publish topic 20
|
||||
|
||||
macro exansion example
|
||||
set temp publish sensor/temperature
|
||||
c.temp 20 -> c.publish sensor/temperature 20
|
||||
|
||||
@@ -78,6 +78,71 @@ std::string getword(std::string& str, const char* if_empty=nullptr, char sep=' '
|
||||
return sword;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> vars;
|
||||
|
||||
std::set<std::string> commands = {
|
||||
"auto", "broker", "client", "connect",
|
||||
"create", "delete", "help", "interval",
|
||||
"ls", "ip", "off", "on", "set",
|
||||
"publish", "reset", "subscribe", "view"
|
||||
};
|
||||
|
||||
void getCommand(std::string& search)
|
||||
{
|
||||
while(search[0]==' ') search.erase(0,1);
|
||||
if (search.length()==0) return;
|
||||
std::string matches;
|
||||
int count=0;
|
||||
for(std::string cmd: commands)
|
||||
{
|
||||
if (cmd.substr(0, search.length()) == search)
|
||||
{
|
||||
if (count) matches +=", ";
|
||||
count++;
|
||||
matches += cmd;
|
||||
}
|
||||
}
|
||||
if (count==1)
|
||||
search = matches;
|
||||
else if (count>1)
|
||||
{
|
||||
Serial << "Ambiguous command: " << matches << endl;
|
||||
search="";
|
||||
}
|
||||
}
|
||||
|
||||
void replace(const char* d, std::string& str, std::string srch, std::string to)
|
||||
{
|
||||
if (d[0] && d[1])
|
||||
{
|
||||
srch=d[0]+srch+d[1];
|
||||
to=d[0]+to+d[1];
|
||||
|
||||
size_t pos = 0;
|
||||
while((pos=str.find(srch, pos)) != std::string::npos)
|
||||
{
|
||||
str.erase(pos, srch.length());
|
||||
str.insert(pos, to);
|
||||
pos += to.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void replaceVars(std::string& cmd)
|
||||
{
|
||||
cmd = ' '+cmd+' ';
|
||||
|
||||
for(auto it: vars)
|
||||
{
|
||||
replace("..", cmd, it.first, it.second);
|
||||
replace(". ", cmd, it.first, it.second);
|
||||
replace(" .", cmd, it.first, it.second);
|
||||
replace(" ", cmd, it.first, it.second);
|
||||
}
|
||||
cmd.erase(0, cmd.find_first_not_of(" "));
|
||||
cmd.erase(cmd.find_last_not_of(" ")+1);
|
||||
}
|
||||
|
||||
// publish at regular interval
|
||||
class automatic
|
||||
{
|
||||
@@ -180,6 +245,7 @@ class automatic
|
||||
{
|
||||
Serial << " auto [$id] on/off" << endl;
|
||||
Serial << " auto [$id] view" << endl;
|
||||
Serial << " auto [$id] interval [s]" << endl;
|
||||
Serial << " auto [$id] create [millis] [topic]" << endl;
|
||||
}
|
||||
|
||||
@@ -219,12 +285,16 @@ void loop()
|
||||
|
||||
if (c==10 or c==14)
|
||||
{
|
||||
|
||||
Serial << "----------------[ " << cmd.c_str() << " ]--------------" << endl;
|
||||
static std::string last_cmd;
|
||||
if (cmd=="!")
|
||||
cmd=last_cmd;
|
||||
else
|
||||
last_cmd=cmd;
|
||||
|
||||
replaceVars(cmd);
|
||||
Serial << "---------------@[ " << cmd.c_str() << " ]--------------" << endl;
|
||||
while(cmd.length())
|
||||
{
|
||||
MqttError retval = MqttOk;
|
||||
@@ -235,27 +305,34 @@ void loop()
|
||||
|
||||
// client.function notation
|
||||
// ("a.fun " becomes "fun a ")
|
||||
if (cmd.find('.') != std::string::npos)
|
||||
if (cmd.find('.') != std::string::npos &&
|
||||
cmd.find('.') < cmd.find(' '))
|
||||
{
|
||||
s=getword(cmd, nullptr, '.');
|
||||
|
||||
if (clients.find(s) != clients.end())
|
||||
if (s.length())
|
||||
{
|
||||
client = clients[s];
|
||||
}
|
||||
else if (brokers.find(s) != brokers.end())
|
||||
{
|
||||
broker = brokers[s];
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial << "Unknown class (" << s.c_str() << ")" << endl;
|
||||
cmd="";
|
||||
if (clients.find(s) != clients.end())
|
||||
{
|
||||
client = clients[s];
|
||||
}
|
||||
else if (brokers.find(s) != brokers.end())
|
||||
{
|
||||
broker = brokers[s];
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial << "Unknown class (" << s.c_str() << ")" << endl;
|
||||
cmd="";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s = getword(cmd);
|
||||
if (compare(s, "delete"))
|
||||
if (s.length()) getCommand(s);
|
||||
if (s.length()==0)
|
||||
{}
|
||||
else if (compare(s, "delete"))
|
||||
{
|
||||
if (client==nullptr && broker==nullptr)
|
||||
{
|
||||
@@ -384,6 +461,32 @@ void loop()
|
||||
Serial << "Missing or existing client name" << endl;
|
||||
cmd+=" ls";
|
||||
}
|
||||
else if (compare(s, "set"))
|
||||
{
|
||||
std::string name(getword(cmd));
|
||||
if (name.length()==0)
|
||||
{
|
||||
for(auto it: vars)
|
||||
{
|
||||
Serial << " " << it.first << " -> " << it.second << endl;
|
||||
}
|
||||
}
|
||||
else if (commands.find(name) != commands.end())
|
||||
{
|
||||
Serial << "Reserved keyword (" << name << ")" << endl;
|
||||
cmd.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmd.length())
|
||||
{
|
||||
vars[name] = cmd;
|
||||
cmd.clear();
|
||||
}
|
||||
else if (vars.find(name) != vars.end())
|
||||
vars.erase(vars.find(name));
|
||||
}
|
||||
}
|
||||
else if (compare(s, "ls") or compare(s, "view"))
|
||||
{
|
||||
Serial << "--< " << clients.size() << " client/s. >--" << endl;
|
||||
@@ -421,6 +524,7 @@ void loop()
|
||||
Serial << endl;
|
||||
Serial << " help" << endl;
|
||||
Serial << " ls / ip / reset" << endl;
|
||||
Serial << " set [name][value]" << endl;
|
||||
Serial << " ! repeat last command" << endl;
|
||||
Serial << endl;
|
||||
Serial << " $id : name of the client." << endl;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/hsaturn/TinyMqtt.git"
|
||||
},
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.1",
|
||||
"exclude": "",
|
||||
"examples": "examples/*/*.ino",
|
||||
"frameworks": "arduino",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=TinyMqtt
|
||||
version=0.4.0
|
||||
version=0.5.1
|
||||
author=Francois BIOT, HSaturn, <hsaturn@gmail.com>
|
||||
maintainer=Francois BIOT, HSaturn, <hsaturn@gmail.com>
|
||||
sentence=A tiny broker and client library for MQTT messaging.
|
||||
|
||||
@@ -69,18 +69,18 @@ void MqttClient::connect(std::string broker, uint16_t port, uint16_t ka)
|
||||
if (client->connect(broker.c_str(), port))
|
||||
{
|
||||
debug("cnx: connecting");
|
||||
message.create(MqttMessage::Type::Connect);
|
||||
message.add("MQTT",4);
|
||||
message.add(0x4); // Mqtt protocol version 3.1.1
|
||||
message.add(0x0); // Connect flags TODO user / name
|
||||
MqttMessage msg(MqttMessage::Type::Connect);
|
||||
msg.add("MQTT",4);
|
||||
msg.add(0x4); // Mqtt protocol version 3.1.1
|
||||
msg.add(0x0); // Connect flags TODO user / name
|
||||
|
||||
keep_alive = ka; // TODO not configurable
|
||||
message.add(0x00); // keep_alive
|
||||
message.add((char)keep_alive);
|
||||
message.add(clientId);
|
||||
keep_alive = ka;
|
||||
msg.add(0x00); // keep_alive
|
||||
msg.add((char)keep_alive);
|
||||
msg.add(clientId);
|
||||
debug("cnx: mqtt connecting");
|
||||
message.sendTo(this);
|
||||
message.reset();
|
||||
msg.sendTo(this);
|
||||
msg.reset();
|
||||
debug("cnx: mqtt sent " << (int32_t)parent);
|
||||
|
||||
clientAlive(0);
|
||||
@@ -339,21 +339,22 @@ if (message.type() != MqttMessage::Type::PingReq && message.type() != MqttMessag
|
||||
Serial << "Connected client:" << clientId.c_str() << ", keep alive=" << keep_alive << '.' << endl;
|
||||
bclose = false;
|
||||
mqtt_connected=true;
|
||||
// Reuse received msg
|
||||
message.create(MqttMessage::Type::Connack);
|
||||
message.add(0); // Session present (not implemented)
|
||||
message.add(0); // Connection accepted
|
||||
message.sendTo(this);
|
||||
{
|
||||
MqttMessage msg(MqttMessage::Type::ConnAck);
|
||||
msg.add(0); // Session present (not implemented)
|
||||
msg.add(0); // Connection accepted
|
||||
msg.sendTo(this);
|
||||
}
|
||||
break;
|
||||
|
||||
case MqttMessage::Type::Connack:
|
||||
case MqttMessage::Type::ConnAck:
|
||||
// TODO what more on connack ?
|
||||
mqtt_connected = true;
|
||||
bclose = false;
|
||||
break;
|
||||
|
||||
case MqttMessage::Type::Suback:
|
||||
case MqttMessage::Type::Puback:
|
||||
case MqttMessage::Type::SubAck:
|
||||
case MqttMessage::Type::PubAck:
|
||||
if (!mqtt_connected) break;
|
||||
// Ignore acks
|
||||
bclose = false;
|
||||
@@ -429,11 +430,6 @@ if (message.type() != MqttMessage::Type::PingReq && message.type() != MqttMessag
|
||||
}
|
||||
break;
|
||||
|
||||
case MqttMessage::Type::PubAck:
|
||||
if (!mqtt_connected) break;
|
||||
bclose = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
bclose=true;
|
||||
break;
|
||||
@@ -462,8 +458,7 @@ bool Topic::matches(const Topic& topic) const
|
||||
// publish from local client
|
||||
MqttError MqttClient::publish(const Topic& topic, const char* payload, size_t pay_length)
|
||||
{
|
||||
MqttMessage msg;
|
||||
msg.create(MqttMessage::Publish);
|
||||
MqttMessage msg(MqttMessage::Publish);
|
||||
msg.add(topic);
|
||||
msg.add(payload, pay_length, false);
|
||||
if (parent)
|
||||
|
||||
@@ -41,11 +41,11 @@ class MqttMessage
|
||||
{
|
||||
Unknown = 0,
|
||||
Connect = 0x10,
|
||||
Connack = 0x20,
|
||||
ConnAck = 0x20,
|
||||
Publish = 0x30,
|
||||
PubAck = 0x40,
|
||||
Subscribe = 0x80,
|
||||
Suback = 0x90,
|
||||
SubAck = 0x90,
|
||||
PingReq = 0xC0,
|
||||
PingResp = 0xD0,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user