aws / aws-iot-device-sdk-js

SDK for connecting to AWS IoT from a device using JavaScript/Node.js
Apache License 2.0
964 stars 384 forks source link

ACK from AWS-IoT device gateway to Nodejs server for each message #144

Closed JasonWolfson closed 7 years ago

JasonWolfson commented 7 years ago

I have a device(client), that has subscribed to a topic "xyz". I am publishing a message using awsIot.device class on the topic from NodeJs server with QoS:1. How can I get the ACK(acknowledgement) from the client to the Node Js server for that message when it reaches the client? Is it possible? Do I have to write any rules or any specific callback functions?

fengsongAWS commented 7 years ago

Hi @AirCycler , Thanks for your interest in aws-iot-device-sdk-js. The puback is handled by mqtt.js underlayer e.g. https://github.com/mqttjs/MQTT.js/blob/master/lib/client.js#L932 The SDK does not handle the ack packet.

JasonWolfson commented 7 years ago

Would you please suggest me then what do you want me to do to get the "puback" ? I mean a hint to write the code. I am new to this stuff.

fengsongAWS commented 7 years ago

Hi @AirCycler , Could you elaborate your use case? Do you want the pub ack from client or server side?

JasonWolfson commented 7 years ago

Hi, I am publishing a message from Nodejs server using AWSIoT.device class to ESP8266 wifi module which is a client, coded in arduino. Now I would like to get the PUBACK from ESP module to Nodejs server when it is received. I am using websockets and mqtt layers in ESP8266 by providing AWS IoT details. So, I need confirmation from the client. I will have a lot of clients and I am using unique sub and pub topics for each ESP module. What do you suggest in this case?

liuszeng commented 7 years ago

Hi @AirCycler ,

There are several concepts that need to be clarified here before we go down the route of addressing the use case:

  1. AWS IoT provides functionality to act as an MQTT server that accepts connected clients and routes messages published from one client to another.
  2. Client connects to AWS IoT and publishes messages to dedicated topics.
  3. Client connects to AWS IoT and subscribes to dedicated topics to be able to receive messages published by some one else.
  4. QoS 1 (at least once) applies for publishes happen from server (AWS IoT) to client and from client to server (AWS IoT). When client publishes to server (AWS IoT) with QoS1, the client should expect to receive PUBACK from the server, indicating that the server received the request and will process it for sure. When server (AWS IoT) publishes to client with QoS1, the client should reply with PUBACK, telling the server (AWS IoT) that the client has got the delivery.
  5. QoS level for publishes from server (AWS IoT) to client is negotiated via client SUBSCRIBE request. If a client asks for a subscription to a topic with QoS1, the server (AWS IoT) will send PUBLISH at QoS1 (expecting a PUBACK from the client) upon any new incoming messages to that topic.

With all the above being said, I assume you mean you have 2 clients connected to AWS IoT and have one client (let's call it publisher) publishes to topic "xyz" and another (let's call it subscriber) subscribed to topics "xyz" so that publisher can send messages to subscriber via AWS IoT MQTT message routing. There is no real "NodeJS server" but a client as a publisher. Can you confirm my assumption?

The problem you are trying to address here is, you want the publisher being notified when the subscriber actually gets the published message, i.e., guaranteed delivery, which is very similar to QoS2 and is not supported by AWS IoT for now.

One thing you can do is have the subscriber publish a message to another topic subscribed by the publisher upon the reception of the message from the publisher. If the publisher receives notification from the subscriber, it guarantees that the subscriber received the published message.

Thanks, Liusu

JasonWolfson commented 7 years ago

Hi,

Your assumption is right. I have two clients. I can do like you said, but is it an efficient way to do sending confirmation like that?

liuszeng commented 7 years ago

Hi @AirCycler ,

Thanks for your confirmation.

What you really need here is the support of QoS2 from MQTT spec (section 4.3.3 QoS 2: Exactly once delivery): http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

To get similar outcome, one possible work-around is to use redundant topic/subscription/publish to have the subscriber notify the publisher about the reception.

Thanks, Liusu

JasonWolfson commented 7 years ago

Hi, I should receive the ACK with in certain time interval, if not I don't want the message in queue anymore. Is there any possible way to get the ACK from AWIoT server if the case is QOS1 only if it supports?

If there is nothing of a better solution, I will go for redundancy solution then.

Would Life cycle Events help in this case?

Thanks, Anusha

liuszeng commented 7 years ago

Hi @AirCycler ,

When the client does a QoS1 publish to the server, the server will reply with a PUBACK. In Node.js SDK, specifically, the PUBACK tracing is provided by the underneath MQTT.js module. On a QoS1 publish, the specified callback will be invoke upon the reception of a PUBACK. Details can be found in the MQTT.js source: https://github.com/mqttjs/MQTT.js/blob/master/lib/client.js#L392 https://github.com/mqttjs/MQTT.js/blob/master/lib/client.js#L935 https://github.com/mqttjs/MQTT.js/blob/master/lib/store.js#L77

But, again, it's the client who made the QoS1 publish request that would receive the PUBACK from server. There is no guaranteed delivery to all the subscribers. The publisher knows nothing about whether the subscribers received the published message.

As for life cycle event, it is emitted when the request made it to the AWS IoT server. It still does not guarantee that the publish request gets delivered to all the subscriber by the server. More details can be found here: http://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html

Thanks, Liusu

JasonWolfson commented 7 years ago

Seems like I am left with redundancy option only. Thank you so much for your help.