The goal of this project is to understand how to "do this in flutter":
There is no error checking. My intent was to learn more like a conversation in which we learn how something works, but we stop short of studying so completely that we address all the "what ifs."
I'm assuming you have familiarity with Adafruit IO. You've subscribed and published to a feed. There is three pieces of information you need to have on hand when connecting to Adafruit.io:
io.adafruit.com
I put this info into a config/private.json file. Here's a screenshot of where the file goes within the project:
The contents of the file looks like:
{
"broker": "io.adafruit.com",
"username": "your username",
"key": "your AIO key"
}
The helper function _getBrokerAndKey()
read the file and turn it into something akin to a dictionary in Python:
Future<Map> _getBrokerAndKey() async {
// TODO: Check if private.json does not exist or expected key/values are not there.
String connect = await rootBundle.loadString('config/private.json');
return (json.decode(connect));
}
for example:
Map connectJson = await _getBrokerAndKey();
// TBD Test valid broker and key
log.info('in _login....broker : ${connectJson['broker']}');
WARNING: As I noted earlier, I do no error checking. The code assumes all is well with the keys and values.
The example code that comes with mqtt_client does not authenticate to the broker. I do this by adding:
final MqttConnectMessage connMess = MqttConnectMessage()
.authenticateAs(connectJson['username'], connectJson['key'])
authenticateAs to the MqttConnectMessage.
Passing updates requires a subscription to a feed. Check out the subscription code in mqtt_stream.dart.
This is where the code in Adafruit_feed.dart
comes in. It's all about the dance between the StreamController (the Dart library code that has a method to add data to a Stream), the Stream (the Dart library code that contains the data), and the StreamBuilder (the Flutter widget that updates the associated UI component).
Adding data happens when this line of code in mqtt_stream.dart runs:
AdafruitFeed.add(pt);
The _subscriptionData Widget in mqtt_ui_page.dart uses a StreamBuilder to associate the data coming in from the mqtt subscription with a UI element (in this case a Text widget) that displays.
Publishing is simpler than subscribing. I am hoping it is obvious what's going on if you go from the mqtt_ui_page where the publish button is and follow it into mqtt_stream.dart where the publish method is.
final Frame f = frames.skip(0).firstWhere((Frame f) =>
f.library.toLowerCase().contains(rec.loggerName.toLowerCase()) &&
f != frames.first);
in this line of code, we're sifting through the stack frames, pulling out the one that contains the name of the dart file where the log message came from. Once we have this glorious piece of info, we can send it to an output stream (in this case, our debug console):
print('${rec.level.name}: ${f.member} (${rec.loggerName}:${f.line}): ${rec.message}');
For example, I set up logging in the mqtt_stream.dart file:
log = Logger('mqtt_stream.dart');
(Sadly, i couldn't find a similar library to Python's to get the name of the file the code is currently running) Then in the code I have on line 167 of mqtt_stream.dart:
log.info('Adafruit client connected');
when the app runs past this line, the debug console prints out:
flutter: INFO: AppMqttTransactions._login (mqtt_stream.dart:167): Adafruit client connected
_Note: The mqtt_client library has its own logging that currently is turned off. This can be toggled on or off by:
client.logging(on: true);
which I put in the _login() function within mqtt_stream.dart.