eclipse / paho.mqtt-sn.embedded-c

Paho C MQTT-SN gateway and libraries for embedded systems. Paho is an Eclipse IoT project.
https://eclipse.org/paho
Other
315 stars 178 forks source link

Register procedure #140

Closed urmydata closed 5 years ago

urmydata commented 5 years ago

Hi,

We are trying to establish communication between Arduino and the Paho MQTT-SN Gateway.

We want to send a topic id only after Arduino sends a REGISTER message. In other words, I want to send it to MQTTSN_TOPIC_TYPE_PREDEFINED after sending REGISTER message.

When processing the REGISTER message in the gateway code, set the type of topic id to MQTTSN_TOPIC_TYPE_NORMAL. ( In MQTTSNPublishHandler::handleRegister() )


void MQTTSNPublishHandler::handleRegister(Client* client, MQTTSNPacket* packet)
{
    uint16_t id;
    uint16_t msgId;
    MQTTSNString topicName  = MQTTSNString_initializer;;
    MQTTSN_topicid topicid;

    if ( client->isActive() || client->isAwake())
    {   
        if ( packet->getREGISTER(&id, &msgId, &topicName) == 0 )
        {
            return;
        }

        topicid.type = MQTTSN_TOPIC_TYPE_NORMAL;
        topicid.data.long_.len = topicName.lenstring.len;
        topicid.data.long_.name = topicName.lenstring.data;

        id = client->getTopics()->add(&topicid)->getTopicId();

        MQTTSNPacket* regAck = new MQTTSNPacket();
        regAck->setREGACK(id, msgId, MQTTSN_RC_ACCEPTED);
        Event* ev = new Event();
        ev->setClientSendEvent(client, regAck);
        _gateway->getClientSendQue()->post(ev);
    }
}

On the other hand, in SubscribeHandler, if type of topic is MQTTSN_TOPIC_TYPE_PREDEFINED, it calls topic :: getTopicById () which checks the type and id and returns the topic.


Topic* Topics::getTopicById(const MQTTSN_topicid* topicid)
{
    Topic* p = _first;

    while (p) 
    {   
        if ( p->_type == topicid->type && p->_topicId == topicid->data.id )
        {   
            return p;
        }   
        p = p->_next;
    }   
    return 0;
}

In this case, the message we sent after sending REGISTER message is not processed because it has a different type.

I'm wondering if we want to do something that violates the MQTT protocol, or no checking for type in topics :: getTopicById () is correct.

Is it possible to use MQTTSN_TOPIC_TYPE_PREDEFINED after the REGISTER, or only if the gateway and client both know topic and topic id in advance, is it possible to use MQTTSN_TOPIC_TYPE_PREDEFINED?

I looked up the document, but it was written as follows.

"Pre-defined" topic ids and "short" topic names are introduced, for which no registration is required. Predefined topic ids are also a two-byte long replacement of the topic name, their mapping to the topic names.

I still don't know which one is correct.

Thanks

ty4tw commented 5 years ago

Hi, Thank you for your information. Could you attach the log of Gateway? It helps me to understand the situation well.

urmydata commented 5 years ago

Hi,

Thank you for your response.

There is no error in that part of the log. We just wonder if what we think is contrary to the proctol or not.

To explain the exact situation, We wanted to send a topic as MQTTSN_TOPIC_TYPE_PREDEFINED after the REGISTER procedure without setting a topic in predefinedTopic.conf.

We did this because we thought that not only the predefinedTopic was recorded in the configuration file, but also the topic that was REGISTERED with a topic as MQTTSN_TOPIC_TYPE_NORMAL, and that later clients could use MQTTSN_TOPIC_TYPE_PREDEFINED when sending a topic to the gateway.

However, getTopicId () which mentioned earlier question checks type so that only topics read in predefinedTopic.conf can be used. That is, if it is not recorded in the configuration file, it couldn't be used as MQTTSN_TOPIC_TYPE_NORMAL. It means that topic which is registered as MQTTSN_TOPIC_TYPE_NORMAL at the time of REGISTER, It couldn't be used as MQTTSN_TOPIC_TYPE_PREDEFINED after REGISTER procedure.

If we delete the type checking part of below code, it works as we intended. It can support that topic which is registered as MQTTSN_TOPIC_TYPE_NORMAL can be used even if client sends topic as MQTTSN_TOPIC_TYPE_PREDEFINED after REGISTER procedure.


Topic* Topics::getTopicById(const MQTTSN_topicid* topicid)
{
    Topic* p = _first;

    while (p) 
    {   
        if ( p->_type == topicid->type && p->_topicId == topicid->data.id )
        {   
            return p;
        }   
        p = p->_next;
    }   
    return 0;
}

So I wanted to know that the predefined topic means only the topic recorded in the configuration file, or also includes the topic that was registered through REGISTER procedure as we thought. When we looked at the documentation, the meaning of the predefined topic was somewhat vague in my personal opinion. I still confused.

In conclusion, does our idea violate the MQTT-SN protocol or not? Is it ok to send topic as MQTTSN_TOPIC_TYPE_PREDEFINED after register procedure without recording topic in configuration file in terms of MQTT-SN protocol?

Thanks.

ty4tw commented 5 years ago

This Issue is better to discuss in the mqtt mailing list which is for a MQTT protocol related discussion. This repository is for a MQTT-SN implementation.

urmydata commented 5 years ago

Hi,

Oh, I mean MQTT-SN not MQTT. It was typo in last paragraph. I edited the last paragraph.

Thanks

urmydata commented 5 years ago

I think I didn't explain the situation very well.

According to MQTT-SN specification document, MQTT-SN supports REGISTER message. According to 5.4.10, REGISTER message can be used by a client to get a corresponding topic id from the topic name to gateway.

According to your MQTT-SN gateway implementation, when the gateway receives REGISTER message, the gateway registers newly-added topic name and retrieves new topic id for that topic name. And, the gateway deals with the newly-added topic name as "normal type" topic.

After this step, I can use a topic id instead of using topic string.

According to MQTT-SN document 5.4.15, SUBSCRIBE message has a flag related to topic ID type, and I can subscribe a topic by topic id or topic name string depending on which topic id type is set. (According to contents in 5.4.15, It says "TopicName or TopicId: contains topic name, topic id, or short topic name as indicated in the TopicIdType field")

When I tried to SUBSCRIBE message with topic id after REGISTER, it enters the following code in MQTTSNGWSubscribeHandler.cpp


if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED )
    {
        topic = client->getTopics()->getTopicById(&topicFilter);
        if ( topic )
        {
            topicId = topic->getTopicId();
            subscribe = new MQTTGWPacket();
            subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId);
        }
        else
        {
            goto RespExit;
        }
    }

Even though I register a new topic name and get new topic ID from the gateway during REGISTER, I failed to subscribe a topic with id. The reason why fail to subscribe is the below code could not find the topic ID and it returns 0.


topic = client->getTopics()->getTopicById(&topicFilter);

Because of this reason, all topic names which are registered through REGISTER cannot be used a retrieved topic ID. So, I think you need to change the code one of the two methods. 1) Skip checking the topic type on getTopicById function or 2) Set topic type to MQTTSN_TOPIC_TYPE_PREDEFINED when the topic name is registered through REGISTER message.

Please check this suggestion.

ty4tw commented 5 years ago

Hi urmydata,

Question is that Can a TopicName have two TopicIdType isn't it ? Answer is no.

urmydata commented 5 years ago

Hi,

No, my question is

"Can I use a topic id which is retrieved from REGISTER-REGACK procedure on SUBSCRIBE procedure?"

As you know, you have to use a retrieved topic ID on PUBLISH procedure, but SUBSCRIBE procedure provides some options to send a topic ID or name.

Thanks.

ty4tw commented 5 years ago

Hi,

You can't use it. The specification clearly mentions as below.

5.4.15 SUBSCRIBE Flags:

urmydata commented 5 years ago

Hi,

Ok, I got it.

Thanks.