Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
laki_icu_app
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张宏
laki_icu_app
Commits
54acb255
Commit
54acb255
authored
Jun 24, 2026
by
akari
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 添加蓝牙控制打印日志
parent
74d50b40
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
210 additions
and
23 deletions
+210
-23
device_control_bloc.dart
lib/blocs/device_control/device_control_bloc.dart
+66
-4
bluetooth_manager.dart
lib/utils/bluetooth/bluetooth_manager.dart
+12
-1
monitoring_index_cubit.dart
lib/views/monitoring/index/cubit/monitoring_index_cubit.dart
+130
-17
monitoring_index_view.dart
lib/views/monitoring/index/monitoring_index_view.dart
+2
-1
No files found.
lib/blocs/device_control/device_control_bloc.dart
View file @
54acb255
...
...
@@ -5,6 +5,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import
'device_control_event.dart'
;
import
'device_control_state.dart'
;
import
'package:laki_icu_app/models/bo/device_control_bo.dart'
;
import
'package:laki_icu_app/models/bo/bluetooth_read_model.dart'
;
import
'package:laki_icu_app/utils/bluetooth/index.dart'
;
import
'package:laki_icu_app/utils/event_bus.dart'
;
import
'package:laki_icu_app/utils/logger.dart'
;
...
...
@@ -181,6 +182,11 @@ class DeviceControlBloc
);
if
(
reports
.
isEmpty
||
isClosed
)
return
;
final
latestReport
=
reports
.
last
;
eventBus
.
emit
(
BluetoothReadInfoChangedEvent
(
BluetoothReadModel
.
fromMcuReport
(
latestReport
),
),
);
eventBus
.
emit
(
McuReportChangedEvent
(
latestReport
));
}
catch
(
e
)
{
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG device_control_parse_error error=
$e
'
);
...
...
@@ -210,19 +216,31 @@ class DeviceControlBloc
sn:
report
.
sn
.
isEmpty
?
state
.
data
.
sn
:
report
.
sn
,
cabinTemp:
state
.
data
.
cabinTemp
.
copyWith
(
currentValue:
_formatTemperature
(
report
.
mainTemperature
),
setValue:
_formatTemperature
(
report
.
temperatureSetting
),
setValue:
_formatTemperatureOrKeep
(
report
.
temperatureSetting
,
state
.
data
.
cabinTemp
.
setValue
,
),
),
cabinHumidity:
state
.
data
.
cabinHumidity
.
copyWith
(
currentValue:
_formatInt
(
report
.
humidity
),
setValue:
_formatInt
(
report
.
humiditySetting
),
setValue:
_formatIntOrKeep
(
report
.
humiditySetting
,
state
.
data
.
cabinHumidity
.
setValue
,
),
),
oxygenConcentration:
state
.
data
.
oxygenConcentration
.
copyWith
(
currentValue:
_formatInt
(
report
.
oxygenConcentration
),
setValue:
_formatInt
(
report
.
oxygenSetting
),
setValue:
_formatIntOrKeep
(
report
.
oxygenSetting
,
state
.
data
.
oxygenConcentration
.
setValue
,
),
),
co2Concentration:
state
.
data
.
co2Concentration
.
copyWith
(
currentValue:
_formatInt
(
report
.
co2Measurement
),
alarmThreshold:
_formatInt
(
report
.
co2Setting
),
alarmThreshold:
_formatIntOrKeep
(
report
.
co2Setting
,
state
.
data
.
co2Concentration
.
alarmThreshold
,
),
),
);
emit
(
state
.
copyWith
(
data:
newData
,
clearError:
true
));
...
...
@@ -287,6 +305,10 @@ class DeviceControlBloc
)
async
{
final
currentValue
=
int
.
tryParse
(
state
.
data
.
cabinTemp
.
setValue
)
??
0
;
final
nextValue
=
(
currentValue
+
event
.
step
).
clamp
(
0
,
99
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG cabin_temp_adjust '
'current=
$currentValue
step=
${event.step}
next=
$nextValue
'
,
);
await
_setCabinTempSetValue
(
'
$nextValue
'
,
emit
);
}
...
...
@@ -304,6 +326,9 @@ class DeviceControlBloc
userSettings:
state
.
userSettings
.
copyWith
(
cabinTempSetValue:
setValue
),
clearError:
true
,
));
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG cabin_temp_set_value value=
$setValue
'
,
);
await
_writeControlValueToBluetooth
(
identifier:
0x02
,
setValue:
setValue
,
...
...
@@ -361,6 +386,10 @@ class DeviceControlBloc
)
async
{
final
currentValue
=
int
.
tryParse
(
state
.
data
.
cabinHumidity
.
setValue
)
??
0
;
final
nextValue
=
(
currentValue
+
event
.
step
).
clamp
(
0
,
100
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG cabin_humidity_adjust '
'current=
$currentValue
step=
${event.step}
next=
$nextValue
'
,
);
await
_setCabinHumiditySetValue
(
'
$nextValue
'
,
emit
);
}
...
...
@@ -379,6 +408,9 @@ class DeviceControlBloc
state
.
userSettings
.
copyWith
(
cabinHumiditySetValue:
setValue
),
clearError:
true
,
));
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG cabin_humidity_set_value value=
$setValue
'
,
);
await
_writeControlValueToBluetooth
(
identifier:
0x04
,
setValue:
setValue
,
...
...
@@ -436,6 +468,10 @@ class DeviceControlBloc
final
currentValue
=
int
.
tryParse
(
state
.
data
.
oxygenConcentration
.
setValue
)
??
0
;
final
nextValue
=
(
currentValue
+
event
.
step
).
clamp
(
0
,
100
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG oxygen_concentration_adjust '
'current=
$currentValue
step=
${event.step}
next=
$nextValue
'
,
);
await
_setOxygenConcentrationSetValue
(
'
$nextValue
'
,
emit
);
}
...
...
@@ -454,6 +490,9 @@ class DeviceControlBloc
state
.
userSettings
.
copyWith
(
oxygenConcentrationSetValue:
setValue
),
clearError:
true
,
));
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG oxygen_concentration_set_value value=
$setValue
'
,
);
await
_writeControlValueToBluetooth
(
identifier:
0x05
,
setValue:
setValue
,
...
...
@@ -512,6 +551,10 @@ class DeviceControlBloc
final
currentValue
=
int
.
tryParse
(
state
.
data
.
co2Concentration
.
alarmThreshold
)
??
0
;
final
nextValue
=
(
currentValue
+
event
.
step
).
clamp
(
0
,
9999
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG co2_alarm_threshold_adjust '
'current=
$currentValue
step=
${event.step}
next=
$nextValue
'
,
);
await
_setCO2ConcentrationAlarmThreshold
(
'
$nextValue
'
,
emit
);
}
...
...
@@ -530,6 +573,10 @@ class DeviceControlBloc
state
.
userSettings
.
copyWith
(
co2AlarmThreshold:
alarmThreshold
),
clearError:
true
,
));
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG co2_alarm_threshold_set_value '
'value=
$alarmThreshold
'
,
);
await
_writeControlValueToBluetooth
(
identifier:
0x31
,
setValue:
alarmThreshold
,
...
...
@@ -860,6 +907,13 @@ class DeviceControlBloc
await
_bluetoothManager
.
connectToDeviceId
(
deviceId
);
}
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG send_control '
'identifier=0x
${identifier.toRadixString(16).padLeft(2, '0').toUpperCase()}
'
'value=
$setValue
scale=
$scale
'
'hex=
${BleBluetoothManager.bytesToHex(command)}
'
'isConnected=
${_bluetoothManager.isConnected}
'
,
);
await
_bluetoothManager
.
writeData
(
command
);
}
catch
(
e
)
{
emit
(
state
.
copyWith
(
error:
'
$errorPrefix
发送失败:
$e
'
));
...
...
@@ -893,10 +947,18 @@ class DeviceControlBloc
return
fixed
.
endsWith
(
'.0'
)
?
fixed
.
substring
(
0
,
fixed
.
length
-
2
)
:
fixed
;
}
String
_formatTemperatureOrKeep
(
double
value
,
String
fallback
)
{
return
value
.
isNaN
?
fallback
:
_formatTemperature
(
value
);
}
String
_formatInt
(
int
value
)
{
return
value
<
0
?
'--'
:
'
$value
'
;
}
String
_formatIntOrKeep
(
int
value
,
String
fallback
)
{
return
value
<
0
?
fallback
:
'
$value
'
;
}
@override
Future
<
void
>
close
()
async
{
await
_mcuReportSub
.
cancel
();
...
...
lib/utils/bluetooth/bluetooth_manager.dart
View file @
54acb255
...
...
@@ -376,6 +376,15 @@ class BleBluetoothManager<T> {
return
;
}
final
hex
=
bytesToHex
(
data
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG write_data '
'deviceId=
${characteristic.deviceId}
'
'service=
${characteristic.serviceId}
'
'characteristic=
${characteristic.characteristicId}
'
'withoutResponse=
$withoutResponse
'
'hex=
$hex
'
,
);
try
{
if
(
withoutResponse
)
{
await
_ble
.
writeCharacteristicWithoutResponse
(
...
...
@@ -385,9 +394,11 @@ class BleBluetoothManager<T> {
}
else
{
await
_ble
.
writeCharacteristicWithResponse
(
characteristic
,
value:
data
);
}
_notifyMessage
(
'蓝牙数据发送成功:
${bytesToHex(data)}
'
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG write_success hex=
$hex
'
);
_notifyMessage
(
'蓝牙数据发送成功:
$hex
'
);
_sendResultController
.
add
(
true
);
}
catch
(
error
)
{
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG write_error hex=
$hex
error=
$error
'
);
_notifyMessage
(
'蓝牙数据发送失败:
$error
'
);
_sendResultController
.
add
(
false
);
}
...
...
lib/views/monitoring/index/cubit/monitoring_index_cubit.dart
View file @
54acb255
...
...
@@ -34,6 +34,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
StreamSubscription
<
BluetoothConnectionStatus
>?
_bluetoothStateSub
;
StreamSubscription
<
String
>?
_bluetoothMessageSub
;
StreamSubscription
<
BluetoothDataPacket
>?
_bluetoothDataSub
;
StreamSubscription
<
BluetoothReadInfoChangedEvent
>?
_bluetoothReadInfoSub
;
StreamSubscription
<
McuReportChangedEvent
>?
_mcuReportChangedSub
;
StreamSubscription
<
LakiMqttConnectionState
>?
_mqttStateSub
;
StreamSubscription
<
LakiMqttMessage
>?
_mqttMessageSub
;
...
...
@@ -62,6 +63,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_listenWebrtcState
();
_listenP2pState
();
_listenBluetoothState
();
_listenBluetoothReadInfo
();
_listenMcuReportChanged
();
_loadBoundBluetoothDevice
();
loadData
();
...
...
@@ -170,13 +172,40 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
void
_listenMcuReportChanged
()
{
_mcuReportChangedSub
=
eventBus
.
on
<
McuReportChangedEvent
>().
listen
((
event
)
{
if
(
isClosed
)
return
;
final
metrics
=
_metricsFromBluetoothReport
(
event
.
report
);
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG index_metrics_from_report '
'
${_metricsLogText(metrics)}
'
,
);
emit
(
state
.
copyWith
(
latestMcuReport:
event
.
report
,
metrics:
_metricsFromBluetoothReport
(
event
.
report
)
,
metrics:
metrics
,
));
});
}
void
_listenBluetoothReadInfo
()
{
_bluetoothReadInfoSub
=
eventBus
.
on
<
BluetoothReadInfoChangedEvent
>().
listen
((
event
)
{
if
(
isClosed
)
return
;
final
metrics
=
_metricsFromBluetoothReadInfo
(
event
.
info
);
if
(
metrics
==
null
)
{
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG index_read_info_no_metrics '
'sn=
${event.info.sn}
temp=
${event.info.mainTemperature}
'
'humidity=
${event.info.humidity}
o2=
${event.info.oxygenConcentration}
'
'co2=
${event.info.co2Measurement}
'
,
);
return
;
}
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG index_metrics_from_read_info '
'
${_metricsLogText(metrics)}
'
,
);
emit
(
state
.
copyWith
(
metrics:
metrics
));
});
}
String
_appendBluetoothSideToSn
(
String
sn
)
{
final
cleanSn
=
sn
.
trim
();
if
(
cleanSn
.
isEmpty
)
return
''
;
...
...
@@ -232,8 +261,8 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
));
try
{
final
metrics
=
await
_monitoringService
.
getMetrics
();
if
(
isClosed
)
return
;
//
final metrics = await _monitoringService.getMetrics();
//
if (isClosed) return;
final
patientInfo
=
await
_monitoringService
.
getPatientInfo
();
if
(
isClosed
)
return
;
final
alerts
=
await
_monitoringService
.
getAlerts
();
...
...
@@ -242,7 +271,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
emit
(
state
.
copyWith
(
status:
MonitoringIndexStatus
.
success
,
isLoading:
false
,
metrics:
metrics
,
patientInfo:
patientInfo
,
alerts:
alerts
,
error:
null
,
...
...
@@ -347,8 +375,8 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
Future
<
void
>
refreshData
()
async
{
try
{
final
metrics
=
await
_monitoringService
.
getMetrics
();
if
(
isClosed
)
return
;
//
final metrics = await _monitoringService.getMetrics();
//
if (isClosed) return;
final
patientInfo
=
await
_monitoringService
.
getPatientInfo
();
if
(
isClosed
)
return
;
final
alerts
=
await
_monitoringService
.
getAlerts
();
...
...
@@ -356,7 +384,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
emit
(
state
.
copyWith
(
status:
MonitoringIndexStatus
.
success
,
metrics:
metrics
,
patientInfo:
patientInfo
,
alerts:
alerts
,
error:
null
,
...
...
@@ -666,36 +693,98 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_mqttClient
=
null
;
}
List
<
MonitoringMetricBO
>
_metricsFromBluetoothReport
(
McuReport
report
)
{
List
<
MonitoringMetricBO
>
_metricsFromBluetoothReport
(
McuReport
report
,
{
List
<
MonitoringMetricBO
>?
baseMetrics
,
})
{
final
metrics
=
baseMetrics
??
state
.
metrics
;
final
replacements
=
<
String
,
MonitoringMetricBO
>{
'舱内温度'
:
_replaceMetricValue
(
'舱内温度'
,
_formatReportTemperatureOrKeep
(
report
.
mainTemperature
,
'舱内温度'
),
fallbackUnit:
'℃'
,
baseMetrics:
metrics
,
),
'舱内湿度'
:
_replaceMetricValue
(
'舱内湿度'
,
_formatReportIntOrKeep
(
report
.
humidity
,
'舱内湿度'
),
fallbackUnit:
'RH'
,
baseMetrics:
metrics
,
),
'氧气浓度'
:
_replaceMetricValue
(
'氧气浓度'
,
_formatReportIntOrKeep
(
report
.
oxygenConcentration
,
'氧气浓度'
),
fallbackUnit:
'%'
,
baseMetrics:
metrics
,
),
'二氧化碳'
:
_replaceMetricValue
(
'二氧化碳'
,
_formatReportIntOrKeep
(
report
.
co2Measurement
,
'二氧化碳'
),
fallbackUnit:
'ppm'
,
baseMetrics:
metrics
,
),
};
if
(
metrics
.
isEmpty
)
{
return
replacements
.
values
.
toList
();
}
return
[
for
(
final
metric
in
metrics
)
replacements
[
metric
.
label
]
??
metric
,
];
}
List
<
MonitoringMetricBO
>?
_metricsFromBluetoothReadInfo
(
BluetoothReadModel
info
,
)
{
final
hasMetric
=
info
.
mainTemperature
!=
null
||
info
.
humidity
!=
null
||
info
.
oxygenConcentration
!=
null
||
info
.
co2Measurement
!=
null
;
if
(!
hasMetric
)
return
null
;
final
metrics
=
state
.
metrics
;
final
replacements
=
<
String
,
MonitoringMetricBO
>{
'舱内温度'
:
_replaceMetricValue
(
'舱内温度'
,
_formatReportTemperature
(
report
.
mainTemperature
),
info
.
mainTemperature
==
null
?
_existingMetricValue
(
'舱内温度'
)
??
'--'
:
_formatReportTemperature
(
info
.
mainTemperature
!),
fallbackUnit:
'℃'
,
baseMetrics:
metrics
,
),
'舱内湿度'
:
_replaceMetricValue
(
'舱内湿度'
,
_formatReportInt
(
report
.
humidity
),
info
.
humidity
==
null
?
_existingMetricValue
(
'舱内湿度'
)
??
'--'
:
'
${info.humidity}
'
,
fallbackUnit:
'RH'
,
baseMetrics:
metrics
,
),
'氧气浓度'
:
_replaceMetricValue
(
'氧气浓度'
,
_formatReportInt
(
report
.
oxygenConcentration
),
info
.
oxygenConcentration
==
null
?
_existingMetricValue
(
'氧气浓度'
)
??
'--'
:
'
${info.oxygenConcentration}
'
,
fallbackUnit:
'%'
,
baseMetrics:
metrics
,
),
'二氧化碳'
:
_replaceMetricValue
(
'二氧化碳'
,
_formatReportInt
(
report
.
co2Measurement
),
info
.
co2Measurement
==
null
?
_existingMetricValue
(
'二氧化碳'
)
??
'--'
:
'
${info.co2Measurement}
'
,
fallbackUnit:
'ppm'
,
baseMetrics:
metrics
,
),
};
if
(
state
.
metrics
.
isEmpty
)
{
if
(
metrics
.
isEmpty
)
{
return
replacements
.
values
.
toList
();
}
return
[
for
(
final
metric
in
state
.
metrics
)
replacements
[
metric
.
label
]
??
metric
,
for
(
final
metric
in
metrics
)
replacements
[
metric
.
label
]
??
metric
,
];
}
...
...
@@ -703,9 +792,11 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
String
label
,
String
value
,
{
required
String
fallbackUnit
,
List
<
MonitoringMetricBO
>?
baseMetrics
,
})
{
final
metrics
=
baseMetrics
??
state
.
metrics
;
MonitoringMetricBO
?
existing
;
for
(
final
metric
in
state
.
metrics
)
{
for
(
final
metric
in
metrics
)
{
if
(
metric
.
label
==
label
)
{
existing
=
metric
;
break
;
...
...
@@ -733,8 +824,29 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
return
fixed
.
endsWith
(
'.0'
)
?
fixed
.
substring
(
0
,
fixed
.
length
-
2
)
:
fixed
;
}
String
_formatReportInt
(
int
value
)
{
return
value
<
0
?
'--'
:
'
$value
'
;
String
_formatReportTemperatureOrKeep
(
double
value
,
String
label
)
{
if
(!
value
.
isNaN
)
return
_formatReportTemperature
(
value
);
return
_existingMetricValue
(
label
)
??
'--'
;
}
String
_formatReportIntOrKeep
(
int
value
,
String
label
)
{
if
(
value
>=
0
)
return
'
$value
'
;
return
_existingMetricValue
(
label
)
??
'--'
;
}
String
?
_existingMetricValue
(
String
label
)
{
for
(
final
metric
in
state
.
metrics
)
{
if
(
metric
.
label
==
label
&&
metric
.
value
!=
'--'
)
{
return
metric
.
value
;
}
}
return
null
;
}
String
_metricsLogText
(
List
<
MonitoringMetricBO
>
metrics
)
{
return
metrics
.
map
((
item
)
=>
'
${item.label}
=
${item.value}${item.unit}
'
)
.
join
(
' '
);
}
/// 清空宠物信息(出舱)
...
...
@@ -777,6 +889,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_bluetoothStateSub
?.
cancel
();
_bluetoothMessageSub
?.
cancel
();
_bluetoothDataSub
?.
cancel
();
_bluetoothReadInfoSub
?.
cancel
();
_mcuReportChangedSub
?.
cancel
();
_webrtcService
.
dispose
();
_p2pVideoService
.
dispose
();
...
...
lib/views/monitoring/index/monitoring_index_view.dart
View file @
54acb255
...
...
@@ -112,7 +112,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
children:
[
Expanded
(
flex:
32
,
child:
state
.
metrics
.
isEmpty
?
_buildMetricsEmpty
()
:
_buildMetrics
(
state
.
metrics
),
child:
_buildMetrics
(
state
.
metrics
),
),
SizedBox
(
height:
24
.
h
),
Expanded
(
...
...
@@ -149,6 +149,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
);
}
// ignore: unused_element
Widget
_buildMetricsEmpty
()
{
return
Container
(
width:
double
.
infinity
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment