瀏覽代碼

add inner log

Melon 1 年之前
父節點
當前提交
a92ef657f7

二進制
android/libs/device_sdk.aar


二進制
example/android/app/libs/device_sdk.aar


+ 7 - 7
example/lib/global.dart

@@ -11,13 +11,13 @@ abstract class Global {
 
     await VnoteDevicePluginPlatform.instance.init();
 
-    final myListener = DeviceEventListener(
-      accpetStatusList: null, // 不传监听全部
-      callback: (int status, Map<String, dynamic>? data) {
-        logger.i("DEVIC_STATUS: $status");
-      },
-    );
-    DeviceEventCenter.instance.addListener(myListener);
+    // final myListener = DeviceEventListener(
+    //   accpetStatusList: null, // 不传监听全部
+    //   callback: (int status, Map<String, dynamic>? data) {
+    //     logger.i("DEVIC_STATUS: $status");
+    //   },
+    // );
+    // DeviceEventCenter.instance.addListener(myListener);
 
     GlobalDeviceEventHandler.setup(statusHandlers: [
       DeviceStatusTipsHandler(

+ 14 - 0
lib/devices/base.dart

@@ -7,6 +7,7 @@ import 'package:vnote_device_plugin/events/event_center.dart';
 import 'package:vnote_device_plugin/events/event_type.dart';
 import 'package:vnote_device_plugin/models/device.dart';
 import 'package:vnote_device_plugin/utils/lock.dart';
+import 'package:vnote_device_plugin/utils/logger.dart';
 import 'package:vnote_device_plugin/vnote_device_plugin_platform_interface.dart';
 
 import 'searcher.dart';
@@ -170,6 +171,8 @@ abstract class DeviceWorkerBase {
 
     await _searchProxy!.search();
 
+    log("Connect");
+
     await VnoteDevicePluginPlatform.instance.callAction(
       "BLE_CONNECT",
       {
@@ -191,6 +194,8 @@ abstract class DeviceWorkerBase {
       return;
     }
 
+    log("Disconnect");
+
     await VnoteDevicePluginPlatform.instance.callAction(
       "BLE_DISCONNECT",
       {"MODEL": model},
@@ -250,22 +255,26 @@ abstract class DeviceWorkerBase {
   }
 
   void _onConnectedCallback() {
+    log("Connected callback");
     _isConnecting = false;
     _isConnected = true;
     connectedEvent.emit(this, null);
   }
 
   void _onConnectErrorCallback(int status, Map<String, dynamic>? data) {
+    log("Connect error callback");
     _isConnecting = false;
     connectErrorEvent.emit(this, status);
   }
 
   void _onDisconnectedCallback() {
+    log("Disconnecting callback");
     _isConnected = false;
     disconnectedEvent.emit(this, null);
   }
 
   void _onConnectingCallback() {
+    log("Connecting callback");
     connectingEvent.emit(this, null);
   }
 
@@ -281,4 +290,9 @@ abstract class DeviceWorkerBase {
 
     return false;
   }
+
+  @protected
+  void log(String content) {
+    LogUtil.write("DeviceWorker[$type] $content.");
+  }
 }

+ 5 - 0
lib/devices/heart.dart

@@ -40,24 +40,29 @@ class HeartDeviceWorker extends DeviceWorkerBase {
   void _onValueUpdate(Map<String, dynamic>? data) {
     final HeartExamData examData = HeartExamData.fromEventData(data!);
     if (examData.ecgPoints.isNotEmpty) {
+      log("Value update; Points size: ${examData.ecgPoints.length}");
       ecgValueUpdateEvent.emit(this, examData.ecgPoints);
     } else if (examData.heartRate > 0) {
+      log("Value update; HR: ${examData.heartRate}");
       hrValueUpdateEvent.emit(this, examData.heartRate);
     }
   }
 
   void _onResult(Map<String, dynamic>? data) {
     final HeartExamResult examData = HeartExamResult.fromEventData(data!);
+    log("Result; HR: ${examData.heartRate}, Analysis: ${examData.analysis.join("|")}");
     resultReceivedEvent.emit(this, examData);
   }
 
   void _onFalloffError(Map<String, dynamic>? data) {
     const String msg = "导联脱落"; // TODO: pick message from data
+    log("Falloff: $msg");
     errorEvent.emit(this, msg);
   }
 
   void _onNoiseError(Map<String, dynamic>? data) {
     const String msg = "EE";
+    log("Noise: $msg");
     errorEvent.emit(this, msg);
   }
 }

+ 2 - 0
lib/devices/ic_reader.dart

@@ -27,11 +27,13 @@ class ICReaderDeviceWorker extends DeviceWorkerBase {
 
   void _onSuccess(Map<String, dynamic>? data) {
     final ICReaderExamData examData = ICReaderExamData.fromEventData(data!);
+    log("Result; CardNo: ${examData.cardNo}, Name: ${examData.name}");
     successEvent.emit(this, examData);
   }
 
   void _onFail(Map<String, dynamic>? data) {
     final String msg = data!["MSG"];
+    log("Fail: $msg");
     errorEvent.emit(this, msg);
   }
 }

+ 5 - 0
lib/devices/nibp.dart

@@ -55,28 +55,33 @@ class NibpDeviceWorker extends DeviceWorkerBase {
 
   void _onLive(Map<String, dynamic>? data) {
     final NibpExamData examData = NibpExamData.fromEventData(data!);
+    log("Value update: ${examData.pressure}");
     liveUpdateEvent.emit(this, examData.pressure);
   }
 
   void _onResult(Map<String, dynamic>? data) {
     final NibpExamData examData = NibpExamData.fromEventData(data!);
+    log("Result; Sbp: ${examData.systolicPressure}, Dbp: ${examData.diastolicPressure}, Pulse: ${examData.pulse}");
     resultUpdateEvent.emit(this, examData);
   }
 
   void _onError(Map<String, dynamic>? data) {
     final String errMsg = data?["MESSAGE"] ?? "";
     final String msg = "${VDeviceEventStatus.EXAM_NIBP_ERROR}|Error|$errMsg";
+    log("Error: $msg");
     errorEvent.emit(this, msg);
   }
 
   void _onBusyError(Map<String, dynamic>? data) {
     const String msg =
         "${VDeviceEventStatus.EXAM_NIBP_BUSY_ERROR}|ProbeFalloff";
+    log("Busy Error: $msg");
     errorEvent.emit(this, msg);
   }
 
   void _onNoResultError(Map<String, dynamic>? data) {
     const String msg = "${VDeviceEventStatus.EXAM_NIBP_NO_RESULT}|NoResult";
+    log("NoResult Error: $msg");
     errorEvent.emit(this, msg);
   }
 }

+ 20 - 0
lib/devices/searcher.dart

@@ -1,6 +1,7 @@
 import 'dart:async';
 
 import 'package:vnote_device_plugin/events/event_type.dart';
+import 'package:vnote_device_plugin/utils/logger.dart';
 
 import '../consts/status.dart';
 import '../events/defines.dart';
@@ -44,10 +45,12 @@ class DeviceSearcher {
   }
 
   void init() {
+    _log("Init");
     DeviceEventCenter.instance.addListener(_listener);
   }
 
   void dispose() {
+    _log("Dispose");
     DeviceEventCenter.instance.removeListener(_listener);
   }
 
@@ -55,6 +58,9 @@ class DeviceSearcher {
     _busy = true;
 
     _startCompleter = Completer<void>();
+
+    _log("Start");
+
     await VnoteDevicePluginPlatform.instance.callAction(
       "SEARCH_START",
       {"TYPE": type},
@@ -65,6 +71,9 @@ class DeviceSearcher {
 
   Future<void> stop() async {
     _stopCompleter = Completer<void>();
+
+    _log("Stop");
+
     await VnoteDevicePluginPlatform.instance.callAction(
       "SEARCH_STOP",
       {"TYPE": type},
@@ -89,15 +98,18 @@ class DeviceSearcher {
   }
 
   void _onStartCallback(Map<String, dynamic>? data) {
+    _log("Start callback");
     _startCompleter?.complete();
   }
 
   void _onTimeoutCallback() {
+    _log("Timeout callback");
     _busy = false;
     timeoutEvent.emit(this, null);
   }
 
   void _onStopCallback(Map<String, dynamic>? data) {
+    _log("Stop callback");
     if (_stopCompleter == null) {
       // 搜索超时
       if (_busy) {
@@ -110,16 +122,24 @@ class DeviceSearcher {
   }
 
   void _onFoundCallback(Map<String, dynamic>? data) {
+    _log("Found");
     _busy = false;
     //  {"STATUS":104,"DATA":{"BLE_NAME":"IR Thermo","BLE_PRODUCT_NAME":"体温计(家测宝)","MAC":"44:A6:E5:16:62:33","MODEL":"DT-8836","TYPE":"temp"}}
     if (data != null) {
       final device = DeviceInfo.fromEventData(data);
+      _log(
+          "BleName: ${device.bleName}, ProductName: ${device.productName}, Model: ${device.model}, Mac: ${device.mac}");
       successEvent.emit(this, device);
     }
   }
 
   void _onNotFoundCallback(Map<String, dynamic>? data) {
     final message = data?["MESSAGE"] ?? "ERROR";
+    _log("Error: $message");
     failEvent.emit(this, message); // TODO:
   }
+
+  void _log(String content) {
+    LogUtil.write("DeviceSearcher[$type] $content.");
+  }
 }

+ 3 - 0
lib/devices/sp_o2.dart

@@ -32,17 +32,20 @@ class SpO2DeviceWorker extends DeviceWorkerBase {
 
   void _onValue(Map<String, dynamic>? data) {
     final SpO2ExamData examData = SpO2ExamData.fromEventData(data!);
+    log("Vaule updata; SpO2: ${examData.spO2}, Pulse: ${examData.pulse}");
     valueUpdateEvent.emit(this, examData);
   }
 
   void _onPoints(Map<String, dynamic>? data) {
     final SpO2ExamData examData = SpO2ExamData.fromEventData(data!);
+    log("Points updata; Length: ${examData.points.length}");
     pointsUpdateEvent.emit(this, examData.points);
   }
 
   void _onFalloffError(Map<String, dynamic>? data) {
     const String msg =
         "${VDeviceEventStatus.EXAM_SPO2PROBE_FALLOFF_ERROR}|ProbeFalloff";
+    log("Error: $msg");
     errorEvent.emit(this, msg);
   }
 }

+ 4 - 0
lib/devices/sugar.dart

@@ -37,22 +37,26 @@ class SugarDeviceWorker extends DeviceWorkerBase {
 
   void _onSuccess(Map<String, dynamic>? data) {
     final SugarExamData examData = SugarExamData.fromEventData(data!);
+    log("Result; SUGAR: ${examData.sugar}");
     successEvent.emit(this, examData);
   }
 
   void _onError(Map<String, dynamic>? data) {
     final String msg = data!["MESSAGE"];
+    log("Error: $msg");
     errorEvent.emit(this, msg);
   }
 
   void _onWarn(Map<String, dynamic>? data) {
     final ExamError model = ExamError.fromEventData(data!);
     model.code = "E${model.code}";
+    log("Warn; CODE: ${model.code}, MSG: ${model.message}");
     warnEvent.emit(this, model);
   }
 
   void _onStatus(Map<String, dynamic>? data) {
     final ExamError model = ExamError.fromEventData(data!);
+    log("Status; CODE: ${model.code}, MSG: ${model.message}");
     statusEvent.emit(this, model);
   }
 }

+ 4 - 0
lib/devices/temp.dart

@@ -34,21 +34,25 @@ class TempDeviceWorker extends DeviceWorkerBase {
 
   void _onTempSuccess(Map<String, dynamic>? data) {
     final double value = data!["TEMP"].toDouble();
+    log("Result; TEMP: $value");
     successEvent.emit(this, value);
   }
 
   void _onTempError(Map<String, dynamic>? data) {
     final String msg = data!["MESSAGE"];
+    log("Error: $msg");
     errorEvent.emit(this, msg);
   }
 
   void _onTempTooLow(Map<String, dynamic>? data) {
     final double value = data!["TEMP"].toDouble();
+    log("Result|TooLow; TEMP: $value");
     tempTooLowEvent.emit(this, value);
   }
 
   void _onTempTooHigh(Map<String, dynamic>? data) {
     final double value = data!["TEMP"].toDouble();
+    log("Result|TooHigh; TEMP: $value");
     tempTooHighEvent.emit(this, value);
   }
 }

+ 3 - 0
lib/devices/urine.dart

@@ -31,15 +31,18 @@ class UrineDeviceWorker extends DeviceWorkerBase {
 
   void _onSuccess(Map<String, dynamic>? data) {
     final UrineExamData examData = UrineExamData.fromEventData(data!);
+    log("Result; LEU: ${examData.leu}, BLD: ${examData.bld}, NIT: ${examData.nit}, KET: ${examData.ket}");
     successEvent.emit(this, examData);
   }
 
   void _onError(Map<String, dynamic>? data) {
     final String msg = data!["MESSAGE"] ?? "ERROR";
+    log("Error: $msg");
     errorEvent.emit(this, msg);
   }
 
   void _onNoResult(Map<String, dynamic>? data) {
+    log("NoResult");
     noResultEvent.emit(this, null);
   }
 }

+ 2 - 0
lib/devices/weight.dart

@@ -26,11 +26,13 @@ class WeightDeviceWorker extends DeviceWorkerBase {
 
   void _onSuccess(Map<String, dynamic>? data) {
     final double value = data!["WEIGHT"].toDouble();
+    log("Result: $value");
     successEvent.emit(this, value);
   }
 
   void _onError(Map<String, dynamic>? data) {
     final String msg = data!["MESSAGE"];
+    log("Error: $msg");
     errorEvent.emit(this, msg);
   }
 }

+ 3 - 0
lib/events/event_center.dart

@@ -2,6 +2,8 @@ import 'dart:collection';
 import 'dart:convert';
 import 'dart:math';
 
+import 'package:vnote_device_plugin/utils/logger.dart';
+
 import 'defines.dart';
 
 /// 设备事件监听器
@@ -71,6 +73,7 @@ class DeviceEventCenter {
 
   /// 通知事件
   void emit(String jsonText) {
+    LogUtil.write("@EVENT Received! $jsonText");
     final res = jsonDecode(jsonText);
     final int status = res["STATUS"];
     final dynamic data = res["DATA"];

+ 109 - 0
lib/utils/logger.dart

@@ -0,0 +1,109 @@
+import 'dart:io';
+
+import 'package:intl/intl.dart';
+import 'package:path_provider/path_provider.dart' as path_provide;
+import 'package:path/path.dart' as path;
+
+class LogUtil {
+  static _Logger? _singleton;
+
+  static Future<void> init() async {
+    if (_singleton == null) {
+      final instance = _Logger();
+      await instance.init();
+      _singleton = instance;
+    }
+  }
+
+  static Future<void> dispose() async {
+    await _singleton?.dispose();
+    _singleton = null;
+  }
+
+  static void write(String content) {
+    if (_singleton != null) {
+      Future.microtask(() {
+        _singleton?.write(content);
+        _checkFileSize();
+      });
+    }
+  }
+
+  static void _checkFileSize() async {
+    if (_singleton!.lineCount > 9999) {
+      _singleton!.write("***Lines too many, ready to create new one***");
+      final instance = _Logger();
+      await instance.init();
+      _singleton = instance;
+      _singleton!.write("***New log which after the last big one***");
+    }
+  }
+}
+
+class _Logger {
+  // ignore: constant_identifier_names
+  static const _DIR = "device_plugin";
+
+  IOSink? _ioSink;
+  late final String _fileName;
+
+  int lineCount = 0;
+
+  Future<void> init() async {
+    Directory? dir = await path_provide.getExternalStorageDirectory();
+    dir ??= await path_provide.getApplicationDocumentsDirectory();
+    final now = DateTime.now();
+    final logTag = DateFormat('yyyyMMddHHmmssSSS').format(now);
+    final fullDir = path.join(dir.path, _DIR);
+    await _checkDir(fullDir);
+    _fileName = path.join(fullDir, "$logTag.log");
+    print(_fileName);
+  }
+
+  Future<void> dispose() async {
+    await _ioSink?.close();
+    _ioSink = null;
+  }
+
+  void write(String content) async {
+    _keepIOSink();
+
+    try {
+      final line = _buildLine(content);
+      _ioSink!.writeln(line);
+      lineCount++;
+    } catch (e) {
+      try {
+        _ioSink!.close();
+        _ioSink = null;
+      } catch (e) {
+        //
+      }
+    }
+  }
+
+  void _keepIOSink() {
+    if (_ioSink == null) {
+      final file = File(_fileName);
+      _ioSink = file.openWrite(mode: FileMode.append);
+    }
+  }
+
+  String _buildLine(String content) {
+    final now = DateTime.now();
+    final timeStr = DateFormat('yyyyMMddHHmmss.SSS').format(now);
+    return "[$timeStr] $content";
+  }
+
+  Future<void> _checkDir(String dir) async {
+    final directory = Directory(dir);
+    final isExists = await directory.exists();
+    if (!isExists) {
+      try {
+        await directory.create();
+      } catch (e) {
+        //
+      }
+    }
+  }
+}

+ 2 - 0
lib/vnote_device_plugin_method_channel.dart

@@ -4,6 +4,7 @@ import 'dart:convert';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/services.dart';
 import 'package:vnote_device_plugin/events/event_center.dart';
+import 'package:vnote_device_plugin/utils/logger.dart';
 
 import 'vnote_device_plugin_platform_interface.dart';
 
@@ -37,6 +38,7 @@ class MethodChannelVnoteDevicePlugin extends VnoteDevicePluginPlatform {
 
   @override
   Future<void> init() async {
+    await LogUtil.init();
     _eventChannelSubcription ??=
         eventChannel.receiveBroadcastStream().listen(_onEventReceived);
     return methodChannel.invokeMethod("init");

+ 3 - 0
pubspec.yaml

@@ -11,6 +11,9 @@ dependencies:
   flutter:
     sdk: flutter
   plugin_platform_interface: ^2.0.2
+  path_provider: ^2.1.0
+  path: ^1.8.0
+  intl: ^0.17.0
 
 dev_dependencies:
   flutter_test: