op.24 想回到那年的時空
妳說妳想回到原來的時空,但無奈現在的妳已經跟以前不同了
已經不能用與我一樣地方式穿越了......
但是沒關係,為了妳我可以再找出方法的!
再度進入連假魔王啦~天啊依舊我還是沒回家呢XD
今天就來一點簡單的部分,來嘗試看看把 Flutter 跟 Broker 運行一起看看吧。
首先需要打開 pubspec.yaml,將 mqtt_client 的套件安裝到專案裡,所以需要在 pubspec.yaml 裡新增程式碼。
dependencies:
mqtt_client: ^8.0.0
然後將視線移到螢幕右上角有個 Pub get 按下去,就可以將套件安裝進去。
(備註:其他套件基本上也是相同的方式)
稍微等個幾秒鐘,下方出現這段提示,表示安裝完成。
接著回到 main.dart 之中,在上方 import 區域加入以下的 import
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
到這邊就完成對 mqtt_client 的安裝啦。
接下來進入到 mqtt_Client 的連線,會需要有以下幾項的參數需要設定,所以我們先宣告以下東西。
const url = '127.0.0.1'; //主機位置
const port = 1883; //MQTT port
const clientID = 'Client01'; //Mqtt Client
const username = 'Client01'; //Mqtt username
const password = 'password'; //Mqtt password
final client = MqttServerClient(url, clientID);
接下來要和 C# 一樣寫連線的 Function
Future<MqttServerClient> connect() async {
client.port = port; //對應 port
client.setProtocolV311(); //設置 mqtt 的版本
client.logging(on: true);
await client.connect(username, password);
if (client.connectionStatus.state == MqttConnectionState.connected) {
print('client connected');
} else {
print(
'ERROR client connection failed - disconnecting, state is ${client.connectionStatus.state}');
client.disconnect();
}
//以下是訂閱主題並監聽的該主題的訊息
client.subscribe("Test", MqttQos.atLeastOnce); //這裡訂閱了 Test 主題。
//下段程式碼為監聽的部分
client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final MqttPublishMessage message = c[0].payload;
final payload = MqttPublishPayload.bytesToStringAsString(message.payload.message);
print('${c[0].topic}:${payload}');
});
}
這裡用到一個比較特殊的 Function,屬於 Future 型的,使用這個目的為的便是使用異步的方式來執行,讓 mqtt 去慢慢處裡,使用 Future 代表說會在未來的某個時間返回結果。
然後在 main 裡塞入剛剛寫的 connect()。
void main() {
//runApp();
connect();
}
到這裡我們運行之前寫的 Broker 與 MQTTLens 來測試,MQTTLens 是一款線上的 mqtt client 端,可由瀏覽器執行 (連結)
成功運行應該可以看到兩個 Client 連線了
我們從 MQTTLens 發布訊息看看。
此時的 Andorid Studio的 Console 視窗會出現剛剛從 MQTTLens 發的訊息。
到這邊我們就完成了訂閱的部分,那麼看起來現在只剩下從 App 這裡發送的功能了。
那我們先在頁面上拉出一個輸入框與按鈕,在 Widgets build 裡,我們先用到昨天有使用到的 Scaffold ,先在程式的最上方加入 AppBar,並且給予一個 title。
return Scaffold(
appBar: AppBar(
title: Text("MQTT example"),
),
記得最重要的一句話, Flutter 就像樂高一樣,我們剛剛已經堆出前面的頁面,現在要來繼續堆剩下的頁面,在 body 裡塞入一個 Center 容器,裡面我們放入一個直立的 Column (垂直布局)。
body: Center(
child: Column(
),
),
接著要在這 挖好(佈局) 的洞放入 輸入框 與按鈕,值得注意的是,輸入框會需要將輸入的內容抓出來,所以會需要在Wigets build 之前,宣告一個物件來儲存內容;
final TextEditingController txf1 = new TextEditingController();
然後再將 輸入框 放入 Column 裡。
TextField(
controller: txf1,
decoration: InputDecoration(hintText: 'Input...'),
),
按鈕算是一個互動元件,除了顯示文字外,按下去後要有對應的事件產生,所以要給予一個 onPressed,後面會對應到自己寫的 Function 。
RaisedButton(
child: Text('Print'),
onPressed: btnEvent,
)
此時 Widget build 應該會長這樣。
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("MQTT example"),
),
body: Center(
child: Column(
children: <Widget>[
TextField(
controller: txf1,
decoration: InputDecoration(hintText: 'Input...'),
),
RaisedButton(
child: Text('Print'),
onPressed: btnEvent,
)
],
),
),
);
再來,剛剛說到按下按鈕的事件,我們接 Widget build 後面寫,簡單地介紹下面程式碼的功用,將內容從輸入框中提取出來,然後透過 mqtt publish 發送出去。
void btnEvent(){
const pubTopic = 'testpub';
final builder = MqttClientPayloadBuilder();
builder.addString(txf1.text);
client.publishMessage(pubTopic, MqttQos.atLeastOnce, builder.payload);
}
今天的完整程式碼如下:
import 'package:flutter/material.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
const url = '127.0.0.1';
const port = 1883;
const clientID = 'Client01';
const username = 'Client01';
const password = 'password';
final client = MqttServerClient(url, clientID);
void main() {
runApp(MyApp());
connect();
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final TextEditingController txf1 = new TextEditingController();
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("MQTT example"),
),
body: Center(
child: Column(
children: <Widget>[
TextField(
controller: txf1,
decoration: InputDecoration(hintText: 'Input...'),
),
RaisedButton(
child: Text('Print'),
onPressed: btnEvent,
)
],
),
),
);
}
void btnEvent(){
print(txf1.text);
const pubTopic = 'testpub';
final builder = MqttClientPayloadBuilder();
builder.addString(txf1.text);
client.publishMessage(pubTopic, MqttQos.atLeastOnce, builder.payload);
}
}
Future<MqttServerClient> connect() async {
client.port = port;
client.setProtocolV311();
client.logging(on: true);
await client.connect(username, password);
if (client.connectionStatus.state == MqttConnectionState.connected) {
print('client connected');
} else {
print(
'client connection failed - disconnecting, state is ${client.connectionStatus.state}');
client.disconnect();
}
client.subscribe("Test", MqttQos.atLeastOnce);
client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final MqttPublishMessage message = c[0].payload;
final payload = MqttPublishPayload.bytesToStringAsString(message.payload.message);
print('${c[0].topic}:${payload}');
});
}
當成功執行時,畫面會出現一個輸入框與按鈕
輸入文字後,Broker會接收到剛剛按下 Print 的內容。
好啦,今天的部分就到此結束啦,也恭喜各位把 MQTT 成功地帶到 Flutter 上了,明天沒意外我們來玩玩資料視覺化,讓冷冰冰的數據變成好看一點的圖表吧。