Update: Add Pre-defined-Topic

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
tomoaki
2018-07-01 18:18:38 +09:00
parent 9ae5c72125
commit bb993aed5b
37 changed files with 1090 additions and 749 deletions

5
.gitignore vendored
View File

@@ -5,3 +5,8 @@
*.pyc *.pyc
/doc/MQTTSNClient/ /doc/MQTTSNClient/
/doc/MQTTSNPacket/ /doc/MQTTSNPacket/
/rbmutex.key
/ringbuffer.key
/Release/
/Debug/
/core

View File

@@ -16,16 +16,17 @@
* *
* Supported functions. * Supported functions.
* *
* void PUBLISH ( const char* topicName, uint8_t* payload, * void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
* uint16_t len, uint8_t qos, bool retain = false );
* *
* void PUBLISH ( uint16_t topicId, uint8_t* payload, * void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
* uint16_t len, uint8_t qos, bool retain = false );
* *
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, * void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
* uint8_t qos );
* *
* void UNSUBSCRIBE( const char* topicName ); * void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
* *
* void DISCONNECT ( uint16_t sleepInSecs ); * void DISCONNECT ( uint16_t sleepInSecs );
* *

View File

@@ -16,16 +16,17 @@
* *
* Supported functions. * Supported functions.
* *
* void PUBLISH ( const char* topicName, uint8_t* payload, * void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
* uint16_t len, uint8_t qos, bool retain = false );
* *
* void PUBLISH ( uint16_t topicId, uint8_t* payload, * void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
* uint16_t len, uint8_t qos, bool retain = false );
* *
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, * void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
* uint8_t qos );
* *
* void UNSUBSCRIBE( const char* topicName ); * void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
* *
* void DISCONNECT ( uint16_t sleepInSecs ); * void DISCONNECT ( uint16_t sleepInSecs );
* *
@@ -112,13 +113,15 @@ int on_Topic03(uint8_t* pload, uint16_t ploadlen)
* A Link list of Callback routines and Topics * A Link list of Callback routines and Topics
*------------------------------------------------------*/ *------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(topic, callback, QoS), SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
//SUB(topic1, on_Topic01, 1),
//SUB(topic4, on_Topic03, 1), // SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic1, 0, on_Topic01, QoS1),
// SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1),
END_OF_SUBSCRIBE_LIST END_OF_SUBSCRIBE_LIST
}; };
/*------------------------------------------------------ /*------------------------------------------------------
* Test functions * Test functions
*------------------------------------------------------*/ *------------------------------------------------------*/

View File

@@ -16,16 +16,17 @@
* *
* Supported functions. * Supported functions.
* *
* void PUBLISH ( const char* topicName, uint8_t* payload, * void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
* uint16_t len, uint8_t qos, bool retain = false );
* *
* void PUBLISH ( uint16_t topicId, uint8_t* payload, * void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
* uint16_t len, uint8_t qos, bool retain = false );
* *
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, * void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
* uint8_t qos );
* *
* void UNSUBSCRIBE( const char* topicName ); * void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
* *
* void DISCONNECT ( uint16_t sleepInSecs ); * void DISCONNECT ( uint16_t sleepInSecs );
* *
@@ -76,6 +77,8 @@ MQTTSNCONF = {
const char* topic1 = "ty4tw/topic1"; const char* topic1 = "ty4tw/topic1";
const char* topic2 = "ty4tw/topic2"; const char* topic2 = "ty4tw/topic2";
const char* topic3 = "ty4tw/topic3"; const char* topic3 = "ty4tw/topic3";
const char* topic4 = "ty4tw/topic4";
const char* topic5 = "ty4tw/topic5";
/*------------------------------------------------------ /*------------------------------------------------------
@@ -100,7 +103,7 @@ int on_Topic02(uint8_t* pload, uint16_t ploadlen)
int on_Topic03(uint8_t* pload, uint16_t ploadlen) int on_Topic03(uint8_t* pload, uint16_t ploadlen)
{ {
DISPLAY("\n\nNew callback recv Topic2\n"); DISPLAY("\n\nNew callback recv Topic3\n");
pload[ploadlen-1]= 0; // set null terminator pload[ploadlen-1]= 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n",pload); DISPLAY("Payload -->%s <--\n\n",pload);
return 0; return 0;
@@ -110,8 +113,9 @@ int on_Topic03(uint8_t* pload, uint16_t ploadlen)
* A Link list of Callback routines and Topics * A Link list of Callback routines and Topics
*------------------------------------------------------*/ *------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(topic, callback, QoS), SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
SUB(topic1, on_Topic01, 1), SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic1, 0, on_Topic01, QoS1),
SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1),
END_OF_SUBSCRIBE_LIST END_OF_SUBSCRIBE_LIST
}; };
@@ -119,29 +123,32 @@ SUBSCRIBE_LIST = {// e.g. SUB(topic, callback, QoS),
/*------------------------------------------------------ /*------------------------------------------------------
* Test functions * Test functions
*------------------------------------------------------*/ *------------------------------------------------------*/
void subscribePredefTopic1(void)
{
SUBSCRIBE(1, on_Topic03, QoS1);
}
void publishTopic1(void) void publishTopic1(void)
{ {
char payload[300]; char payload[300];
sprintf(payload, "publish \"ty4tw/Topic1\" \n"); sprintf(payload, "publish \"ty4tw/Topic1\" \n");
uint8_t qos = 0; PUBLISH(topic1,(uint8_t*)payload, strlen(payload), QoS0);
PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos);
} }
void subscribeTopic2(void) void subscribeTopic2(void)
{ {
uint8_t qos = 1; SUBSCRIBE(10, on_Topic02, QoS1);
SUBSCRIBE(topic2, on_Topic02, qos);
} }
void publishTopic2(void) void publishTopic2(void)
{ {
char payload[300]; char payload[300];
sprintf(payload, "publish \"ty4tw/topic2\" \n"); sprintf(payload, "publish \"ty4tw/topic2\" \n");
uint8_t qos = 0; PUBLISH(topic2,(uint8_t*)payload, strlen(payload), QoS1);
PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos);
} }
void unsubscribe(void) void unsubscribe(void)
{ {
UNSUBSCRIBE(topic2); UNSUBSCRIBE(topic2);
@@ -149,8 +156,7 @@ void unsubscribe(void)
void subscribechangeCallback(void) void subscribechangeCallback(void)
{ {
uint8_t qos = 1; SUBSCRIBE(topic2, on_Topic02, QoS1);
SUBSCRIBE(topic2, on_Topic03, qos);
} }
void test3(void) void test3(void)
@@ -178,6 +184,7 @@ void asleep(void)
*------------------------------------------------------*/ *------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test), TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Step0:Subscribe predef topic1", subscribePredefTopic1),
TEST("Step1:Publish topic1", publishTopic1), TEST("Step1:Publish topic1", publishTopic1),
TEST("Step2:Publish topic2", publishTopic2), TEST("Step2:Publish topic2", publishTopic2),
TEST("Step3:Subscribe topic2", subscribeTopic2), TEST("Step3:Subscribe topic2", subscribeTopic2),

View File

@@ -183,9 +183,9 @@ void LMqttsnClient::subscribe(const char* topicName, TopicCallback onPublish, ui
_subMgr.subscribe(topicName, onPublish, qos); _subMgr.subscribe(topicName, onPublish, qos);
} }
void LMqttsnClient::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType) void LMqttsnClient::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos)
{ {
_subMgr.subscribe(topicId, onPublish, qos, topicType); _subMgr.subscribe(topicId, onPublish, qos);
} }
void LMqttsnClient::unsubscribe(const char* topicName) void LMqttsnClient::unsubscribe(const char* topicName)
@@ -193,6 +193,11 @@ void LMqttsnClient::unsubscribe(const char* topicName)
_subMgr.unsubscribe(topicName); _subMgr.unsubscribe(topicName);
} }
void LMqttsnClient::unsubscribe(const uint16_t topicId)
{
_subMgr.unsubscribe(topicId);
}
void LMqttsnClient::disconnect(uint16_t sleepInSecs) void LMqttsnClient::disconnect(uint16_t sleepInSecs)
{ {
_gwProxy.disconnect(sleepInSecs); _gwProxy.disconnect(sleepInSecs);

View File

@@ -34,7 +34,9 @@ namespace linuxAsyncClient {
struct OnPublishList struct OnPublishList
{ {
MQTTSN_topicTypes type;
const char* topic; const char* topic;
uint16_t id;
int (*pubCallback)(uint8_t* payload, uint16_t payloadlen); int (*pubCallback)(uint8_t* payload, uint16_t payloadlen);
uint8_t qos; uint8_t qos;
}; };
@@ -52,8 +54,9 @@ public:
void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false); void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false);
void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos); void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos);
void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType); void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void unsubscribe(const char* topicName); void unsubscribe(const char* topicName);
void unsubscribe(const uint16_t topicId);
void disconnect(uint16_t sleepInSecs); void disconnect(uint16_t sleepInSecs);
void initialize(LUdpConfig netconf, LMqttsnConfig mqconf); void initialize(LUdpConfig netconf, LMqttsnConfig mqconf);
void run(void); void run(void);

View File

