1. 项目背景与需求分析
最近在为一个老旧小区改造智慧社区系统,业主委员会提出两个核心需求:一是替换传统的IC卡门禁,实现手机APP开门;二是需要一套线上报修系统,解决以往纸质工单易丢失、进度难追踪的问题。经过技术选型,最终决定基于Flutter框架开发跨平台应用,后端对接OpenHarmony系统的门禁控制器。
选择Flutter主要考虑到:
- 跨平台特性:一套代码可同时生成Android和iOS应用,降低维护成本
- 热重载功能:开发调试效率显著提升,尤其适合快速迭代的社区项目
- 丰富的UI组件库:Material和Cupertino风格组件可快速构建美观界面
而选择OpenHarmony作为硬件系统是因为:
- 分布式能力:未来可扩展对接社区其他IoT设备(如摄像头、电梯控制)
- 国产化支持:符合社区对数据安全的特殊要求
- 内核级优化:对低功耗设备(如门禁机)的运行效率更好
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境搭建与项目初始化
2.1 Flutter环境配置
在MacOS环境下执行以下步骤(Windows类似):
bash复制# 安装Flutter SDK
brew install --cask flutter
# 验证安装
flutter doctor
# 安装Android Studio和Xcode(略)
# 配置VS Code插件:Flutter、Dart
特别注意:
- 国内用户需要配置Pub镜像源
bash复制export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
2.2 OpenHarmony开发环境
- 下载DevEco Studio 3.1+版本
- 安装OpenHarmony SDK
- 配置门禁设备的调试证书
javascript复制// device_config.json
{
"device_type": "door_control",
"device_name": "Entrance_Gate_01",
"distributed_capability": true
}
2.3 项目初始化
创建Flutter项目时需特别注意:
bash复制flutter create --org com.yourdomain community_access
修改pubspec.yaml添加关键依赖:
yaml复制dependencies:
flutter_hms_scan: ^2.8.0 # 华为扫码SDK
dio: ^5.3.3 # 网络请求
provider: ^6.1.1 # 状态管理
flutter_svg: ^2.0.7 # 矢量图支持
3. 门禁功能实现详解
3.1 蓝牙通信模块
门禁控制的核心是通过BLE与OpenHarmony设备通信。实现步骤:
- 扫描设备:
dart复制void _scanDevices() async {
flutterBlue.startScan(timeout: Duration(seconds: 4));
flutterBlue.scanResults.listen((results) {
for (ScanResult r in results) {
if (r.device.name == 'OH_DoorLock_${communityId}') {
_connectDevice(r.device);
}
}
});
}
- 特征值读写:
dart复制const LOCK_SERVICE_UUID = "0000FFE0-0000-1000-8000-00805F9B34FB";
const LOCK_CHARACTERISTIC_UUID = "0000FFE1-0000-1000-8000-00805F9B34FB";
Future<void> _sendCommand(List<int> cmd) async {
await _selectedDevice.writeCharacteristic(
_lockCharacteristic,
cmd,
type: CharacteristicWriteType.withoutResponse
);
}
3.2 安全认证设计
为防止非法开门,实现三级安全机制:
- 用户身份Token验证
- 动态密钥交换(ECDH算法)
- 指令签名(HMAC-SHA256)
关键代码片段:
dart复制String _generateCommandSignature(String cmd) {
final hmac = Hmac(sha256, _sessionKey);
return hmac.convert(utf8.encode(cmd)).toString();
}
3.3 离线模式处理
考虑到地库可能无网络,实现本地缓存机制:
dart复制class OfflineAccess {
static Future<bool> verifyLocal(String userId) async {
final prefs = await SharedPreferences.getInstance();
final lastSync = prefs.getInt('last_sync') ?? 0;
if (DateTime.now().millisecondsSinceEpoch - lastSync > 24*60*60*1000) {
return false; // 超过24小时未同步则禁用
}
return _verifyInLocalDB(userId);
}
}
4. 报修表单系统实现
4.1 表单数据结构设计
使用Firebase作为后端服务(也可替换为其他BaaS):
dart复制class RepairForm {
final String id;
final String userId;
final String category; // 水电/门窗/电梯等
final String description;
final List<String>? images;
final DateTime createTime;
final RepairStatus status;
// 表单验证规则
static final validCategories = [
'plumbing', 'electrical', 'elevator', 'other'
];
bool validate() {
return description.length >= 10
&& validCategories.contains(category);
}
}
4.2 动态表单生成
根据报修类型动态显示不同字段:
dart复制Widget _buildDynamicFields() {
switch (_selectedCategory) {
case 'plumbing':
return Column(
children: [
_buildLocationSelector(),
_buildWaterPressureField(),
],
);
case 'electrical':
return Column(
children: [
_buildCircuitBreakerSwitch(),
_buildVoltageField(),
],
);
default:
return SizedBox();
}
}
4.3 图片上传优化
针对老年用户可能不会压缩图片的问题:
dart复制Future<List<String>> _uploadImages(List<File> files) async {
final compressed = await Future.wait(
files.map((file) => FlutterImageCompress.compressWithFile(
file.path,
minWidth: 1080,
quality: 70,
))
);
return await _storage.uploadAll(compressed);
}
5. 与OpenHarmony设备联调实战
5.1 设备配对流程
- 设备端配置:
javascript复制// OpenHarmony设备代码
import ohos.bluetooth;
const BLE_CONFIG = {
serviceUUID: '0000FFE0-0000-1000-8000-00805F9B34FB',
charUUID: '0000FFE1-0000-1000-8000-00805F9B34FB',
advertiseData: {
deviceName: 'OH_DoorLock_001',
manufacturerData: new Uint8Array([0x01, 0x02]),
}
};
function setupBLEService() {
const server = bluetooth.createGattServer();
server.addService(BLE_CONFIG.serviceUUID, [
{
characteristic: BLE_CONFIG.charUUID,
permissions: bluetooth.GattCharacteristicPermission.READ | bluetooth.GattCharacteristicPermission.WRITE,
properties: bluetooth.GattCharacteristicProperty.WRITE | bluetooth.GattCharacteristicProperty.NOTIFY
}
]);
}
5.2 常见问题排查
-
连接超时问题:
- 检查设备是否开启可发现模式
- 验证Service UUID是否匹配
- 测试RSSI信号强度(建议>-70dBm)
-
指令无响应:
- 确认特征值的writeType设置
- 检查设备端GATT服务是否正常注册
- 使用Wireshark抓包分析BLE通信
-
Android/iOS差异处理:
dart复制Future<void> _connectDevice(BluetoothDevice device) async {
await device.connect(autoConnect: false);
// iOS需要延迟发现服务
if (Platform.isIOS) {
await Future.delayed(Duration(milliseconds: 500));
}
final services = await device.discoverServices();
// ...后续处理
}
6. 性能优化与测试
6.1 启动时间优化
通过Flutter性能工具分析:
bash复制flutter run --profile
flutter build apk --analyze-size
关键优化点:
- 延迟加载非必要插件
- 预编译着色器
- 优化首屏widget树
6.2 压力测试方案
模拟100用户并发场景:
-
使用JMeter构造测试脚本
-
监控指标:
- API响应时间(P99 < 1s)
- 内存占用(<150MB)
- 帧率(>58fps)
-
异常情况测试:
- 弱网切换(使用iOS Network Link Conditioner)
- 低电量模式
- 权限被拒绝场景
7. 实际部署经验
在小区部署时遇到的典型问题:
-
老年用户适配:
- 增加字体缩放功能(最小32sp)
- 录制操作指引视频
- 提供子女远程协助入口
-
设备兼容性问题:
- 部分老旧Android机BLE实现不规范
- iOS后台蓝牙权限限制
- 最终解决方案:
dart复制void _handleConnectionError(error) {
if (error is PlatformException) {
if (error.code == 'timeout') {
_showRetryDialog();
} else if (error.code == 'permission_denied') {
_navigateToSettings();
}
}
}
- 数据统计功能增强:
dart复制class AccessAnalytics {
static void logAccess(String userId) {
final now = DateTime.now();
final hour = now.hour;
// 高峰时段检测
if (hour >= 7 && hour <= 9) {
_checkPeakCapacity();
}
}
static Future<void> _checkPeakCapacity() async {
final count = await _db.getAccessCountLast30min();
if (count > 100) {
_sendCapacityAlert();
}
}
}
整个项目从开发到上线历时3个月,关键收获是:跨平台框架在实际硬件对接场景中,需要特别关注平台特定行为和设备兼容性。下一步计划将门禁功能扩展到电梯控制,并增加人脸识别开门选项。
