Reputation: 363
I'm building a Flutter Embedded application that uses MQTT to communicate between processes. Currently, I have a repository that subscribes to specific MQTT topics, but I want to improve it by triggering BLoC events when messages are received.
Current Approach: I’ve created a stream for each topic and have a method that listens to these streams, processes the data, and handles the topic. However, I don’t know the type of data in advance, and the logic feels a bit scattered. Here's what my current code looks like:
void _routeMessages() {
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>>? c) {
for (var message in c!) {
var payload = message.payload as MqttPublishMessage;
var data = MqttPublishPayload.bytesToStringAsString(payload.payload.message);
var topic = message.topic;
log('Data received on: $topic', name: 'mqttService | _routeMessages');
// HERE I WOULD LIKE TO TRIGGER A BLoC EVENT
// Call the appropriate BLoC event based on the topic, e.g., OnSku event
}
});
}
class A extends Bloc<Aevent, AState> {
on<OnSKU>((event, emit) {
// HERE PROCESS THE MQTT DATA
});
add(Subscribe({OnSKU: 'machine/backup/sku'}));
}
Goal: Instead of manually handling each topic and parsing the data, I would like to subscribe to a topic, provide a BLoC event for it, and automatically dispatch that event when a message is received for that topic. This way, the corresponding BLoC will handle the event, process the data, and update the state accordingly.
Future<void> _subscribeAndEmit(Subscribe event, Emitter<MachineDataState> emit) async {
if (_repository.isConnected()) {
// Subscribe to the topic and set its parser
_repository.subscribe(event.handler);
// Listen to the topic stream and emit states
await emit.forEach(
_repository.getStreamForTopic(event.handler),
onData: (parsedData) {
final topic = event.handler.topic;
final String? data = parsedData == 'null' ? null : parsedData;
if (topic == MqttTopics.get('backup', 'sku')) {
recievedData['sku'] = data;
emit(MachineDataReceived(data: recievedData));
}
if (topic == MqttTopics.get('backup', 'serial')) {
recievedData['serial'] = data;
emit(MachineDataReceived(data: recievedData));
}
if (topic == MqttTopics.get('backup', 'model')) {
recievedData['model'] = data;
emit(MachineDataReceived(data: recievedData));
}
if (topic == MqttTopics.get('backup', 'lifetime')) {
recievedData['lifetime'] = data;
emit(MachineDataReceived(data: recievedData));
}
return Initial();
},
onError: (error, stackTrace) {
return Error(error: error.toString());
},
);
} else {
emit(Error(error: Strings.errorNotConnected));
}
}
However, I would like to simplify this process and allow the repository to directly trigger a BLoC event when a message is received, instead of manually checking each topic and dispatching the event.
My Question: Is it possible to refactor the repository so that it triggers the appropriate BLoC event automatically when a message is received for a given topic? I’m looking for a cleaner and more elegant way to achieve this.
If this approach isn’t feasible, are there alternative solutions to achieve a similar result?
Upvotes: 0
Views: 20