@@ -73,6 +73,15 @@ struct LUdpConfig{
uint16_t uPortNo; uint16_t uPortNo;
}; };
typedef enum
{
MQTTSN_TOPIC_TYPE_NORMAL,
MQTTSN_TOPIC_TYPE_PREDEFINED,
MQTTSN_TOPIC_TYPE_SHORT
} MQTTSN_topicTypes;
/*====================================== /*======================================
MACROs for Application MACROs for Application
=======================================*/ =======================================*/
@@ -93,7 +102,7 @@ struct LUdpConfig{
#define END_OF_TEST_LIST {0, 0, 0} #define END_OF_TEST_LIST {0, 0, 0}
#define SUBSCRIBE_LIST OnPublishList theOnPublishList[] #define SUBSCRIBE_LIST OnPublishList theOnPublishList[]
#define SUB(...) {__VA_ARGS__} #define SUB(...) {__VA_ARGS__}
#define END_OF_SUBSCRIBE_LIST {0,0,0} #define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0}
#define UDPCONF LUdpConfig theNetcon #define UDPCONF LUdpConfig theNetcon
#define MQTTSNCONF LMqttsnConfig theMqcon #define MQTTSNCONF LMqttsnConfig theMqcon
#ifdef CLIENT_MODE #ifdef CLIENT_MODE
@@ -129,6 +138,9 @@ struct LUdpConfig{
/*====================================== /*======================================
MQTT-SN Defines MQTT-SN Defines
========================================*/ ========================================*/
#define QoS0 0
#define QoS1 1
#define QoS2 2
#define MQTTSN_TYPE_ADVERTISE 0x00 #define MQTTSN_TYPE_ADVERTISE 0x00
#define MQTTSN_TYPE_SEARCHGW 0x01 #define MQTTSN_TYPE_SEARCHGW 0x01
#define MQTTSN_TYPE_GWINFO 0x02 #define MQTTSN_TYPE_GWINFO 0x02
@@ -157,9 +169,6 @@ struct LUdpConfig{
#define MQTTSN_TYPE_WILLMSGUPD 0x1C #define MQTTSN_TYPE_WILLMSGUPD 0x1C
#define MQTTSN_TYPE_WILLMSGRESP 0x1D #define MQTTSN_TYPE_WILLMSGRESP 0x1D
#define MQTTSN_TOPIC_TYPE_NORMAL 0x00
#define MQTTSN_TOPIC_TYPE_PREDEFINED 0x01
#define MQTTSN_TOPIC_TYPE_SHORT 0x02
#define MQTTSN_TOPIC_TYPE 0x03 #define MQTTSN_TOPIC_TYPE 0x03
#define MQTTSN_FLAG_DUP 0x80 #define MQTTSN_FLAG_DUP 0x80
@@ -179,14 +188,10 @@ struct LUdpConfig{
#define MQTTSN_RC_REJECTED_INVALID_TOPIC_ID 0x02 #define MQTTSN_RC_REJECTED_INVALID_TOPIC_ID 0x02
#define MQTTSN_RC_REJECTED_NOT_SUPPORTED 0x03 #define MQTTSN_RC_REJECTED_NOT_SUPPORTED 0x03
#define PREDEFINEDID_OTA_REQ (0x0ff0)
#define PREDEFINEDID_OTA_READY (0x0ff1)
#define PREDEFINEDID_OTA_NO_CLIENT (0x0ff2)
/*================================= /*=================================
* Starting prompt * Starting prompt
==================================*/ ==================================*/
#define TESTER_VERSION " * Version: 1.0.0" #define TESTER_VERSION " * Version: 2.0.0"
#define PAHO_COPYRIGHT0 " * MQTT-SN Gateway Tester" #define PAHO_COPYRIGHT0 " * MQTT-SN Gateway Tester"
#define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse" #define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse"

View File

@@ -66,25 +66,22 @@ void LPublishManager::publish(const char* topicName, Payload* payload, uint8_t q
publish(topicName, payload->getRowData(), payload->getLen(), qos, retain); publish(topicName, payload->getRowData(), payload->getLen(), qos, retain);
} }
void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain) void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain)
{
uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL;
if ( strlen(topicName) < 2 )
{
topicType = MQTTSN_TOPIC_TYPE_SHORT;
}
publish(topicName, payload, len, qos, topicType, retain);
}
void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, uint8_t topicType, bool retain)
{ {
uint16_t msgId = 0; uint16_t msgId = 0;
uint8_t topicType = MQTTSN_TOPIC_TYPE_SHORT;
if ( strlen(topicName) > 2 )
{
topicType = MQTTSN_TOPIC_TYPE_NORMAL;
}
if ( qos > 0 ) if ( qos > 0 )
{ {
msgId = theClient->getGwProxy()->getNextMsgId(); msgId = theClient->getGwProxy()->getNextMsgId();
} }
PubElement* elm = add(topicName, 0, payload, len, qos, retain, msgId, topicType); PubElement* elm = add(topicName, 0, payload, len, qos, retain, msgId, topicType);
if (elm->status == TOPICID_IS_READY) if (elm->status == TOPICID_IS_READY)
{ {
sendPublish(elm); sendPublish(elm);
@@ -286,7 +283,7 @@ void LPublishManager::published(uint8_t* msg, uint16_t msglen)
} }
_publishedFlg = NEG_TASK_INDEX; _publishedFlg = NEG_TASK_INDEX;
theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, msg[1] & 0x03); theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, (MQTTSN_topicTypes)(msg[1] & MQTTSN_TOPIC_TYPE));
_publishedFlg = SAVE_TASK_INDEX; _publishedFlg = SAVE_TASK_INDEX;
} }

View File

@@ -62,7 +62,6 @@ public:
~LPublishManager(); ~LPublishManager();
void publish(const char* topicName, Payload* payload, uint8_t qos, bool retain = false); void publish(const char* topicName, Payload* payload, uint8_t qos, bool retain = false);
void publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, uint8_t topicType, bool retain = false);
void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false); void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false);
void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void responce(const uint8_t* msg, uint16_t msglen); void responce(const uint8_t* msg, uint16_t msglen);

View File

@@ -190,13 +190,13 @@ void LRegisterManager::registerTopic(char* topicName)
void LRegisterManager::responceRegAck(uint16_t msgId, uint16_t topicId) void LRegisterManager::responceRegAck(uint16_t msgId, uint16_t topicId)
{ {
const char* topicName = getTopic(msgId); const char* topicName = getTopic(msgId);
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_NORMAL;
if (topicName) if (topicName)
{ {
uint8_t topicType = strlen((char*) topicName) > 2 ? MQTTSN_TOPIC_TYPE_NORMAL : MQTTSN_TOPIC_TYPE_SHORT; theClient->getGwProxy()->getTopicTable()->setTopicId((char*) topicName, topicId, type); // Add Topic to TopicTable
theClient->getGwProxy()->getTopicTable()->setTopicId((char*) topicName, topicId, topicType); // Add Topic to TopicTable
RegQueElement* elm = getElement(msgId); RegQueElement* elm = getElement(msgId);
remove(elm); remove(elm);
theClient->getPublishManager()->sendSuspend((char*) topicName, topicId, topicType); theClient->getPublishManager()->sendSuspend((char*) topicName, topicId, type);
} }
} }
@@ -213,7 +213,7 @@ void LRegisterManager::responceRegister(uint8_t* msg, uint16_t msglen)
{ {
TopicCallback callback = tp->getCallback(); TopicCallback callback = tp->getCallback();
void* topicName = calloc(strlen((char*) msg + 5) + 1, sizeof(char)); void* topicName = calloc(strlen((char*) msg + 5) + 1, sizeof(char));
theClient->getGwProxy()->getTopicTable()->add((char*) topicName, 0, MQTTSN_TOPIC_TYPE_NORMAL, callback, 1); theClient->getGwProxy()->getTopicTable()->add((char*) topicName, MQTTSN_TOPIC_TYPE_NORMAL, 0, callback, 1);
regack[6] = MQTTSN_RC_ACCEPTED; regack[6] = MQTTSN_RC_ACCEPTED;
} }
else else

View File

