|
@@ -1,7 +1,10 @@
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
|
|
|
import 'package:pm25go/scan.dart';
|
|
|
+import 'package:intl/intl.dart';
|
|
|
import 'bluetooth.dart';
|
|
|
+import 'dart:typed_data';
|
|
|
+import 'dart:convert';
|
|
|
|
|
|
void main() {
|
|
|
runApp(const MyApp());
|
|
@@ -72,22 +75,42 @@ class MyHomePage extends StatefulWidget {
|
|
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
|
|
var _statusText = "正在等待藍牙運接…\nWaiting for Bluetooth Connection...";
|
|
|
-
|
|
|
+ var _updateText = "無數據";
|
|
|
//Bluetooth Connection
|
|
|
- bool _btConnected = false;
|
|
|
DeviceSelectionWrapper connectedBluetoothDevice =
|
|
|
DeviceSelectionWrapper("", "", false, false);
|
|
|
-
|
|
|
+ bool _alreadyListening = false;
|
|
|
+ var incomingLine = "";
|
|
|
//Data update for display
|
|
|
int _pm01 = 0; //No recommended data found
|
|
|
int _pm25 = 0; //Healthy range: 35, recommend < 15
|
|
|
int _pm10 = 0; //Healthy range: 150, recommend < 50
|
|
|
+
|
|
|
+ Color GetPm25Color() {
|
|
|
+ if (_pm25 == 0) {
|
|
|
+ return Colors.grey;
|
|
|
+ } else if (_pm25 < 15) {
|
|
|
+ return Colors.green;
|
|
|
+ } else if (_pm25 < 35) {
|
|
|
+ return Colors.orangeAccent;
|
|
|
+ }
|
|
|
+ return Colors.red;
|
|
|
+ }
|
|
|
+
|
|
|
+ Color GetPm10Color() {
|
|
|
+ if (_pm10 == 0) {
|
|
|
+ return Colors.grey;
|
|
|
+ } else if (_pm10 < 50) {
|
|
|
+ return Colors.green;
|
|
|
+ } else if (_pm10 < 150) {
|
|
|
+ return Colors.orangeAccent;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Colors.red;
|
|
|
+ }
|
|
|
+
|
|
|
void _toggleBluetooth() async {
|
|
|
- // This call to setState tells the Flutter framework that something has
|
|
|
- // changed in this State, which causes it to rerun the build method below
|
|
|
- // so that the display can reflect the updated values. If we changed
|
|
|
- // _counter without calling setState(), then the build method would not be
|
|
|
- // called again, and so nothing would appear to happen.
|
|
|
+ //If the connection has already been established, stop the previous connection first
|
|
|
DeviceSelectionWrapper deviceStateToSend = connectedBluetoothDevice;
|
|
|
final DeviceSelectionWrapper result = await Navigator.push(
|
|
|
context,
|
|
@@ -98,8 +121,50 @@ class _MyHomePageState extends State<MyHomePage> {
|
|
|
|
|
|
//Update the status text
|
|
|
if (result.deviceSelected && result.deviceConnected) {
|
|
|
+ //Device already setup. Start listening to it
|
|
|
setState(() {
|
|
|
_statusText = "已連接到藍牙裝置 " + result.deviceName;
|
|
|
+
|
|
|
+ if (!_alreadyListening) {
|
|
|
+ connectedBluetoothDevice.connection.input?.listen(
|
|
|
+ (Uint8List data) {
|
|
|
+ var incomingData = utf8.decode(data);
|
|
|
+ incomingLine = incomingLine + incomingData;
|
|
|
+ if (incomingLine.contains("\n")) {
|
|
|
+ var chunks = incomingData.split("\n");
|
|
|
+ var lineToBeProcessed = chunks[0];
|
|
|
+ chunks.removeAt(0);
|
|
|
+ var otherLines = chunks.join("\n");
|
|
|
+ //Process the target line to the target data on screen
|
|
|
+ var values = lineToBeProcessed.split(",");
|
|
|
+ if (values.length == 3 &&
|
|
|
+ values[0] != "" &&
|
|
|
+ values[1] != "" &&
|
|
|
+ values[2] != "") {
|
|
|
+ //Valid data.
|
|
|
+ setState(() {
|
|
|
+ _pm01 = int.parse(values[0]);
|
|
|
+ _pm25 = int.parse(values[1]);
|
|
|
+ _pm10 = int.parse(values[2]);
|
|
|
+
|
|
|
+ _updateText = "最後更新: " +
|
|
|
+ DateFormat('kk:mm:ss dd/MM/yyyy')
|
|
|
+ .format(DateTime.now());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ print('Processing Line: ${lineToBeProcessed}');
|
|
|
+ //Replace the incoming line with the poped data
|
|
|
+ incomingLine = otherLines;
|
|
|
+ }
|
|
|
+ //connectedBluetoothDevice.connection.output.add(data); // Sending data
|
|
|
+ },
|
|
|
+ onDone: () {
|
|
|
+ //Connection terminated. Set already listening to false
|
|
|
+ _alreadyListening = false;
|
|
|
+ },
|
|
|
+ );
|
|
|
+ _alreadyListening = true;
|
|
|
+ }
|
|
|
});
|
|
|
} else {
|
|
|
setState(() {
|
|
@@ -109,15 +174,6 @@ class _MyHomePageState extends State<MyHomePage> {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- void _connectBluetoothDevice() {
|
|
|
- try {
|
|
|
- _btConnected = true;
|
|
|
- } catch (exception) {
|
|
|
- //Connection to BT failed
|
|
|
- _btConnected = false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
// This method is rerun every time setState is called, for instance as done
|
|
@@ -175,7 +231,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|
|
Expanded(
|
|
|
flex: 2,
|
|
|
child: Container(
|
|
|
- padding: EdgeInsets.all(5),
|
|
|
+ padding: const EdgeInsets.all(5),
|
|
|
height: 120,
|
|
|
color: Colors.blue,
|
|
|
child: Text(
|
|
@@ -222,7 +278,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|
|
child: Container(
|
|
|
padding: EdgeInsets.all(5),
|
|
|
height: 120,
|
|
|
- color: Colors.grey,
|
|
|
+ color: GetPm25Color(),
|
|
|
child: Text(
|
|
|
(() {
|
|
|
if (_pm25 == 0) {
|
|
@@ -270,7 +326,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|
|
child: Container(
|
|
|
padding: EdgeInsets.all(5),
|
|
|
height: 120,
|
|
|
- color: Colors.grey,
|
|
|
+ color: GetPm10Color(),
|
|
|
child: Text(
|
|
|
(() {
|
|
|
if (_pm10 == 0) {
|
|
@@ -307,6 +363,11 @@ class _MyHomePageState extends State<MyHomePage> {
|
|
|
)),
|
|
|
),
|
|
|
])),
|
|
|
+ Container(
|
|
|
+ alignment: Alignment.center,
|
|
|
+ padding: EdgeInsetsDirectional.all(16),
|
|
|
+ child: Text(_updateText),
|
|
|
+ )
|
|
|
],
|
|
|
),
|
|
|
)),
|