shamblett / mqtt_client

A server and browser based MQTT client for dart
Other
547 stars 177 forks source link

Ping triggers client.update and brings the same message multiple times #539

Closed Gabones closed 1 month ago

Gabones commented 3 months ago

I have managed to implement an app with mqtt_client and connect it to AWS IoT Core. The mqtt connection is coded inside a flutter provider. I'm listening to published messages through a StreamBuilder widget, and everything seems to work fine. However, I have the following issue: every time the package pings the server, the StreamBuilder is triggered, and I receive the last message again in the app. I tried to find a solution for this but didn't manage to. Is there something I can do to prevent this, or is adding a unique ID to my messages the only way?

class BodyStream extends StatelessWidget {
  const BodyStream({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: context.watch<MqttService>().client.updates,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          var mqttReceiveMessages = snapshot.data;

          if (mqttReceiveMessages != null) {
            final recMess = mqttReceiveMessages[0].payload as MqttPublishMessage;

            context.read<MqttService>().messages.add(MqttPublishPayload.bytesToStringAsString(recMess.payload.message));
          }
        }

        return ListView.separated(
          padding: const EdgeInsets.all(8),
          itemCount: context.read<MqttService>().messages.length,
          itemBuilder: (BuildContext context, int index) {
            return Text(context.read<MqttService>().messages[index]);
          },
          separatorBuilder: (BuildContext context, int index) => const Divider(),
        );
      },
    );
  }
}
shamblett commented 3 months ago

I'm not a flutter user so I'm not sure what -

I have the following issue: every time the package pings the server, the StreamBuilder is triggered.  and I receive the last message again in the app...

means but I can tell you how the client works.

The client will not give you the last publish message received again once you have consumed it through its listener so I assume that flutter is somehow caching this. When you say 'pings the server' I assume you are using the keep alive functionality provided by the client, if so then I doubt its the sending of the ping request to the broker that's triggering anything, more like the ping response generated by the broker is doing this.

Each received publish message does have a unique message identifier, you can access it like this -

publishMessage. variableHeader.messageIdentifier

These are allocated by the broker so exact values wont be of use to you also they will be reused over time, however, the message identifier of a received publish message should be different to the last one received in all cases. You could use this to compare your last message with the previous one, if they are the same you can discard the message.