@@ -64,10 +64,17 @@ void LSubscribeManager::onConnect(void)
if (_first == 0) if (_first == 0)
{ {
for (uint8_t i = 0; theOnPublishList[i].topic != 0; i++) for (uint8_t i = 0; theOnPublishList[i].topic != 0; i++)
{
if ( theOnPublishList[i].type == MQTTSN_TOPIC_TYPE_PREDEFINED)
{
subscribe(theOnPublishList[i].id, theOnPublishList[i].pubCallback, theOnPublishList[i].qos);
}
else
{ {
subscribe(theOnPublishList[i].topic, theOnPublishList[i].pubCallback, theOnPublishList[i].qos); subscribe(theOnPublishList[i].topic, theOnPublishList[i].pubCallback, theOnPublishList[i].qos);
} }
} }
}
else else
{ {
SubElement* elm = _first; SubElement* elm = _first;
@@ -149,30 +156,43 @@ void LSubscribeManager::send(SubElement* elm)
void LSubscribeManager::subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos) void LSubscribeManager::subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos)
{ {
uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL; MQTTSN_topicTypes topicType;
if ( strlen(topicName) <= 2) if ( strlen(topicName) > 2 )
{
topicType = MQTTSN_TOPIC_TYPE_NORMAL;
}
else
{ {
topicType = MQTTSN_TOPIC_TYPE_SHORT; topicType = MQTTSN_TOPIC_TYPE_SHORT;
} }
SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, topicName, 0, topicType, qos, onPublish); SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, topicName, topicType, 0, qos, onPublish);
send(elm); send(elm);
} }
void LSubscribeManager::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType) void LSubscribeManager::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos)
{ {
SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, 0, topicId, topicType, qos, onPublish); SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, 0, MQTTSN_TOPIC_TYPE_PREDEFINED, topicId, qos, onPublish);
send(elm); send(elm);
} }
void LSubscribeManager::unsubscribe(const char* topicName) void LSubscribeManager::unsubscribe(const char* topicName)
{ {
SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, topicName, 0, MQTTSN_TOPIC_TYPE_NORMAL, 0, 0); MQTTSN_topicTypes topicType;
if ( strlen(topicName) > 2 )
{
topicType = MQTTSN_TOPIC_TYPE_NORMAL;
}
else
{
topicType = MQTTSN_TOPIC_TYPE_SHORT;
}
SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, topicName, topicType, 0, 0, 0);
send(elm); send(elm);
} }
void LSubscribeManager::unsubscribe(uint16_t topicId, uint8_t topicType) void LSubscribeManager::unsubscribe( uint16_t topicId)
{ {
SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, 0, topicId, topicType, 0, 0); SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, 0, MQTTSN_TOPIC_TYPE_PREDEFINED, topicId, 0, 0);
send(elm); send(elm);
} }
@@ -214,20 +234,19 @@ void LSubscribeManager::responce(const uint8_t* msg)
uint16_t msgId = getUint16(msg + 4); uint16_t msgId = getUint16(msg + 4);
uint8_t rc = msg[6]; uint8_t rc = msg[6];
LTopicTable* tt = theClient->getGwProxy()->getTopicTable();
SubElement* elm = getElement(msgId); SubElement* elm = getElement(msgId);
if (elm) if (elm)
{ {
if ( rc == MQTTSN_RC_ACCEPTED ) if ( rc == MQTTSN_RC_ACCEPTED )
{ {
tt->add((char*) elm->topicName, topicId, elm->topicType, elm->callback); theClient->getGwProxy()->getTopicTable()->add((char*) elm->topicName, elm->topicType, topicId, elm->callback);
getElement(msgId)->done = SUB_DONE; getElement(msgId)->done = SUB_DONE;
DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Subscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName, topicId); DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Subscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName, topicId);
} }
else else
{ {
remove(elm);
DISPLAY("\033[0m\033[0;31m SUBACK Invalid messageId. %s\033[0m\033[0;37m\n\n", getElement(msgId)->topicName); DISPLAY("\033[0m\033[0;31m SUBACK Invalid messageId. %s\033[0m\033[0;37m\n\n", getElement(msgId)->topicName);
remove(elm);
} }
} }
} }
@@ -237,22 +256,20 @@ void LSubscribeManager::responce(const uint8_t* msg)
SubElement* elm = getElement(msgId); SubElement* elm = getElement(msgId);
if (elm) if (elm)
{ {
LTopicTable* tt = theClient->getGwProxy()->getTopicTable(); //theClient->getGwProxy()->getTopicTable()->setCallback(elm->topicName, 0);
tt->setCallback(elm->topicName, 0);
DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Unsubscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName); DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Unsubscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName);
remove(getElement(msgId)); remove(elm);
} }
else else
{ {
DISPLAY("\033[0m\033[0;31m UNSUBACK Invalid messageId. %s\033[0m\033[0;37m\n\n", getElement(msgId)->topicName); DISPLAY("\033[0m\033[0;31m UNSUBACK Invalid messageId. \033[0m\033[0;37m\n\n");
remove(getElement(msgId));
} }
} }
} }
/* SubElement operations */ /* SubElement operations */
SubElement* LSubscribeManager::add(uint8_t msgType, const char* topicName, uint16_t topicId, uint8_t topicType, SubElement* LSubscribeManager::add(uint8_t msgType, const char* topicName, MQTTSN_topicTypes topicType, uint16_t topicId,
uint8_t qos, TopicCallback callback) uint8_t qos, TopicCallback callback)
{ {
SubElement* elm = 0; SubElement* elm = 0;
@@ -358,7 +375,7 @@ SubElement* LSubscribeManager::getElement(const char* topicName, uint8_t msgType
SubElement* elm = _first; SubElement* elm = _first;
while (elm) while (elm)
{ {
if (strcmp(elm->topicName, topicName) == 0 && elm->msgType == msgType) if ( elm->msgType == msgType && strncmp(elm->topicName, topicName, strlen(topicName)) == 0 )
{ {
return elm; return elm;
} }
@@ -370,7 +387,7 @@ SubElement* LSubscribeManager::getElement(const char* topicName, uint8_t msgType
return 0; return 0;
} }
SubElement* LSubscribeManager::getElement(uint16_t topicId, uint8_t topicType) SubElement* LSubscribeManager::getElement(uint16_t topicId, MQTTSN_topicTypes topicType)
{ {
SubElement* elm = _first; SubElement* elm = _first;
while (elm) while (elm)

View File

@@ -37,7 +37,7 @@ typedef struct SubElement{
time_t sendUTC; time_t sendUTC;
uint16_t topicId; uint16_t topicId;
uint8_t msgType; uint8_t msgType;
uint8_t topicType; MQTTSN_topicTypes topicType;
uint8_t qos; uint8_t qos;
int retryCount; int retryCount;
@@ -56,9 +56,9 @@ public:
~LSubscribeManager(); ~LSubscribeManager();
void onConnect(void); void onConnect(void);
void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos); void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos);
void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType); void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void unsubscribe(const char* topicName); void unsubscribe(const char* topicName);
void unsubscribe(uint16_t topicId, uint8_t topicType); void unsubscribe(uint16_t topicId);
void responce(const uint8_t* msg); void responce(const uint8_t* msg);
void checkTimeout(void); void checkTimeout(void);
bool isDone(void); bool isDone(void);
@@ -66,9 +66,9 @@ private:
void send(SubElement* elm); void send(SubElement* elm);
SubElement* getFirstElement(void); SubElement* getFirstElement(void);
SubElement* getElement(uint16_t msgId); SubElement* getElement(uint16_t msgId);
SubElement* getElement(uint16_t topicId, uint8_t topicType); SubElement* getElement(uint16_t topicId, MQTTSN_topicTypes topicType);
SubElement* getElement(const char* topicName, uint8_t msgType); SubElement* getElement(const char* topicName, uint8_t msgType);
SubElement* add(uint8_t msgType, const char* topicName, uint16_t topicId, uint8_t topicType, uint8_t qos, TopicCallback callback); SubElement* add(uint8_t msgType, const char* topicName, MQTTSN_topicTypes topicType, uint16_t topicId, uint8_t qos, TopicCallback callback);
void remove(SubElement* elm); void remove(SubElement* elm);
SubElement* _first; SubElement* _first;
SubElement* _last; SubElement* _last;

View File

@@ -131,7 +131,7 @@ LTopic* LTopicTable::getTopic(const char* topic){
return 0; return 0;
} }
LTopic* LTopicTable::getTopic(uint16_t topicId, uint8_t topicType){ LTopic* LTopicTable::getTopic(uint16_t topicId, MQTTSN_topicTypes topicType){
LTopic* p = _first; LTopic* p = _first;
while(p){ while(p){
if (p->_topicId == topicId && p->_topicType == topicType){ if (p->_topicId == topicId && p->_topicType == topicType){
@@ -156,12 +156,12 @@ char* LTopicTable::getTopicName(LTopic* topic){
} }
void LTopicTable::setTopicId(const char* topic, uint16_t id, uint8_t type){ void LTopicTable::setTopicId(const char* topic, uint16_t id, MQTTSN_topicTypes type){
LTopic* tp = getTopic(topic); LTopic* tp = getTopic(topic);
if (tp){ if (tp){
tp->_topicId = id; tp->_topicId = id;
}else{ }else{
add(topic, id, type, 0); add(topic, type, id, 0);
} }
} }
@@ -176,7 +176,7 @@ bool LTopicTable::setCallback(const char* topic, TopicCallback callback){
} }
bool LTopicTable::setCallback(uint16_t topicId, uint8_t topicType, TopicCallback callback){ bool LTopicTable::setCallback(uint16_t topicId, MQTTSN_topicTypes topicType, TopicCallback callback){
LTopic* p = getTopic(topicId, topicType); LTopic* p = getTopic(topicId, topicType);
if (p){ if (p){
p->_callback = callback; p->_callback = callback;
@@ -186,7 +186,7 @@ bool LTopicTable::setCallback(uint16_t topicId, uint8_t topicType, TopicCallback
} }
int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, uint8_t topicType){ int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, MQTTSN_topicTypes topicType){
LTopic* p = getTopic(topicId, topicType); LTopic* p = getTopic(topicId, topicType);
if (p){; if (p){;
return p->execCallback(payload, payloadlen); return p->execCallback(payload, payloadlen);
@@ -195,7 +195,7 @@ int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payl
} }
LTopic* LTopicTable::add(const char* topicName, uint16_t id, uint8_t type, TopicCallback callback, uint8_t alocFlg) LTopic* LTopicTable::add(const char* topicName, MQTTSN_topicTypes type, uint16_t id, TopicCallback callback, uint8_t alocFlg)
{ {
LTopic* elm; LTopic* elm;
@@ -234,9 +234,9 @@ exit:
return elm; return elm;
} }
void LTopicTable::remove(uint16_t topicId) void LTopicTable::remove(uint16_t topicId, MQTTSN_topicTypes type)
{ {
LTopic* elm = getTopic(topicId); LTopic* elm = getTopic(topicId, type);
if (elm){ if (elm){
if (elm->_prev == 0) if (elm->_prev == 0)

View File

@@ -42,7 +42,7 @@ public:
TopicCallback getCallback(void); TopicCallback getCallback(void);
private: private:
uint16_t _topicId; uint16_t _topicId;
uint8_t _topicType; MQTTSN_topicTypes _topicType;
char* _topicStr; char* _topicStr;
TopicCallback _callback; TopicCallback _callback;
uint8_t _malocFlg; uint8_t _malocFlg;
@@ -60,16 +60,16 @@ public:
uint16_t getTopicId(const char* topic); uint16_t getTopicId(const char* topic);
char* getTopicName(LTopic* topic); char* getTopicName(LTopic* topic);
LTopic* getTopic(const char* topic); LTopic* getTopic(const char* topic);
LTopic* getTopic(uint16_t topicId, uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL); LTopic* getTopic(uint16_t topicId, MQTTSN_topicTypes topicType);
void setTopicId(const char* topic, uint16_t id, uint8_t topicType); void setTopicId(const char* topic, uint16_t id, MQTTSN_topicTypes topicType);
bool setCallback(const char* topic, TopicCallback callback); bool setCallback(const char* topic, TopicCallback callback);
bool setCallback(uint16_t topicId, uint8_t type, TopicCallback callback); bool setCallback(uint16_t topicId, MQTTSN_topicTypes type, TopicCallback callback);
int execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL); int execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, MQTTSN_topicTypes topicType);
LTopic* add(const char* topic, uint16_t id = 0, uint8_t type = MQTTSN_TOPIC_TYPE_NORMAL, TopicCallback callback = 0, uint8_t alocFlg = 0); LTopic* add(const char* topic, MQTTSN_topicTypes type, uint16_t id = 0, TopicCallback callback = 0, uint8_t alocFlg = 0);
LTopic* add(uint16_t topicId, uint16_t id, uint8_t type, TopicCallback callback, uint8_t alocFlg); //LTopic* add(uint16_t topicId, uint16_t id, MQTTSN_topicTypes type, TopicCallback callback, uint8_t alocFlg);
LTopic* match(const char* topic); LTopic* match(const char* topic);
void clearTopic(void); void clearTopic(void);
void remove(uint16_t topicId); void remove(uint16_t topicId, MQTTSN_topicTypes type);
private: private:
LTopic* _first; LTopic* _first;

View File

@@ -9,6 +9,7 @@ TESTAPPL := mainTestProcess
CONFIG := gateway.conf CONFIG := gateway.conf
CLIENTS := clients.conf CLIENTS := clients.conf
PREDEFTOPIC := predefinedTopic.conf
SRCDIR := src SRCDIR := src
SUBDIR := ../MQTTSNPacket/src SUBDIR := ../MQTTSNPacket/src
@@ -135,6 +136,7 @@ install:
cp -pf $(LPROG) ../../ cp -pf $(LPROG) ../../
cp -pf $(CONFIG) ../../ cp -pf $(CONFIG) ../../
cp -pf $(CLIENTS) ../../ cp -pf $(CLIENTS) ../../
cp -pf $(PREDEFTOPIC) ../../
exectest: exectest:
./$(OUTDIR)/$(TESTPROGNAME) -f ./gateway.conf ./$(OUTDIR)/$(TESTPROGNAME) -f ./gateway.conf

View File

@@ -61,6 +61,8 @@ Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW messag
**GatewayId** is used by GWINFO message. **GatewayId** is used by GWINFO message.
**KeepAlive** is a duration of ADVERTISE message in seconds. **KeepAlive** is a duration of ADVERTISE message in seconds.
when **ClientAuthentication** is YES, see MQTTSNGWClient.cpp line53, clients file specified by ClientsList is required. This file defines connect allowed clients by ClientId and SensorNetwork Address. e.g. IP address and Port No. when **ClientAuthentication** is YES, see MQTTSNGWClient.cpp line53, clients file specified by ClientsList is required. This file defines connect allowed clients by ClientId and SensorNetwork Address. e.g. IP address and Port No.
When **PredefinedTopic** is YES, Pre-definedTopicID file specified by PredefinedTopicFile is effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format.

View File

@@ -20,6 +20,9 @@ BrokerSecurePortNo=8883
ClientAuthentication=NO ClientAuthentication=NO
#ClientsList=/path/to/your_clients.conf #ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO
#PredefinedTopicFile=/path/to/your_predefinedTopic.conf
#RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/ #RootCApath=/etc/ssl/certs/
#CertsFile=/path/to/certKey.pem #CertsFile=/path/to/certKey.pem

View File

@@ -0,0 +1,19 @@
#***********************************************************************
# Copyright (c) 2017, Tomoaki Yamaguchi
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v1.0 which accompany this distribution.
#
# The Eclipse Public License is available at
# http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#***********************************************************************
#
# ClientID, TopicName, TopicID
#
GatewayTestClient,ty4tw/predefinedTopic1, 1
GatewayTestClient,ty4tw/predefinedTopic2, 2
GatewayTestClient,ty4tw/predefinedTopic3, 3

View File

@@ -90,18 +90,21 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
} }
else else
{ {
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
topicId.data.long_.len = pub.topiclen; topicId.data.long_.len = pub.topiclen;
topicId.data.long_.name = pub.topic; topicId.data.long_.name = pub.topic;
id = client->getTopics()->getTopicId(&topicId); Topic* tp = client->getTopics()->getTopicByName(&topicId);
if ( id > 0 ) if ( tp )
{ {
topicId.data.id = id; topicId.type = tp->getType();
topicId.data.long_.len = pub.topiclen;
topicId.data.long_.name = pub.topic;
topicId.data.id = tp->getTopicId();
} }
else else
{ {
/* This message might be subscribed with wild card. */ /* This message might be subscribed with wild card. */
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
Topic* topic = client->getTopics()->match(&topicId); Topic* topic = client->getTopics()->match(&topicId);
if (topic == 0) if (topic == 0)
{ {
@@ -179,11 +182,11 @@ void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet)
{ {
Ack ack; Ack ack;
packet->getAck(&ack); packet->getAck(&ack);
uint16_t topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId); TopicIdMapelement* topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId);
if (topicId) if (topicId)
{ {
MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); MQTTSNPacket* mqttsnPacket = new MQTTSNPacket();
mqttsnPacket->setPUBACK(topicId, (uint16_t)ack.msgId, 0); mqttsnPacket->setPUBACK(topicId->getTopicId(), (uint16_t)ack.msgId, 0);
client->eraseWaitedPubTopicId((uint16_t)ack.msgId); client->eraseWaitedPubTopicId((uint16_t)ack.msgId);
Event* ev1 = new Event(); Event* ev1 = new Event();

View File

@@ -38,12 +38,11 @@ void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet)
int qos = 0; int qos = 0;
packet->getSUBACK(&msgId, &rc); packet->getSUBACK(&msgId, &rc);
uint16_t topicId = client->getWaitedSubTopicId(msgId); TopicIdMapelement* topicId = client->getWaitedSubTopicId(msgId);
if (topicId) if (topicId)
{ {
MQTTSNPacket* snPacket = new MQTTSNPacket(); MQTTSNPacket* snPacket = new MQTTSNPacket();
client->eraseWaitedSubTopicId(msgId);
if (rc == 0x80) if (rc == 0x80)
{ {
@@ -54,10 +53,11 @@ void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet)
returnCode = MQTTSN_RC_ACCEPTED; returnCode = MQTTSN_RC_ACCEPTED;
qos = rc; qos = rc;
} }
snPacket->setSUBACK(qos, topicId, msgId, returnCode); snPacket->setSUBACK(qos, topicId->getTopicId(), msgId, returnCode);
Event* evt = new Event(); Event* evt = new Event();
evt->setClientSendEvent(client, snPacket); evt->setClientSendEvent(client, snPacket);
_gateway->getClientSendQue()->post(evt); _gateway->getClientSendQue()->post(evt);
client->eraseWaitedSubTopicId(msgId);
} }
} }

View File

@@ -15,6 +15,7 @@
* Tieto Poland Sp. z o.o. - Gateway improvements * Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWDefines.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
#include "SensorNetwork.h" #include "SensorNetwork.h"
@@ -124,6 +125,51 @@ bool ClientList::authorize(const char* fileName)
return _authorize; return _authorize;
} }
bool ClientList::setPredefinedTopics(const char* fileName)
{
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos0, pos1;
MQTTSNString clientId;
bool rc = false;
clientId.cstring = 0;
clientId.lenstring.data = 0;
clientId.lenstring.len = 0;
if ((fp = fopen(fileName, "r")) != 0)
{
while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
{
if (*buf == '#')
{
continue;
}
string data = string(buf);
while ((pos0 = data.find_first_of("  \t\n")) != string::npos)
{
data.erase(pos0, 1);
}
if (data.empty())
{
continue;
}
pos0 = data.find_first_of(",");
pos1 = data.find(",", pos0 + 1) ;
string id = data.substr(0, pos0);
clientId.cstring = strdup(id.c_str());
string topicName = data.substr(pos0 + 1, pos1 - pos0 -1);
uint16_t topicID = stoul(data.substr(pos1 + 1));
createPredefinedTopic( &clientId, topicName, topicID);
free(clientId.cstring);
}
fclose(fp);
rc = true;
}
return rc;
}
void ClientList::erase(Client*& client) void ClientList::erase(Client*& client)
{ {
if ( !_authorize && client->erasable()) if ( !_authorize && client->erasable())
@@ -179,14 +225,21 @@ Client* ClientList::getClient(void)
return _firstClient; return _firstClient;
} }
Client* ClientList::getClient(uint8_t* clientId)
Client* ClientList::getClient(MQTTSNString* clientId)
{ {
_mutex.lock(); _mutex.lock();
Client* client = _firstClient; Client* client = _firstClient;
const char* clID =clientId->cstring;
if (clID == 0 )
{
clID = clientId->lenstring.data;
}
while (client != 0) while (client != 0)
{ {
if (strcmp((const char*)client->getClientId(), (const char*)clientId) == 0 ) if (strncmp((const char*)client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0 )
{ {
_mutex.unlock(); _mutex.unlock();
return client; return client;
@@ -222,7 +275,10 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
/* creat a new client */ /* creat a new client */
client = new Client(secure); client = new Client(secure);
if ( addr )
{
client->setClientAddress(addr); client->setClientAddress(addr);
}
client->setSensorNetType(unstableLine); client->setSensorNetType(unstableLine);
if ( MQTTSNstrlen(*clientId) ) if ( MQTTSNstrlen(*clientId) )
{ {
@@ -256,6 +312,50 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
return client; return client;
} }
Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t topicId)
{
Client* client = getClient(clientId);
if ( _authorize && client == 0)
{
return 0;
}
/* anonimous clients */
if ( _clientCnt > MAX_CLIENTS )
{
return 0; // full of clients
}
if ( client == 0 )
{
/* creat a new client */
client = new Client();
client->setClientId(*clientId);
_mutex.lock();
/* add the list */
if ( _firstClient == 0 )
{
_firstClient = client;
_endClient = client;
}
else
{
_endClient->_nextClient = client;
client->_prevClient = _endClient;
_endClient = client;
}
_clientCnt++;
_mutex.unlock();
}
// create Topic & Add it
client->getTopics()->add((const char*)topicName.c_str(), topicId);
return client;
}
uint16_t ClientList::getClientCount() uint16_t ClientList::getClientCount()
{ {
return _clientCnt; return _clientCnt;
@@ -299,6 +399,7 @@ Client::Client(bool secure)
_prevClient = 0; _prevClient = 0;
_nextClient = 0; _nextClient = 0;
_clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH); _clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH);
_hasPredefTopic = false;
} }
Client::~Client() Client::~Client()
@@ -334,16 +435,14 @@ Client::~Client()
} }
} }
uint16_t Client::getWaitedPubTopicId(uint16_t msgId) TopicIdMapelement* Client::getWaitedPubTopicId(uint16_t msgId)
{ {
MQTTSN_topicTypes type; return _waitedPubTopicIdMap.getElement(msgId);
return _waitedPubTopicIdMap.getTopicId(msgId, &type);
} }
uint16_t Client::getWaitedSubTopicId(uint16_t msgId) TopicIdMapelement* Client::getWaitedSubTopicId(uint16_t msgId)
{ {
MQTTSN_topicTypes type; return _waitedSubTopicIdMap.getElement(msgId);
return _waitedSubTopicIdMap.getTopicId(msgId, &type);
} }
MQTTGWPacket* Client::getClientSleepPacket() MQTTGWPacket* Client::getClientSleepPacket()
@@ -426,7 +525,7 @@ void Client::setSessionStatus(bool status)
bool Client::erasable(void) bool Client::erasable(void)
{ {
return _sessionStatus; return _sessionStatus || !_hasPredefTopic;
} }
void Client::updateStatus(MQTTSNPacket* packet) void Client::updateStatus(MQTTSNPacket* packet)
@@ -702,13 +801,15 @@ void Client::setOTAClient(Client* cl)
======================================*/ ======================================*/
Topic::Topic() Topic::Topic()
{ {
_type = MQTTSN_TOPIC_TYPE_NORMAL;
_topicName = 0; _topicName = 0;
_topicId = 0; _topicId = 0;
_next = 0; _next = 0;
} }
Topic::Topic(string* topic) Topic::Topic(string* topic, MQTTSN_topicTypes type)
{ {
_type = type;
_topicName = topic; _topicName = topic;
_topicId = 0; _topicId = 0;
_next = 0; _next = 0;
@@ -732,6 +833,11 @@ uint16_t Topic::getTopicId(void)
return _topicId; return _topicId;
} }
MQTTSN_topicTypes Topic::getType(void)
{
return _type;
}
bool Topic::isMatch(string* topicName) bool Topic::isMatch(string* topicName)
{ {
string::size_type tlen = _topicName->size(); string::size_type tlen = _topicName->size();
@@ -824,6 +930,11 @@ bool Topic::isMatch(string* topicName)
} }
} }
void Topic::print(void)
{
WRITELOG("TopicName=%s ID=%d Type=%d\n", _topicName->c_str(), _topicId, _type);
}
/*===================================== /*=====================================
Class Topics Class Topics
======================================*/ ======================================*/
@@ -831,6 +942,7 @@ Topics::Topics()
{ {
_first = 0; _first = 0;
_nextTopicId = 0; _nextTopicId = 0;
_cnt = 0;
} }
Topics::~Topics() Topics::~Topics()
@@ -844,32 +956,15 @@ Topics::~Topics()
} }
} }
uint16_t Topics::getTopicId(const MQTTSN_topicid* topicid) Topic* Topics::getTopicByName(const MQTTSN_topicid* topicid)
{
if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL)
{
return 0;
}
Topic* p = _first;
while (p)
{
if ( (int)strlen(p->_topicName->c_str()) == topicid->data.long_.len &&
strncmp(p->_topicName->c_str(), topicid->data.long_.name, topicid->data.long_.len) == 0)
{
return p->_topicId;
}
p = p->_next;
}
return 0;
}
Topic* Topics::getTopic(uint16_t id)
{ {
Topic* p = _first; Topic* p = _first;
char* ch = topicid->data.long_.name;
string sname = string(ch, ch + topicid->data.long_.len);
while (p) while (p)
{ {
if (p->_topicId == id) if ( p->_topicName->compare(sname) == 0 )
{ {
return p; return p;
} }
@@ -878,13 +973,13 @@ Topic* Topics::getTopic(uint16_t id)
return 0; return 0;
} }
Topic* Topics::getTopic(const MQTTSN_topicid* topicid) Topic* Topics::getTopicById(const MQTTSN_topicid* topicid)
{ {
Topic* p = _first; Topic* p = _first;
while (p) while (p)
{ {
if ( (int)strlen(p->_topicName->c_str()) == topicid->data.long_.len && if ( p->_type == topicid->type && p->_topicId == topicid->data.id )
strncmp(p->_topicName->c_str(), topicid->data.long_.name, topicid->data.long_.len) == 0 )
{ {
return p; return p;
} }
@@ -893,35 +988,43 @@ Topic* Topics::getTopic(const MQTTSN_topicid* topicid)
return 0; return 0;
} }
// For MQTTSN_TOPIC_TYPE_NORMAL */
Topic* Topics::add(const MQTTSN_topicid* topicid) Topic* Topics::add(const MQTTSN_topicid* topicid)
{ {
Topic* topic; if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL )
uint16_t id = 0;
if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL)
{ {
return 0; return 0;
} }
id = getTopicId(topicid);
if (id) Topic* topic = getTopicByName(topicid);
if ( topic )
{ {
topic = getTopic(id);
}
else
{
string topicName = string(topicid->data.long_.name, topicid->data.long_.len);
topic = add(&topicName);
}
return topic; return topic;
}
string name(topicid->data.long_.name, topicid->data.long_.len);
return add(name.c_str(), 0);
} }
Topic* Topics::add(const char* topicName, uint16_t id)
Topic* Topics::add(const string* topicName)
{ {
Topic* topic = 0; MQTTSN_topicid topicId;
Topic* tp = _first; if ( _cnt >= MAX_TOPIC_PAR_CLIENT )
{
return 0;
}
topicId.data.long_.name = (char*)const_cast<char*>(topicName);
topicId.data.long_.len = strlen(topicName);
Topic* topic = getTopicByName(&topicId);
if ( topic )
{
return topic;
}
topic = new Topic(); topic = new Topic();
@@ -929,15 +1032,30 @@ Topic* Topics::add(const string* topicName)
{ {
return 0; return 0;
} }
string* name = new string(*topicName);
topic->_topicName = name;
topic->_topicId = getNextTopicId();
if (tp == 0) string* name = new string(topicName);
topic->_topicName = name;
if ( id == 0 )
{
topic->_type = MQTTSN_TOPIC_TYPE_NORMAL;
topic->_topicId = getNextTopicId();
}
else
{
topic->_type = MQTTSN_TOPIC_TYPE_PREDEFINED;
topic->_topicId = id;
}
_cnt++;
if ( _first == 0)
{ {
_first = topic; _first = topic;
} }
else
{
Topic* tp = _first;
while (tp) while (tp)
{ {
if (tp->_next == 0) if (tp->_next == 0)
@@ -950,6 +1068,7 @@ Topic* Topics::add(const string* topicName)
tp = tp->_next; tp = tp->_next;
} }
} }
}
return topic; return topic;
} }
@@ -978,6 +1097,60 @@ Topic* Topics::match(const MQTTSN_topicid* topicid)
return 0; return 0;
} }
void Topics::eraseNormal(void)
{
Topic* topic = _first;
Topic* next = 0;
Topic* prev = 0;
while (topic)
{
if ( topic->_type == MQTTSN_TOPIC_TYPE_NORMAL )
{
next = topic->_next;
if ( _first == topic )
{
_first = next;
}
if ( prev )
{
prev->_next = next;
}
delete topic;
_cnt--;
topic = next;
}
else
{
prev = topic;
topic = topic->_next;
}
}
}
void Topics::print(void)
{
Topic* topic = _first;
if (topic == 0 )
{
WRITELOG("No Topic.\n");
}
else
{
while (topic)
{
topic->print();
topic = topic->_next;
}
}
}
uint8_t Topics::getCount(void)
{
return _cnt;
}
/*===================================== /*=====================================
Class TopicIdMap Class TopicIdMap
=====================================*/ =====================================*/
@@ -995,6 +1168,16 @@ TopicIdMapelement::~TopicIdMapelement()
} }
MQTTSN_topicTypes TopicIdMapelement::getTopicType(void)
{
return _type;
}
uint16_t TopicIdMapelement::getTopicId(void)
{
return _topicId;
}
TopicIdMap::TopicIdMap() TopicIdMap::TopicIdMap()
{ {
_maxInflight = MAX_INFLIGHTMESSAGES; _maxInflight = MAX_INFLIGHTMESSAGES;
@@ -1015,28 +1198,27 @@ TopicIdMap::~TopicIdMap()
} }
} }
uint16_t TopicIdMap::getTopicId(uint16_t msgId, MQTTSN_topicTypes* type) TopicIdMapelement* TopicIdMap::getElement(uint16_t msgId)
{ {
TopicIdMapelement* p = _first; TopicIdMapelement* p = _first;
while ( p ) while ( p )
{ {
if ( p->_msgId == msgId ) if ( p->_msgId == msgId )
{ {
*type = p->_type; return p;
return p->_topicId;
} }
p = p->_next; p = p->_next;
} }
return 0; return 0;
} }
int TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) TopicIdMapelement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
{ {
if ( _cnt > _maxInflight * 2 || topicId == 0) if ( _cnt > _maxInflight * 2 || topicId == 0)
{ {
return 0; return 0;
} }
if ( getTopicId(msgId, &type) > 0 ) if ( getElement(msgId) > 0 )
{ {
erase(msgId); erase(msgId);
} }
@@ -1058,7 +1240,7 @@ int TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
_end = elm; _end = elm;
} }
_cnt++; _cnt++;
return 1; return elm;
} }
void TopicIdMap::erase(uint16_t msgId) void TopicIdMap::erase(uint16_t msgId)

View File

@@ -117,13 +117,15 @@ class Topic
friend class Topics; friend class Topics;
public: public:
Topic(); Topic();
Topic(string* topic); Topic(string* topic, MQTTSN_topicTypes type);
~Topic(); ~Topic();
string* getTopicName(void); string* getTopicName(void);
uint16_t getTopicId(void); uint16_t getTopicId(void);
MQTTSN_topicTypes getType(void);
bool isMatch(string* topicName); bool isMatch(string* topicName);
void print(void);
private: private:
MQTTSN_topicTypes _type;
uint16_t _topicId; uint16_t _topicId;
string* _topicName; string* _topicName;
Topic* _next; Topic* _next;
@@ -138,17 +140,18 @@ public:
Topics(); Topics();
~Topics(); ~Topics();
Topic* add(const MQTTSN_topicid* topicid); Topic* add(const MQTTSN_topicid* topicid);
Topic* add(const string* topic); Topic* add(const char* topicName, uint16_t id = 0);
uint16_t getTopicId(const MQTTSN_topicid* topic); Topic* getTopicByName(const MQTTSN_topicid* topic);
uint16_t getNextTopicId(); Topic* getTopicById(const MQTTSN_topicid* topicid);
Topic* getTopic(uint16_t topicId);
Topic* getTopic(const MQTTSN_topicid* topicid);
Topic* match(const MQTTSN_topicid* topicid); Topic* match(const MQTTSN_topicid* topicid);
void eraseNormal(void);
uint16_t getNextTopicId();
void print(void);
uint8_t getCount(void);
private: private:
uint16_t _nextTopicId; uint16_t _nextTopicId;
Topic* _first; Topic* _first;
uint8_t _cnt;
}; };
/*===================================== /*=====================================
@@ -160,6 +163,8 @@ class TopicIdMapelement
public: public:
TopicIdMapelement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); TopicIdMapelement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
~TopicIdMapelement(); ~TopicIdMapelement();
MQTTSN_topicTypes getTopicType(void);
uint16_t getTopicId(void);
private: private:
uint16_t _msgId; uint16_t _msgId;
@@ -174,8 +179,8 @@ class TopicIdMap
public: public:
TopicIdMap(); TopicIdMap();
~TopicIdMap(); ~TopicIdMap();
uint16_t getTopicId(uint16_t msgId, MQTTSN_topicTypes* type); TopicIdMapelement* getElement(uint16_t msgId);
int add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); TopicIdMapelement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
void erase(uint16_t msgId); void erase(uint16_t msgId);
void clear(void); void clear(void);
private: private:
@@ -240,8 +245,8 @@ public:
~Client(); ~Client();
Connect* getConnectData(void); Connect* getConnectData(void);
uint16_t getWaitedPubTopicId(uint16_t msgId); TopicIdMapelement* getWaitedPubTopicId(uint16_t msgId);
uint16_t getWaitedSubTopicId(uint16_t msgId); TopicIdMapelement* getWaitedSubTopicId(uint16_t msgId);
MQTTGWPacket* getClientSleepPacket(void); MQTTGWPacket* getClientSleepPacket(void);
void deleteFirstClientSleepPacket(void); void deleteFirstClientSleepPacket(void);
WaitREGACKPacketList* getWaitREGACKPacketList(void); WaitREGACKPacketList* getWaitREGACKPacketList(void);
@@ -327,6 +332,7 @@ private:
SensorNetAddress _sensorNetAddr; SensorNetAddress _sensorNetAddr;
bool _sessionStatus; bool _sessionStatus;
bool _hasPredefTopic;
Client* _nextClient; Client* _nextClient;
Client* _prevClient; Client* _prevClient;
@@ -342,15 +348,16 @@ public:
ClientList(); ClientList();
~ClientList(); ~ClientList();
bool authorize(const char* fileName); bool authorize(const char* fileName);
bool setPredefinedTopics(const char* fileName);
void erase(Client*&); void erase(Client*&);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure);
Client* getClient(SensorNetAddress* addr); Client* getClient(SensorNetAddress* addr);
Client* getClient(uint8_t* clientId); Client* getClient(MQTTSNString* clientId);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine,
bool secure);
uint16_t getClientCount(void); uint16_t getClientCount(void);
Client* getClient(void); Client* getClient(void);
bool isAuthorized(); bool isAuthorized();
private: private:
Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId);
Client* _firstClient; Client* _firstClient;
Client* _endClient; Client* _endClient;
Mutex _mutex; Mutex _mutex;

View File

@@ -115,9 +115,21 @@ void ClientRecvTask::run()
continue; continue;
} }
client = _gateway->getClientList()->getClient(&data.clientID);
if ( client )
{
/* set SensorNet Address */
client->setClientAddress(_sensorNetwork->getSenderAddress());
}
else
{
/* create a client */ /* create a client */
client = _gateway->getClientList()->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, false, false); client = _gateway->getClientList()->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, false, false);
}
log(client, packet, &data.clientID); log(client, packet, &data.clientID);
if (!client) if (!client)
{ {
WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
@@ -126,7 +138,6 @@ void ClientRecvTask::run()
} }
/* set sensorNetAddress & post Event */ /* set sensorNetAddress & post Event */
client->setClientAddress(_sensorNetwork->getSenderAddress());
ev = new Event(); ev = new Event();
ev->setClientRecvEvent(client, packet); ev->setClientRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev); _gateway->getPacketEventQue()->post(ev);

View File

@@ -116,10 +116,8 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet
/* renew the TopicList */ /* renew the TopicList */
if (topics) if (topics)
{ {
delete topics; topics->eraseNormal();;
} }
topics = new Topics();
client->setTopics(topics);
client->setSessionStatus(true); client->setSessionStatus(true);
} }

View File

@@ -25,6 +25,7 @@ namespace MQTTSNGW
#define CONFIG_DIRECTORY "./" #define CONFIG_DIRECTORY "./"
#define CONFIG_FILE "gateway.conf" #define CONFIG_FILE "gateway.conf"
#define CLIENT_LIST "clients.conf" #define CLIENT_LIST "clients.conf"
#define PREDEFINEDTOPIC_FILE "predefinedTopic.conf"
/*========================================================== /*==========================================================
* Gateway default parameters * Gateway default parameters
@@ -39,6 +40,7 @@ namespace MQTTSNGW
#define MAX_CLIENTID_LENGTH (64) // Max length of clientID #define MAX_CLIENTID_LENGTH (64) // Max length of clientID
#define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages #define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages
#define MAX_SAVED_PUBLISH (20) // Max number of PUBLISH message for Asleep state #define MAX_SAVED_PUBLISH (20) // Max number of PUBLISH message for Asleep state
#define MAX_TOPIC_PAR_CLIENT (50) // Max Topic count for a client. it should be less than 256
#define MQTTSNGW_MAX_PACKET_SIZE (1024) // Max Packet size (5+2+TopicLen+PayloadLen) #define MQTTSNGW_MAX_PACKET_SIZE (1024) // Max Packet size (5+2+TopicLen+PayloadLen)
#define SIZE_OF_LOG_PACKET (500) // Length of the packet log in bytes #define SIZE_OF_LOG_PACKET (500) // Length of the packet log in bytes

View File

@@ -40,8 +40,8 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
int qos; int qos;
uint8_t retained; uint8_t retained;
uint16_t msgId; uint16_t msgId;
MQTTSN_topicid topicid;
uint8_t* payload; uint8_t* payload;
MQTTSN_topicid topicid;
int payloadlen; int payloadlen;
Publish pub; Publish pub;
char shortTopic[2]; char shortTopic[2];
@@ -68,68 +68,6 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
Topic* topic = 0; Topic* topic = 0;
if ( topicid.type == MQTTSN_TOPIC_TYPE_PREDEFINED)
{
if(msgId)
{
/* Reply PubAck to the client */
MQTTSNPacket* pubAck = new MQTTSNPacket();
pubAck->setPUBACK( topicid.data.id, msgId, MQTTSN_RC_ACCEPTED);
Event* ev1 = new Event();
ev1->setClientSendEvent(client, pubAck);
_gateway->getClientSendQue()->post(ev1);
}
#ifdef OTA_CLIENTS
if ( topicid.data.id == PREDEFINEDID_OTA_REQ )
{
uint8_t clientId[MAX_CLIENTID_LENGTH + 1];
if ( payloadlen <= MAX_CLIENTID_LENGTH )
{
memcpy(clientId, payload, payloadlen);
clientId[payloadlen] = 0;
Client* cl = _gateway->getClientList()->getClient(clientId);
if ( cl )
{
WRITELOG("\033[0m\033[0;33m OTA Client : %s\033[0m\033[0;37m\n",cl->getClientId());
MQTTSNPacket* pubota = new MQTTSNPacket();
pubota->setPUBLISH(0, 0, 0, 0, topicid, 0, 0);
cl->setOTAClient(client);
Event* evt = new Event();
evt->setClientSendEvent(cl, pubota);
_gateway->getClientSendQue()->post(evt);
}
else
{
MQTTSNPacket* publish = new MQTTSNPacket();
topicid.data.id = PREDEFINEDID_OTA_NO_CLIENT;
publish->setPUBLISH(0, 0, 0, 0, topicid, clientId, (uint16_t)strlen((const char*)clientId));
Event* evt = new Event();
evt->setClientSendEvent(client, publish);
_gateway->getClientSendQue()->post(evt);
}
}
}
else if ( topicid.data.id == PREDEFINEDID_OTA_READY )
{
Client* cl = client->getOTAClient();
if ( cl )
{
WRITELOG("\033[0m\033[0;33m OTA Manager : %s\033[0m\033[0;37m\n",cl->getClientId());
MQTTSNPacket* pubota = new MQTTSNPacket();
pubota->setPUBLISH(0, 0, 0, 0, topicid, payload, payloadlen);
client->setOTAClient(0);
Event* evt = new Event();
evt->setClientSendEvent(cl, pubota);
_gateway->getClientSendQue()->post(evt);
}
}
#endif
return;
}
if( topicid.type == MQTTSN_TOPIC_TYPE_SHORT ) if( topicid.type == MQTTSN_TOPIC_TYPE_SHORT )
{ {
shortTopic[0] = topicid.data.short_name[0]; shortTopic[0] = topicid.data.short_name[0];
@@ -137,10 +75,10 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
pub.topic = shortTopic; pub.topic = shortTopic;
pub.topiclen = 2; pub.topiclen = 2;
} }
else
if ( topicid.type == MQTTSN_TOPIC_TYPE_NORMAL )
{ {
topic = client->getTopics()->getTopic(topicid.data.id); topic = client->getTopics()->getTopicById(&topicid);
if( !topic && msgId && qos > 0 ) if( !topic && msgId && qos > 0 )
{ {
/* Reply PubAck with INVALID_TOPIC_ID to the client */ /* Reply PubAck with INVALID_TOPIC_ID to the client */

View File

@@ -41,161 +41,123 @@ void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packe
uint16_t msgId; uint16_t msgId;
MQTTSN_topicid topicFilter; MQTTSN_topicid topicFilter;
Topic* topic = 0; Topic* topic = 0;
uint16_t topicId = 0;
MQTTGWPacket* subscribe;
Event* ev1;
Event* evsuback;
if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 ) if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 )
{ {
return; return;
} }
if (topicFilter.type <= MQTTSN_TOPIC_TYPE_SHORT) if ( msgId == 0 )
{
if (topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED)
{
/*----- Predefined TopicId ------*/
MQTTSNPacket* sSuback = new MQTTSNPacket();
if (msgId)
{
int rc = MQTTSN_RC_ACCEPTED;
switch (topicFilter.data.id)
{
case PREDEFINEDID_OTA_REQ: // check topicIds are defined.
case PREDEFINEDID_OTA_READY:
case PREDEFINEDID_OTA_NO_CLIENT:
break;
default:
rc = MQTTSN_RC_REJECTED_INVALID_TOPIC_ID;
}
sSuback->setSUBACK(qos, topicFilter.data.id, msgId, rc);
Event* evsuback = new Event();
evsuback->setClientSendEvent(client, sSuback);
_gateway->getClientSendQue()->post(evsuback);
}
switch (topicFilter.data.id)
{
case 1:
/*
* ToDo: write here Predefined Topic 01 Procedures.
*/
break;
case 2:
/*
* ToDo: write here Predefined Topic 02 Procedures. so on
*/
break;
default:
break;
}
}
else
{
uint16_t topicId = 0;
MQTTGWPacket* subscribe = new MQTTGWPacket();
topic = client->getTopics()->getTopic(&topicFilter);
if (topic == 0)
{
if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL)
{
topic = client->getTopics()->add(&topicFilter);
topicId = topic->getTopicId();
subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId);
}
else if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT)
{
char topic[3];
topic[0] = topicFilter.data.short_name[0];
topic[1] = topicFilter.data.short_name[1];
topic[2] = 0;
topicId = topicFilter.data.id;
subscribe->setSUBSCRIBE(topic, (uint8_t)qos, (uint16_t)msgId);
}
}
else
{
topicId = topic->getTopicId();
subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId);
}
if ( msgId > 0 )
{
client->setWaitedSubTopicId(msgId, topicId, topicFilter.type);
}
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, subscribe);
_gateway->getBrokerSendQue()->post(ev1);
return;
}
}
else
{
/*-- Invalid TopicIdType --*/
if (msgId)
{
MQTTSNPacket* sSuback = new MQTTSNPacket();
sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_REJECTED_INVALID_TOPIC_ID);
Event* evsuback = new Event();
evsuback->setClientSendEvent(client, sSuback);
_gateway->getClientSendQue()->post(evsuback);
}
}
}
void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet)
{
uint16_t msgId;
MQTTSN_topicid topicFilter;
if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 )
{ {
return; return;
} }
if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED ) if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED )
{ {
/* topic = client->getTopics()->getTopicById(&topicFilter);
* ToDo: procedures for Predefined Topic if ( topic )
*/ {
topicId = topic->getTopicId();
subscribe = new MQTTGWPacket();
subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId);
}
else
{
goto RespExit;
}
}
else if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL)
{
topic = client->getTopics()->getTopicByName(&topicFilter);
if ( topic == 0 )
{
topic = client->getTopics()->add(&topicFilter);
if ( topic == 0 )
{
WRITELOG("%s Client(%s) can't add the Topic.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return;
}
}
topicId = topic->getTopicId();
subscribe = new MQTTGWPacket();
subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId);
}
else //MQTTSN_TOPIC_TYPE_SHORT
{
char topicstr[3];
topicstr[0] = topicFilter.data.short_name[0];
topicstr[1] = topicFilter.data.short_name[1];
topicstr[2] = 0;
topicId = 0;
subscribe = new MQTTGWPacket();
subscribe->setSUBSCRIBE(topicstr, (uint8_t)qos, (uint16_t)msgId);
}
client->setWaitedSubTopicId(msgId, topicId, topicFilter.type);
ev1 = new Event();
ev1->setBrokerSendEvent(client, subscribe);
_gateway->getBrokerSendQue()->post(ev1);
return;
RespExit:
MQTTSNPacket* sSuback = new MQTTSNPacket();
sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_NOT_SUPPORTED);
evsuback = new Event();
evsuback->setClientSendEvent(client, sSuback);
_gateway->getClientSendQue()->post(evsuback);
}
void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet)
{
uint16_t msgId;
MQTTSN_topicid topicFilter;
MQTTGWPacket* unsubscribe = 0;;
if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 )
{
return; return;
} }
Topic* topic = client->getTopics()->getTopic(&topicFilter); if ( msgId == 0 )
MQTTGWPacket* unsubscribe = new MQTTGWPacket(); {
return;
}
if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL) Topic* topic = client->getTopics()->getTopicById(&topicFilter);
if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT)
{
char shortTopic[3];
shortTopic[0] = topicFilter.data.short_name[0];
shortTopic[1] = topicFilter.data.short_name[1];
shortTopic[2] = 0;
unsubscribe = new MQTTGWPacket();
unsubscribe->setUNSUBSCRIBE(shortTopic, msgId);
}
else
{ {
if ( topic == 0 ) if ( topic == 0 )
{
if (msgId)
{ {
MQTTSNPacket* sUnsuback = new MQTTSNPacket(); MQTTSNPacket* sUnsuback = new MQTTSNPacket();
sUnsuback->setUNSUBACK(msgId); sUnsuback->setUNSUBACK(msgId);
Event* evsuback = new Event(); Event* evsuback = new Event();
evsuback->setClientSendEvent(client, sUnsuback); evsuback->setClientSendEvent(client, sUnsuback);
_gateway->getClientSendQue()->post(evsuback); _gateway->getClientSendQue()->post(evsuback);
}
delete unsubscribe;
return; return;
} }
else else
{ {
unsubscribe = new MQTTGWPacket();
unsubscribe->setUNSUBSCRIBE(topic->getTopicName()->c_str(), msgId); unsubscribe->setUNSUBSCRIBE(topic->getTopicName()->c_str(), msgId);
} }
} }
else if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT)
{
char shortTopic[3];
shortTopic[0] = topicFilter.data.short_name[0];
shortTopic[1] = topicFilter.data.short_name[1];
shortTopic[2] = 0;
unsubscribe->setUNSUBSCRIBE(shortTopic, msgId);
}
else
{
delete unsubscribe;
return;
}
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, unsubscribe); ev1->setBrokerSendEvent(client, unsubscribe);

View File

@@ -17,6 +17,6 @@
#ifndef MQTTSNGWVERSION_H_IN_ #ifndef MQTTSNGWVERSION_H_IN_
#define MQTTSNGWVERSION_H_IN_ #define MQTTSNGWVERSION_H_IN_
#define PAHO_GATEWAY_VERSION "1.0.1" #define PAHO_GATEWAY_VERSION "1.1.0"
#endif /* MQTTSNGWVERSION_H_IN_ */ #endif /* MQTTSNGWVERSION_H_IN_ */

View File

@@ -13,7 +13,7 @@
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
#include "SensorNetwork.h" #include "SensorNetwork.h"
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
@@ -202,11 +202,38 @@ void Gateway::initialize(int argc, char** argv)
if (!_clientList.authorize(fileName.c_str())) if (!_clientList.authorize(fileName.c_str()))
{ {
throw Exception("Gateway::initialize: No client list defined by configuration."); throw Exception("Gateway::initialize: No client list defined by the configuration.");
} }
_params.clientListName = strdup(fileName.c_str()); _params.clientListName = strdup(fileName.c_str());
} }
} }
if (getParam("PredefinedTopic", param) == 0 )
{
if (!strcasecmp(param, "YES") )
{
if (getParam("PredefinedTopicFile", param) == 0)
{
fileName =*getConfigDirName() + string(param);
}
else
{
fileName = *getConfigDirName() + string(PREDEFINEDTOPIC_FILE);
}
if (!_clientList.setPredefinedTopics(fileName.c_str()))
{
throw Exception("Gateway::initialize: No PredefinedTopic file defined by the configuration..");
}
_params.predefinedTopicFileName = strdup(fileName.c_str());
}
else
{
_params.predefinedTopicFileName = 0;
}
}
fileName = *getConfigDirName() + *getConfigFileName(); fileName = *getConfigDirName() + *getConfigFileName();
_params.configName = strdup(fileName.c_str()); _params.configName = strdup(fileName.c_str());
} }
@@ -229,6 +256,10 @@ void Gateway::run(void)
} }
WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription());
WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure);
if ( _params.predefinedTopicFileName )
{
WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName);
}
WRITELOG(" RootCApath: %s\n", _params.rootCApath); WRITELOG(" RootCApath: %s\n", _params.rootCApath);
WRITELOG(" RootCAfile: %s\n", _params.rootCAfile); WRITELOG(" RootCAfile: %s\n", _params.rootCAfile);
WRITELOG(" CertKey: %s\n", _params.certKey); WRITELOG(" CertKey: %s\n", _params.certKey);

View File

@@ -72,10 +72,10 @@ namespace MQTTSNGW
/*===================================== /*=====================================
Predefined TopicId for OTA Predefined TopicId for OTA
====================================*/ ====================================*/
#define OTA_CLIENTS //#define OTA_CLIENTS
#define PREDEFINEDID_OTA_REQ (0x0ff0) //#define PREDEFINEDID_OTA_REQ (0x0ff0)
#define PREDEFINEDID_OTA_READY (0x0ff1) //#define PREDEFINEDID_OTA_READY (0x0ff1)
#define PREDEFINEDID_OTA_NO_CLIENT (0x0ff2) //#define PREDEFINEDID_OTA_NO_CLIENT (0x0ff2)
/*===================================== /*=====================================
Class Event Class Event
@@ -160,6 +160,7 @@ typedef struct
char* rootCAfile; char* rootCAfile;
char* certKey; char* certKey;
char* privateKey; char* privateKey;
char* predefinedTopicFileName;
}GatewayParams; }GatewayParams;
/*===================================== /*=====================================

View File

@@ -87,27 +87,29 @@ void TestProcess::run(void)
printf("Timer Test completed\n\n"); printf("Timer Test completed\n\n");
/* Test Que */ /* Test Que */
printf("Test Que ");
TestQue* tque = new TestQue(); TestQue* tque = new TestQue();
tque->test(); tque->test();
delete tque; delete tque;
/* Test Tree23 */ /* Test Tree23 */
printf("Test Tree23 ");
TestTree23* tree23 = new TestTree23(); TestTree23* tree23 = new TestTree23();
tree23->test(); tree23->test();
delete tree23; delete tree23;
/* Test TopicTable */ /* Test TopicTable */
printf("Test Topic ");
TestTopics* testTopic = new TestTopics(); TestTopics* testTopic = new TestTopics();
testTopic->test(); testTopic->test();
delete testTopic; delete testTopic;
/* Test TopicIdMap */ /* Test TopicIdMap */
printf("Test TopicIdMap ");
TestTopicIdMap* testMap = new TestTopicIdMap(); TestTopicIdMap* testMap = new TestTopicIdMap();
testMap->test(); testMap->test();
delete testMap; delete testMap;
/* Test EventQue */ /* Test EventQue */
printf("Test EventQue "); printf("Test EventQue ");
Client* client = new Client(); Client* client = new Client();

View File

@@ -35,7 +35,6 @@ void TestQue::test(void)
int* v = 0; int* v = 0;
int i = 0; int i = 0;
printf("Test Que ");
for ( i = 0; i < 10; i++ ) for ( i = 0; i < 10; i++ )
{ {
v = new int(i); v = new int(i);

View File

@@ -31,55 +31,70 @@ TestTopicIdMap::~TestTopicIdMap()
delete _map; delete _map;
} }
bool TestTopicIdMap::testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTypes type)
{
TopicIdMapelement* elm = _map->getElement((uint16_t)msgid );
if ( elm )
{
//printf("msgid=%d id=%d type=%d\n", msgid, elm->getTopicId(), elm->getTopicType());
return elm->getTopicId() == id && elm->getTopicType() == type;
}
//printf("msgid=%d\n", msgid);
return false;
}
#define MAXID 30 #define MAXID 30
void TestTopicIdMap::test(void) void TestTopicIdMap::test(void)
{ {
uint16_t id[MAXID]; uint16_t id[MAXID];
printf("Test TopicIdMat ");
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < MAXID; i++ )
{ {
id[i] = i + 1; id[i] = i + 1;
}
for ( int i = 0; i < MAXID; i++ )
{
_map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL); _map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL);
} }
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{ {
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_SHORT; assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
uint16_t topicId = _map->getTopicId((uint16_t)i, &type);
//printf("TopicId=%d msgId=%d type=%d\n", topicId, i, type);
assert((i <= MAX_INFLIGHTMESSAGES * 2 + 1 && topicId == i) || (i > MAX_INFLIGHTMESSAGES * 2 + 1 && topicId == 0));
} }
//printf("\n"); for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
}
for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
}
for ( int i = 0; i < 5; i++ ) for ( int i = 0; i < 5; i++ )
{ {
_map->erase(i); _map->erase(id[i]);
} }
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < 5; i++ )
{ {
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_SHORT; assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
uint16_t topicId = _map->getTopicId((uint16_t)i, &type);
//printf("TopicId=%d msgId=%d type=%d\n", topicId, i, type);
assert((i < 5 && topicId == 0) || (i >= 5 && topicId != 0) || (i > MAX_INFLIGHTMESSAGES * 2 + 1 && topicId == 0) );
} }
for ( int i = 5; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
}
for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
}
_map->clear(); _map->clear();
//printf("\n");
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < MAXID; i++ )
{ {
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_SHORT; assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
uint16_t topicId = _map->getTopicId((uint16_t)i, &type);
//printf("TopicId=%d msgId=%d type=%d\n", topicId, i, type);
assert( topicId == 0 );
} }
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < MAXID; i++ )
@@ -87,38 +102,91 @@ void TestTopicIdMap::test(void)
_map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT); _map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT);
} }
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{ {
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_NORMAL; assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
uint16_t topicId = _map->getTopicId((uint16_t)i, &type);
//printf("TopicId=%d msgId=%d type=%d\n", topicId, i, type);
assert((i <= MAX_INFLIGHTMESSAGES * 2 + 1 && topicId == i) || (i > MAX_INFLIGHTMESSAGES * 2 + 1 && topicId == 0));
} }
//printf("\n"); for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
}
for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL));
}
for ( int i = 0; i < 5; i++ ) for ( int i = 0; i < 5; i++ )
{ {
_map->erase(i); _map->erase(id[i]);
} }
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < 5; i++ )
{ {
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_NORMAL; assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
uint16_t topicId = _map->getTopicId((uint16_t)i, &type);
//printf("TopicId=%d msgId=%d type=%d\n", topicId, i, type);
assert((i < 5 && topicId == 0) || (i >= 5 && topicId != 0) || (i > MAX_INFLIGHTMESSAGES * 2 + 1 && topicId == 0) );
} }
for ( int i = 5; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
}
for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
}
_map->clear(); _map->clear();
//printf("\n");
for ( int i = 0; i < MAXID; i++ ) for ( int i = 0; i < MAXID; i++ )
{ {
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_NORMAL; assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
uint16_t topicId = _map->getTopicId((uint16_t)i, &type); }
//printf("TopicId=%d msgId=%d type=%d\n", topicId, i, type);
assert( topicId == 0 ); for ( int i = 0; i < MAXID; i++ )
{
_map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED);
}
for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
}
for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
}
for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT));
}
for ( int i = 0; i < 5; i++ )
{
_map->erase(id[i]);
}
for ( int i = 0; i < 5; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
}
for ( int i = 5; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ )
{
assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
}
for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
}
_map->clear();
for ( int i = 0; i < MAXID; i++ )
{
assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED));
} }
printf("[ OK ]\n"); printf("[ OK ]\n");
} }

View File

@@ -24,6 +24,7 @@ public:
TestTopicIdMap(); TestTopicIdMap();
~TestTopicIdMap(); ~TestTopicIdMap();
void test(void); void test(void);
bool testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTypes type);
private: private:
TopicIdMap* _map; TopicIdMap* _map;

View File

@@ -38,7 +38,7 @@ bool testIsMatch(const char* topicFilter, const char* topicName)
string* filter = new string(topicFilter); string* filter = new string(topicFilter);
string* name = new string(topicName); string* name = new string(topicName);
Topic topic(filter); Topic topic(filter, MQTTSN_TOPIC_TYPE_NORMAL);
bool isMatch = topic.isMatch(name); bool isMatch = topic.isMatch(name);
delete name; delete name;
@@ -46,38 +46,82 @@ bool testIsMatch(const char* topicFilter, const char* topicName)
return isMatch; return isMatch;
} }
bool testGetTopic(const char* topicName, const char* searchedTopicName) bool testGetTopicByName(const char* topicName, const char* searchedTopicName)
{ {
Topics topics; Topics topics;
string name(topicName); MQTTSN_topicid topicid, serchId;
MQTTSN_topicid topicid;
topicid.type = MQTTSN_TOPIC_TYPE_NORMAL; topicid.type = MQTTSN_TOPIC_TYPE_NORMAL;
topicid.data.long_.len = strlen(searchedTopicName); topicid.data.long_.len = strlen(topicName);
topicid.data.long_.name = const_cast<char*>(searchedTopicName); topicid.data.long_.name = const_cast<char*>(topicName);
topics.add(&name); topics.add(&topicid);
return topics.getTopic(&topicid) != 0; serchId.type = MQTTSN_TOPIC_TYPE_NORMAL;
serchId.data.long_.len = strlen(searchedTopicName);
serchId.data.long_.name = const_cast<char*>(searchedTopicName);
return topics.getTopicByName(&serchId) != 0;
} }
bool testGetTopicId(const char* topicName, const char* searchedTopicName) bool testGetTopicById(const char* topicName, const char* searchedTopicName)
{ {
Topics topics; Topics topics;
string name(topicName); MQTTSN_topicid topicid, stopicid;
MQTTSN_topicid topicid;
topicid.type = MQTTSN_TOPIC_TYPE_NORMAL; topicid.type = MQTTSN_TOPIC_TYPE_NORMAL;
topicid.data.long_.len = strlen(topicName);
topicid.data.long_.name = const_cast<char*>(topicName);
stopicid.type = MQTTSN_TOPIC_TYPE_NORMAL;
stopicid.data.long_.len = strlen(searchedTopicName);
stopicid.data.long_.name = const_cast<char*>(searchedTopicName);
Topic* tp = topics.add(&topicid);
Topic*stp = topics.add(&stopicid);
topicid.data.id = tp->getTopicId();
stopicid.data.id = stp->getTopicId();
stp = topics.getTopicById(&stopicid);
return stp->getTopicId() == tp->getTopicId();
}
bool testGetPredefinedTopicByName(const char* topicName, const uint16_t id, const char* searchedTopicName)
{
Topics topics;
MQTTSN_topicid topicid;
topics.add(topicName, id);
topicid.type = MQTTSN_TOPIC_TYPE_PREDEFINED;
topicid.data.long_.len = strlen(searchedTopicName); topicid.data.long_.len = strlen(searchedTopicName);
topicid.data.long_.name = const_cast<char*>(searchedTopicName); topicid.data.long_.name = const_cast<char*>(searchedTopicName);
topics.add(&name); return topics.getTopicByName(&topicid) != 0;
}
return topics.getTopicId(&topicid) != 0; bool testGetPredefinedTopicById(const char* topicName, const uint16_t id, uint16_t sid)
{
Topics topics;
MQTTSN_topicid topicid;
Topic* t = topics.add(topicName, id);
topicid.type = MQTTSN_TOPIC_TYPE_PREDEFINED;
topicid.data.id = sid;
Topic* tp = topics.getTopicById(&topicid);
if ( tp )
{
return tp->getTopicId() == id && strcmp(t->getTopicName()->c_str(), topicName) == 0;
}
else
{
return false;
}
} }
void TestTopics::test(void) void TestTopics::test(void)
{ {
printf("Test Topics ");
const int TOPIC_COUNT = 13; const int TOPIC_COUNT = 13;
MQTTSN_topicid topic[TOPIC_COUNT]; MQTTSN_topicid topic[TOPIC_COUNT];
@@ -116,6 +160,18 @@ void TestTopics::test(void)
topic[12].data.long_.len = strlen(tp[12]); topic[12].data.long_.len = strlen(tp[12]);
topic[12].data.long_.name = tp[12]; topic[12].data.long_.name = tp[12];
/* Test EraseNorma() */
for ( int i = 0; i < TOPIC_COUNT; i++ )
{
MQTTSN_topicid pos = topic[i];
Topic* t = _topics->add(&pos);
//printf("Topic=%s ID=%d\n", t->getTopicName()->c_str(), t->getTopicId());
assert(t !=0);
}
_topics->eraseNormal();
assert(_topics->getCount() == 0);
/* Add Topic to Topics */ /* Add Topic to Topics */
for ( int i = 0; i < TOPIC_COUNT; i++ ) for ( int i = 0; i < TOPIC_COUNT; i++ )
{ {
@@ -129,25 +185,29 @@ void TestTopics::test(void)
{ {
string str = "Test/"; string str = "Test/";
str += 0x30 + i; str += 0x30 + i;
Topic* t = _topics->add(&str); Topic* t = _topics->add(str.c_str());
//printf("Topic=%s ID=%d\n", t->getTopicName()->c_str(), t->getTopicId()); //printf("Topic=%s ID=%d\n", t->getTopicName()->c_str(), t->getTopicId());
assert(t !=0); assert(t !=0);
} }
/* Get Topic by MQTTSN_topicid */ /* Get Topic by MQTTSN_topicid by Name*/
for ( int i = 0; i < TOPIC_COUNT; i++ ) for ( int i = 0; i < TOPIC_COUNT; i++ )
{ {
Topic* t = _topics->getTopic(&topic[i]); Topic* t = _topics->getTopicByName(&topic[i]);
//printf("Topic=%s ID=%d ID=%d\n", t->getTopicName()->c_str(), t->getTopicId(),_topics->getTopicId(&topic[i])); //printf("Topic=%s ID=%d\n", t->getTopicName()->c_str(), t->getTopicId());
assert(t->getTopicId() == i + 1); assert(strcmp(t->getTopicName()->c_str(), topic[i].data.long_.name) == 0 );
} }
/* Get TopicId by MQTTSN_topicid */ /* Get Topic by MQTTSN_topicid by ID*/
for ( int i = 0; i < TOPIC_COUNT; i++ ) for ( int i = 0; i < TOPIC_COUNT; i++ )
{ {
uint16_t id = _topics->getTopicId(&topic[i]); Topic* t = _topics->getTopicByName(&topic[i]);
//printf("ID=%d \n", id); MQTTSN_topicid stpid;
assert(id == i + 1); stpid.type = MQTTSN_TOPIC_TYPE_NORMAL;
stpid.data.id =t->getTopicId();
Topic* st = _topics->getTopicById(&stpid);
//printf("Topic=%s ID=%d ID=%d\n", t->getTopicName()->c_str(), t->getTopicId(), st->getTopicId());
assert(t->getTopicId() == st->getTopicId() );
} }
/* Test Wildcard */ /* Test Wildcard */
@@ -286,13 +346,20 @@ void TestTopics::test(void)
assert(testIsMatch("/+", "/finance")); assert(testIsMatch("/+", "/finance"));
assert(!testIsMatch("+", "/finance")); assert(!testIsMatch("+", "/finance"));
assert(testGetTopicId("mytopic", "mytopic")); assert(testGetTopicById("mytopic", "mytopic"));
assert(!testGetTopicId("mytopic", "mytop")); assert(!testGetTopicById("mytopic", "mytop"));
assert(!testGetTopicId("mytopic", "mytopiclong")); assert(!testGetTopicById("mytopic", "mytopiclong"));
assert(testGetTopic("mytopic", "mytopic")); assert(testGetTopicByName("mytopic", "mytopic"));
assert(!testGetTopic("mytopic", "mytop")); assert(!testGetTopicByName("mytopic", "mytop"));
assert(!testGetTopic("mytopic", "mytopiclong")); assert(!testGetTopicByName("mytopic", "mytopiclong"));
assert(testGetPredefinedTopicByName("mypretopic", 1, "mypretopic"));
assert(!testGetPredefinedTopicByName("mypretopic", 1, "mypretop"));
assert(!testGetPredefinedTopicByName("mypretopic", 1, "mypretopiclong"));
assert(testGetPredefinedTopicById("mypretopic2", 2, 2));
assert(!testGetPredefinedTopicById("mypretopic2", 2, 1));
printf("[ OK ]\n"); printf("[ OK ]\n");
} }

View File

@@ -33,7 +33,6 @@ TestTree23::~TestTree23()
void TestTree23::test(void) void TestTree23::test(void)
{ {
printf("Test Tree23 ");
int N = 100; int N = 100;
Key* r1[100]; Key* r1[100];

View File

@@ -213,8 +213,10 @@ int readMQTTSNString(MQTTSNString* MQTTSNString, unsigned char** pptr, unsigned
*pptr += MQTTSNString->lenstring.len; *pptr += MQTTSNString->lenstring.len;
} }
else else
{
MQTTSNString->lenstring.data = NULL; MQTTSNString->lenstring.data = NULL;
MQTTSNString->cstring = NULL; MQTTSNString->cstring = NULL;
}
rc = 1; rc = 1;
FUNC_EXIT_RC(rc); FUNC_EXIT_RC(rc);
return rc; return rc;