diff --git a/star_lock/VERSION.md b/star_lock/VERSION.md new file mode 100644 index 00000000..c6f13291 --- /dev/null +++ b/star_lock/VERSION.md @@ -0,0 +1,45 @@ +# 项目版本管理 +在项目进行过程中,我们遇到过以下场景: +1. 对用户说“你用的包我们没有了,代码已经向前发展了,我们无法提供相同的安装包/另一个平台的该版本安装包” +2. 对用户说“功能有问题?我也不清楚你是不是版本太老了,要不你直接升级到最新版吧“ +3. ”什么?X.X.X版本有XX问题?我不知道这个问题好像已经修复了啊,要不你升级最新版试试“ +4. 用户并不是总能升级到最新版、例如新版本引入了某个功能带来新的问题,我们需要在特定版本修复特定问题。 +5. 例如对于应用商店,当我提交审核1.1.1版本,那么我将会根据反馈修复问题,而此时主分支已经进化到1.2.0版本引入了更多的功能,我现在并不像将1.2的新增功能提交测试,我需要继续在1.0版本修复一些问题。(别想着这是应用商店,用户也是如此,例如你交付给某个客户进行测试,双方都不会想在测试-修复的循环中不断引入新功能【新问题】) + +为了避免以上情况,我们必须对项目进行规范的版本管理。 +具体来说,任何和内部协同,外部交付的构建,必须遵循此文档的规范。 + +## 分支管理 +目前没有进行工作流分支管理,所有的开发都在`master`分支上进行。 + +在构建时需要拉出新分支来区分构建的版本的代码。具体来讲,当你现在需要构建,你需要进行如下操作: +1. 按规则修改pubspec.yaml中的版本号,并添加对应的版本说明记录 +2. 在master分支,提交并push代码 +3. 在master拉出新分支,例如`build-1.0.18+2024032002`,其中的`1.0.18+2024032002`是你刚新增的版本 +4. 在新分支构建 +5. 如果构建过程需要修改代码,提交在build-xx分支而不是master分支 +6. 构建完成后,如有必要可以合并到master分支,保留build-xx分支已备后续可以再次构建此版本的其他构建平台或构建方式 +7. 构建完成后,记得切换回master分支 + +## 版本号 +项目版本号遵循flutter规范,即`major.minor.patch+build`,例如`1.0.0+1`。 +其中的构建号必须在每一次构建都进行递增,具体的规则是年月日二位自增,例如`2024032701`。 + +前面的版本号是由项目的业务需求决定的,例如`1.0.0`,`1.0.1`,`1.1.0`等。 + +具体来说,`major`是大版本号,`minor`是小版本号,`patch`是修订号 + +其中大版本号必须是完全不兼容的更新才可以使用,脱胎换骨,浴火重生级别的。 + +小版本号是功能差异,不一定完全兼容,用户可能需要升级否则无法使用某个功能, +例如增加了一个新功能,或者修改了一个已有的功能。 + +修订号是修复bug,或者优化性能,或者修改了一些细节,但是不影响用户使用的。 + +## 构建物文件名 + +无论分发到什么渠道,通过自行发布页面或者通过即时通讯工具传递安装包,都必须使用规范的文件名以避免混淆。 + +文件名的格式为:`app-sky-64-release-VersionCode.apk` + +其中`sky`是渠道名,`64`是CPU架构,`release`是构建类型,`VersionCode`是版本号。 diff --git a/star_lock/android/app/build.gradle b/star_lock/android/app/build.gradle index 8dc22d6e..89e4ce38 100644 --- a/star_lock/android/app/build.gradle +++ b/star_lock/android/app/build.gradle @@ -143,7 +143,12 @@ android { // 但是禁用NDK配置,又无法使用flutter run 命令了,因为编译完成它按照名称匹配找不到.apk包 ndk { //设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so) - abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64" +// abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64" + + + // 参考魅族平台的公告,得知在2023年1月商店就可以只需要64位应用即可 + // 这说明32位是很老很老的平台,我们的flutter或者说我们的项目本来就兼容不了老平台,架构兼容也没必要 + abiFilters "arm64-v8a" } manifestPlaceholders = [ @@ -161,10 +166,11 @@ android { abi { enable true reset() - // x86_64,x86,armeabi-v7a,armeabi,arm64-v8a - // x86_64,x86,armeabi-v7a,armeabi,arm64-v8a - include "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64" - universalApk true + // 参考魅族平台的公告,得知在2023年1月商店就可以只需要64位应用即可 + // 这说明32位是很老很老的平台,我们的flutter或者说我们的项目本来就兼容不了老平台,架构兼容也没必要 +// include "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64" +// include "arm64-v8a" + universalApk false } } } diff --git a/star_lock/android/app/src/main/AndroidManifest.xml b/star_lock/android/app/src/main/AndroidManifest.xml index e33b4192..8ebd4ddc 100644 --- a/star_lock/android/app/src/main/AndroidManifest.xml +++ b/star_lock/android/app/src/main/AndroidManifest.xml @@ -29,6 +29,7 @@ + @@ -37,6 +38,9 @@ + diff --git a/star_lock/android/app/src/main/res/drawable/app_icon.png b/star_lock/android/app/src/main/res/drawable/app_icon.png new file mode 100644 index 00000000..20f2a164 Binary files /dev/null and b/star_lock/android/app/src/main/res/drawable/app_icon.png differ diff --git a/star_lock/lib/common/XSConstantMacro/XSConstantMacro.dart b/star_lock/lib/common/XSConstantMacro/XSConstantMacro.dart index 60b9b31e..f66cb8a3 100644 --- a/star_lock/lib/common/XSConstantMacro/XSConstantMacro.dart +++ b/star_lock/lib/common/XSConstantMacro/XSConstantMacro.dart @@ -26,16 +26,16 @@ class XSConstantMacro { // "110412" 已过期 // "110408" 已删除 // "110410" 已重置 - static int keyStatusNormalUse = 110401; // 正常使用 - static int keyStatusWaitReceive = 110402; // 待接收 + static int keyStatusNormalUse = 110401; // 正常使用 + static int keyStatusWaitReceive = 110402; // 待接收 static int keyStatusWaitIneffective = 110403; // 待生效 - static int keyStatusFrozen = 110405; // 已冻结 - static int keyStatusExpired = 110412; // 已过期 - static int keyStatusDeleted = 110408; // 已删除 - static int keyStatusReset = 110410; // 已重置 + static int keyStatusFrozen = 110405; // 已冻结 + static int keyStatusExpired = 110412; // 已过期 + static int keyStatusDeleted = 110408; // 已删除 + static int keyStatusReset = 110410; // 已重置 - static String getKeyStatusStr(int keyStatus){ - switch(keyStatus){ + static String getKeyStatusStr(int keyStatus) { + switch (keyStatus) { case 110401: // 正常使用 return ""; @@ -55,10 +55,17 @@ class XSConstantMacro { return "未知"; } } + // 门锁事件类型 lockEventType 事件类型:0-全部事件;10-开门事件20-异常事件30-门铃事件40-视频事件 static int lockEventTypeAll = 0; static int lockEventTypeOpenDoor = 10; static int lockEventTypeAbnormal = 20; static int lockEventTypeDoorbell = 30; static int lockEventTypeVideo = 40; + + //猫眼工作模式 + static int catEyeWorkModePowerSaving = 1; //省电模式 + static int catEyeWorkModeStayCapture = 2; //逗留抓拍模式 + static int catEyeWorkModeRealTimeMonitoring = 3; //实时监控模式 + static int catEyeWorkModeCustom = 4; //自定义模式 } diff --git a/star_lock/lib/flavors.dart b/star_lock/lib/flavors.dart index 39d9a0f2..7eda6066 100644 --- a/star_lock/lib/flavors.dart +++ b/star_lock/lib/flavors.dart @@ -16,6 +16,8 @@ class StarLockAMapKey { class F { static Flavor? appFlavor; + // 是否为精简模式(在一些应用商店场景下,需要精简掉一些功能) + static bool isLite = false; static String get name => appFlavor?.name ?? ''; diff --git a/star_lock/lib/login/login/starLock_login_page.dart b/star_lock/lib/login/login/starLock_login_page.dart index 579b9b98..76708589 100644 --- a/star_lock/lib/login/login/starLock_login_page.dart +++ b/star_lock/lib/login/login/starLock_login_page.dart @@ -207,8 +207,7 @@ class _StarLockLoginPageState extends State { child: SizedBox( width: 10.sp, )), - //上架审核注释 提交Google暂时屏蔽 - F.appFlavor == Flavor.sky + F.isLite ? Container() : GestureDetector( child: SizedBox( diff --git a/star_lock/lib/main.dart b/star_lock/lib/main.dart index 652ef00a..a32db23e 100644 --- a/star_lock/lib/main.dart +++ b/star_lock/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/translations/trans_lib.dart'; import 'app.dart'; @@ -17,6 +18,8 @@ FutureOr main() async { // 设置国际化信息 await _initTranslation(); + initLocalNotification(); + runApp(MyApp()); if (AppPlatform.isAndroid) { @@ -37,7 +40,7 @@ Future _initTranslation() async => TranslationLoader.loadTranslation( Future _setCommonServices() async { await Get.putAsync(() => StoreService().init()); await Get.putAsync(() => PlatformInfoService().init()); - if (F.appFlavor == Flavor.sky) { + if (F.isLite) { //上架审核注释 获取设备信息 // await Get.putAsync(() => DeviceInfoService().init()); } else { @@ -45,3 +48,14 @@ Future _setCommonServices() async { } // Get.log(PlatformInfoService.to.info.version); } + +initLocalNotification() async { + WidgetsFlutterBinding.ensureInitialized(); + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('app_icon'); + const InitializationSettings initializationSettings = + InitializationSettings(android: initializationSettingsAndroid); + await flutterLocalNotificationsPlugin.initialize(initializationSettings); +} diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 8b7034ec..f04bcb3a 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -744,6 +744,7 @@ class LockDetailLogic extends BaseGetXController { // 3 修改了锁名字 state.lockAlias.value = event.setResult; state.keyInfos.value.lockAlias = event.setResult; + Storage.setString(saveLockAlias, state.lockAlias.value); } else if (event.type == 4) { // 4 更新了电量 state.electricQuantity.value = int.parse(event.setResult); diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart index 131bfe68..9cee013e 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -109,6 +109,7 @@ class _LockDetailPageState extends State state.electricQuantity.value = state.keyInfos.value.electricQuantity!; state.isOpenPassageMode.value = state.keyInfos.value.passageMode!; state.lockAlias.value = state.keyInfos.value.lockAlias!; + Storage.setString(saveLockAlias, state.lockAlias.value); BlueManage().connectDeviceName = state.keyInfos.value.bluetooth!.bluetoothDeviceName!; @@ -178,7 +179,7 @@ class _LockDetailPageState extends State SizedBox( height: 10.h, ), - buildPageIndicator(), + Obx(() => buildPageIndicator()), Expanded( child: Container( margin: EdgeInsets.only(left: 10.w, right: 10.w, top: 30.h), @@ -992,7 +993,8 @@ class _LockDetailPageState extends State state.closedUnlockSuccessfulTimer?.cancel(); _lockRefreshLockDetailInfoDataEvent?.cancel(); state.replySubscription.cancel(); - state.lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent!.cancel(); + state.lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent! + .cancel(); if (state.animationController != null) { state.animationController!.dispose(); diff --git a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart index 42f67ac1..542f134d 100644 --- a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart +++ b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart @@ -1,7 +1,53 @@ +import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'catEyeSet_state.dart'; class CatEyeSetLogic extends BaseGetXController { final CatEyeSetState state = CatEyeSetState(); + +//设置自动亮屏 + void updateAutoLightScreenConfig() async { + var entity = await ApiRepository.to.updateAutoLightScreenConfig( + lockId: state.lockSetInfoData.value.lockId!, + autoLightScreen: state.isAutoBright.value == true ? 1 : 0, + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast('设置成功'); + } + } + + //设置自动亮屏 + void updateLightScreenTimeConfig() async { + var entity = await ApiRepository.to.updateLightScreenTimeConfig( + lockId: state.lockSetInfoData.value.lockId!, + autoLightScreenTime: + int.parse(state.selectBrightDuration.value.replaceAll('秒', '')), + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast('设置成功'); + } + } + + //设置逗留警告 + void updateStayWarnConfig() async { + var entity = await ApiRepository.to.updateStayWarnConfig( + lockId: state.lockSetInfoData.value.lockId!, + stayWarn: state.isStayWarning.value == true ? 1 : 0, + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast('设置成功'); + } + } + + //设置异常警告 + void updateAbnormalWarnConfig() async { + var entity = await ApiRepository.to.updateAbnormalWarnConfig( + lockId: state.lockSetInfoData.value.lockId!, + abnormalWarn: state.isExceptionWarning.value == true ? 1 : 0, + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast('设置成功'); + } + } } diff --git a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart index ce771065..4887adda 100644 --- a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart +++ b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart @@ -33,12 +33,18 @@ class _CatEyeSetPageState extends State { children: [ CommonItem( leftTitel: '猫眼工作模式', - rightTitle: "", + rightTitle: state.selectCatEyeWorkMode.value, allHeight: 70.h, isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.catEyeWorkModePage); + Get.toNamed(Routers.catEyeWorkModePage, arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + })?.then((value) { + if (value != null) { + state.selectCatEyeWorkMode.value = value; + } + }); }), Obx(() => CommonItem( leftTitel: '自动亮屏', @@ -94,15 +100,26 @@ class _CatEyeSetPageState extends State { onChanged: (value) { switch (clickIndex) { case 1: //自动亮屏 - state.isAutoBright.value = value; + { + state.isAutoBright.value = value; + logic.updateAutoLightScreenConfig(); + } break; case 2: //逗留警告 - state.isStayWarning.value = value; + { + state.isStayWarning.value = value; + logic.updateStayWarnConfig(); + } break; case 3: //异常警告 - state.isExceptionWarning.value = value; + { + state.isExceptionWarning.value = value; + logic.updateAbnormalWarnConfig(); + } break; default: + print('clickIndex is not match'); + break; } }, ); @@ -120,6 +137,7 @@ class _CatEyeSetPageState extends State { chooseCallback: (value) { state.selectBrightDuration.value = state.brightDurationTimeList[value]; + logic.updateLightScreenTimeConfig(); }, ); }); diff --git a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_state.dart b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_state.dart index 9fb26f65..d60fc960 100644 --- a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_state.dart +++ b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_state.dart @@ -1,4 +1,5 @@ import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; class CatEyeSetState { var brightDurationTimeList = ['10秒', '15秒', '20秒'].obs; @@ -6,4 +7,11 @@ class CatEyeSetState { var isAutoBright = false.obs; //自动亮屏 var isStayWarning = false.obs; //逗留警告 var isExceptionWarning = false.obs; //异常警告 + var lockSetInfoData = LockSetInfoData().obs; + var selectCatEyeWorkMode = ''.obs; //猫眼工作模式 + + CatEyeSetState() { + Map map = Get.arguments; + lockSetInfoData.value = map["lockSetInfoData"]; + } } diff --git a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart new file mode 100644 index 00000000..22af4d71 --- /dev/null +++ b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart @@ -0,0 +1,27 @@ +import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class CatEyeWorkModeLogic extends BaseGetXController { + final CatEyeWorkModeState state = CatEyeWorkModeState(); + +//设置猫眼工作模式 + void updateCatEyeModeConfig() async { + var entity = await ApiRepository.to.updateCatEyeModeConfig( + lockId: state.lockSetInfoData.value.lockId!, + catEyeConfig: { + 'catEyeMode': state.selectCatEyeWorkMode.value, + 'catEyeModeConfig': { + 'recordMode': state.recordMode.value, + 'recordStartTime': state.recordStartTime.value, + 'recordEndTime': state.recordEndTime.value, + 'detectionDistance': state.detectionDistance.value, + 'realTimeMode': state.realTimeMode.value, + } + }, + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast('设置成功'); + } + } +} diff --git a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_page.dart b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_page.dart index 2dd8478c..ee44fae7 100644 --- a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_page.dart +++ b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_page.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; +import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart'; import '../../../../../app_settings/app_colors.dart'; import '../../../../../tools/titleAppBar.dart'; @@ -14,8 +16,8 @@ class CatEyeWorkModePage extends StatefulWidget { } class _CatEyeWorkModePageState extends State { - bool isCheck = false; - List boolList = [true, false, false, false]; + final logic = Get.put(CatEyeWorkModeLogic()); + final state = Get.find().state; @override Widget build(BuildContext context) { @@ -30,44 +32,34 @@ class _CatEyeWorkModePageState extends State { SizedBox( height: 30.h, ), - _buildTipsView( - '省电模式:\n', - '适合门口较为安全的环境。\n仅发生特定事件才录像,并可查看实时画面。\n一般情况下,满电可使用7-8个月', - 0, - boolList[0]), + _buildTipsView('省电模式:\n', + '适合门口较为安全的环境。\n仅发生特定事件才录像,并可查看实时画面。\n一般情况下,满电可使用7-8个月', 0), + SizedBox( + height: 30.h, + ), + _buildTipsView('逗留抓拍模式:\n', + '有人逗留或发生特定事件才录像,可随时查看\n实时画面。\n一般情况下,满电可使用5~6个月。', 1), + SizedBox( + height: 30.h, + ), + _buildTipsView('实时监控模式:\n', + '适合门口人员复杂、较不安全的环境。\n有人出现就录像,可随时查看实时画面。\n一般情况下,满电可使用2~4个月。', 2), SizedBox( height: 30.h, ), _buildTipsView( - '逗留抓拍模式:\n', - '有人逗留或发生特定事件才录像,可随时查看\n实时画面。\n一般情况下,满电可使用5~6个月。', - 1, - boolList[1]), - SizedBox( - height: 30.h, - ), - _buildTipsView( - '实时监控模式:\n', - '适合门口人员复杂、较不安全的环境。\n有人出现就录像,可随时查看实时画面。\n一般情况下,满电可使用2~4个月。', - 2, - boolList[2]), - SizedBox( - height: 30.h, - ), - _buildTipsView('自定义模式:\n', '根据您家门口实际情况设置录像和实时画面功能。\n可使用时长由具体设置决定。', - 3, boolList[3]) + '自定义模式:\n', '根据您家门口实际情况设置录像和实时画面功能。\n可使用时长由具体设置决定。', 3) ], )); } - Widget _buildTipsView( - String titleStr, String subTitle, int clickIndex, bool isClick) { + Widget _buildTipsView(String titleStr, String subTitle, int clickIndex) { return GestureDetector( child: Container( width: ScreenUtil().screenWidth - 40.w, margin: EdgeInsets.only(left: 20.w, right: 20.w, bottom: 10.h), decoration: BoxDecoration( - color: isClick + color: state.boolList.value[clickIndex] ? AppColors.blueViewBgColor : AppColors.greyBackgroundColor, borderRadius: BorderRadius.circular(10.0), @@ -77,7 +69,7 @@ class _CatEyeWorkModePageState extends State { left: 20.w, top: 30.h, bottom: 30.h, right: 20.w), child: Row( children: [ - isClick + state.boolList.value[clickIndex] ? Image.asset( 'images/mine/icon_mine_blueSelect.png', width: 20.w, @@ -89,7 +81,8 @@ class _CatEyeWorkModePageState extends State { ), SizedBox(width: 10.w), Expanded( - child: _buildRichText(titleStr, subTitle, isClick), + child: _buildRichText( + titleStr, subTitle, state.boolList.value[clickIndex]), ), SizedBox( width: 10.w, @@ -128,11 +121,30 @@ class _CatEyeWorkModePageState extends State { ), onTap: () { setState(() { - for (int i = 0; i < boolList.length; i++) { + for (int i = 0; i < state.boolList.value.length; i++) { if (clickIndex == i) { - boolList[clickIndex] = true; + state.boolList.value[clickIndex] = true; + switch (clickIndex) { + case 0: + state.selectCatEyeWorkMode.value = + XSConstantMacro.catEyeWorkModePowerSaving; + break; + case 1: + state.selectCatEyeWorkMode.value = + XSConstantMacro.catEyeWorkModeStayCapture; + break; + case 2: + state.selectCatEyeWorkMode.value = + XSConstantMacro.catEyeWorkModeRealTimeMonitoring; + break; + case 3: + state.selectCatEyeWorkMode.value = + XSConstantMacro.catEyeWorkModeCustom; + break; + } + logic.updateCatEyeModeConfig(); } else { - boolList[i] = false; + state.boolList.value[i] = false; } } }); diff --git a/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart new file mode 100644 index 00000000..74cbeb03 --- /dev/null +++ b/star_lock/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart @@ -0,0 +1,20 @@ +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; + +class CatEyeWorkModeState { + var lockSetInfoData = LockSetInfoData().obs; + var selectCatEyeWorkMode = 0.obs; //猫眼工作模式 + var boolList = [true, false, false, false].obs; + var recordMode = 0.obs; //录像时段 0全天 1自定义时间 + //自定义时间需要填:recordStartTime与recordEndTime参数 + var recordStartTime = 0.obs; // 1709715049775, + var recordEndTime = 0.obs; //1709715049775, + var recordTime = 0.obs; //有人出现时录像 + var detectionDistance = 0.obs; //人体侦测距离 + var realTimeMode = 0.obs; //实时画面 0发生事件事查看 1实时查看 + + CatEyeWorkModeState() { + Map map = Get.arguments; + lockSetInfoData.value = map["lockSetInfoData"]; + } +} diff --git a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index 658f797d..1099927f 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -299,7 +299,7 @@ class _LockSetPageState extends State with RouteAware { // 常开模式 Obx(() => Visibility( visible: state.lockFeature.value.passageMode == 1 ? true : false, - // visible: true, + // visible: true, child: CommonItem( leftTitel: TranslationLoader.lanKeys!.normallyOpenMode!.tr, rightTitle: (state.lockSettingInfo.value.passageMode ?? 0) == 1 @@ -380,7 +380,9 @@ class _LockSetPageState extends State with RouteAware { isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.catEyeSetPage); + Get.toNamed(Routers.catEyeSetPage, arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); })), // Obx(() => //自动亮屏已包括至面容开锁模块 diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart index 9b83b752..337787c2 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:math'; import 'package:flutter/services.dart'; @@ -7,6 +6,7 @@ import 'package:flutter_voice_processor/flutter_voice_processor.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/talk/call/callTalk.dart'; +import 'package:star_lock/talk/udp/udp_talkClass.dart'; import '../../../../talk/call/g711.dart'; import '../../../../talk/udp/udp_manage.dart'; @@ -33,7 +33,7 @@ class LockMonitoringLogic extends BaseGetXController { // 预加载图片数据 Uint8List imageData = Uint8List.fromList(event.tvList); // 更新状态 - state.listData.value = imageData; + state.listPhotoData.value = imageData; } }); } @@ -42,40 +42,59 @@ class LockMonitoringLogic extends BaseGetXController { StreamSubscription? _getUDPStatusRefreshUIEvent; void _getUDPStatusRefreshUIAction() { _getUDPStatusRefreshUIEvent = - eventBus.on().listen((event) { + eventBus.on().listen((event) async { state.udpStatus.value = event.udpStatus; - if (state.udpStatus.value == 8) { - // 接听成功了,然后刷新界面的时间 60秒以后自动挂断 - state.oneMinuteTimeTimer = - Timer.periodic(const Duration(seconds: 1), (Timer t) async { - state.oneMinuteTime.value++; - // Get.log('state.oneMinuteTime.value:${state.oneMinuteTime.value}'); - if (state.oneMinuteTime.value >= 60) { - // 超过60秒了 - state.oneMinuteTimeTimer.cancel(); - state.oneMinuteTime.value = 0; - // 挂断 - UDPSenderManage.sendMainProtocol( - command: 150, - commandTypeIsCalling: 1, - subCommand: 30, - lockID: UDPManage().lockId, - lockIP: UDPManage().host, - userMobile: await state.userUid, - userMobileIP: await state.userMobileIP, - endData: []); + state.oneMinuteTime.value = 0; - CallTalk().stopPcmSound(); - // 关闭当前界面 - Get.back(); + // 如果已经挂断,则取消定时器并退出 + if (state.udpStatus.value == 0 && UDPTalkClass().isEndCall == true) { + state.oneMinuteTimeTimer.cancel(); + state.oneMinuteTime.value = 0; + return; + } + + // 如果是接听状态,则启动定时器更新通话时间 + if (state.udpStatus.value == 8) { + state.oneMinuteTimeTimer.cancel(); // 取消旧定时器 + state.oneMinuteTimeTimer = + Timer.periodic(const Duration(seconds: 1), (Timer t) { + state.oneMinuteTime.value++; + if (state.oneMinuteTime.value >= 60) { + t.cancel(); // 取消定时器 + initiateUdpHangUpAction(); // 挂断操作 + print('通话时间超过60秒,自动挂断'); + state.oneMinuteTime.value = 0; } }); } }); } + //发起接听命令,每隔一秒钟发一次,六秒无应答则失败 + void initiateUdpAnswerAction() { + state.answerTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + udpAnswerAction(); + state.answerSeconds++; + + //如果接听成功,取消定时器;接听失败,继续发接听命令 + if (UDPTalkClass().status == 8) { + state.answerTimer.cancel(); // 取消定时器 + return; + } + + // 检查条件,如果达到6秒且未得到应答,则认为失败 + if (state.answerSeconds >= 6) { + state.answerTimer.cancel(); + showToast("接听失败"); + initiateUdpHangUpAction(); + // UDPTalkClass().callNoAnswer(); + } + }); + } + /// 接听 udpAnswerAction() async { + print('点了接听么'); UDPSenderManage.sendMainProtocol( command: 150, commandTypeIsCalling: 1, @@ -87,6 +106,27 @@ class LockMonitoringLogic extends BaseGetXController { endData: []); } + //发起挂断命令,每隔一秒钟发一次,六秒无应答则失败 + void initiateUdpHangUpAction() { + // 每隔一秒调用一次 udpHangUpAction 方法 + state.hangUpTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + state.hangUpSeconds++; + udpHangUpAction(); + + //如果已经挂断成功,则取消定时器 + if (UDPTalkClass().isEndCall == true) { + state.hangUpTimer.cancel(); + return; + } + + // 检查条件,如果达到6秒且未得到应答,则认为失败 + if (state.hangUpSeconds >= 6) { + state.hangUpTimer.cancel(); // 取消定时器 + UDPTalkClass().callNoAnswer(); + } + }); + } + /// 挂断 udpHangUpAction() async { UDPSenderManage.sendMainProtocol( @@ -100,6 +140,20 @@ class LockMonitoringLogic extends BaseGetXController { endData: []); } + //发起开门命令,每隔一秒钟发一次,六秒无应答则失败 + void initiateUdpOpenDoorAction(List list) { + // 每隔一秒调用一次 udpOpenDoorAction 方法 + state.openDoorTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + state.openDoorSeconds++; + udpOpenDoorAction(list); + + // 检查条件,如果达到6秒且未得到应答,则认为失败 + if (state.openDoorSeconds >= 6) { + state.openDoorTimer.cancel(); // 取消定时器 + } + }); + } + /// 开门 udpOpenDoorAction(List list) async { UDPSenderManage.sendMainProtocol( @@ -406,6 +460,6 @@ class LockMonitoringLogic extends BaseGetXController { state.oneMinuteTimeTimer.cancel(); } stopProcessing(); - state.listData.value = Uint8List(0); + state.listPhotoData.value = Uint8List(0); } } diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart index cd3a7164..c5318826 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart @@ -1,8 +1,11 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/talk/call/callTalk.dart'; +import 'package:star_lock/talk/udp/udp_talkClass.dart'; import '../../../../app_settings/app_colors.dart'; import '../../../../login/selectCountryRegion/common/index.dart'; @@ -23,8 +26,11 @@ class _LockMonitoringPageState extends State { @override void initState() { super.initState(); + initAsync(); + } - requestMicrophonePermission(); + Future initAsync() async { + await requestMicrophonePermission(); } @override @@ -34,16 +40,23 @@ class _LockMonitoringPageState extends State { height: 1.sh, child: Stack( children: [ - Obx(() => state.listData.value.isEmpty - ? Container(color: Colors.transparent) - : Image.memory( - state.listData.value, - // key: ValueKey(state.listData.value.hashCode), - gaplessPlayback: true, - width: 1.sw, - height: 1.sh, - fit: BoxFit.cover, - )), + Obx(() { + if (state.listPhotoData.value.isEmpty || + state.listPhotoData.value.length < 10) { + return Container(color: Colors.transparent); + } else { + return Image.memory( + state.listPhotoData.value, + gaplessPlayback: true, + width: 1.sw, + height: 1.sh, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Container(color: Colors.transparent); + }, + ); + } + }), Positioned( top: ScreenUtil().statusBarHeight + 30.h, width: 1.sw, @@ -163,8 +176,15 @@ class _LockMonitoringPageState extends State { return Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // 接听 Obx(() => bottomBtnItemWidget( - getAnswerBtnImg(), getAnswerBtnName(), Colors.white, () async { - logic.udpAnswerAction(); + state.isClickAnswer.value == true + ? 'images/main/icon_lockDetail_monitoringUnTalkback.png' + : getAnswerBtnImg(), + state.isClickAnswer.value == true ? '长按说话' : getAnswerBtnName(), + Colors.white, () async { + if (state.isClickAnswer.value == false) { + logic.initiateUdpAnswerAction(); + state.isClickAnswer.value = true; + } }, longPress: () { // 开始长按 print("onLongPress"); @@ -186,7 +206,15 @@ class _LockMonitoringPageState extends State { logic.stopProcessing(); CallTalk().stopPcmSound(); // 挂断 - logic.udpHangUpAction(); + if (state.isClickHangUp.value == false) { + logic.initiateUdpHangUpAction(); + state.isClickHangUp.value = true; + } else { + print('点了这里?'); + state.isClickHangUp.value = false; + UDPTalkClass().stopLocalAudio(); + logic.udpHangUpAction(); + } }), bottomBtnItemWidget("images/main/icon_lockDetail_monitoringUnlock.png", "开锁", AppColors.mainColor, () { @@ -298,7 +326,7 @@ class _LockMonitoringPageState extends State { } // state.isSenderAudioData.value = false; - print("发送接听了"); + // print("发送接听了"); // 刚进来是接听状态,然后改为长按对讲 }); } diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart index 0aa6ca7a..115baf05 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart @@ -10,16 +10,17 @@ import '../../../../tools/storage.dart'; class LockMonitoringState { var isOpenVoice = false.obs; - var udpSendDataFrameNumber = 0;// 帧序号 + var udpSendDataFrameNumber = 0; // 帧序号 // var isSenderAudioData = false.obs;// 是否要发送音频数据 var userMobileIP = NetworkInfo().getWifiIP(); var userUid = Storage.getUid(); - var udpStatus = 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话 + var udpStatus = + 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话 var passwordTF = TextEditingController(); - var listData = Uint8List(0).obs; //得到的视频流字节数据 + var listPhotoData = Uint8List(0).obs; //得到的视频流字节数据 var listAudioData = [].obs; //得到的音频流字节数据 late final VoiceProcessor? voiceProcessor; @@ -29,7 +30,14 @@ class LockMonitoringState { var oneMinuteTime = 0.obs; // 定时器秒数 // 定时器如果发送了接听的命令 而没收到回复就每秒重复发送10次 - late Timer answerTimer; - late Timer hangUpTimer; - late Timer openDoorTimer; + late Timer answerTimer = Timer(const Duration(seconds: 1), () {}); //接听命令定时器 + var answerSeconds = 0.obs; + var isClickAnswer = false.obs; //是否点击了接听按钮 + + late Timer hangUpTimer = Timer(const Duration(seconds: 1), () {}); //挂断命令定时器 + var hangUpSeconds = 0.obs; + var isClickHangUp = false.obs; //是否点击了挂断按钮 + + late Timer openDoorTimer = Timer(const Duration(seconds: 1), () {}); //开门命令定时器 + var openDoorSeconds = 0.obs; } diff --git a/star_lock/lib/main/lockMian/lockMain/lockMain_page.dart b/star_lock/lib/main/lockMian/lockMain/lockMain_page.dart index 2094997e..f75b807f 100644 --- a/star_lock/lib/main/lockMian/lockMain/lockMain_page.dart +++ b/star_lock/lib/main/lockMian/lockMain/lockMain_page.dart @@ -215,8 +215,7 @@ class _StarLockMainPageState extends State with BaseWidget { SizedBox( height: 160.h, ), - //上架审核注释 提交Google暂时屏蔽 - F.appFlavor == Flavor.sky + F.isLite ? Container() : SubmitBtn( btnName: '演示模式', diff --git a/star_lock/lib/main_sky.dart b/star_lock/lib/main_sky_full.dart similarity index 100% rename from star_lock/lib/main_sky.dart rename to star_lock/lib/main_sky_full.dart diff --git a/star_lock/lib/main_sky_lite.dart b/star_lock/lib/main_sky_lite.dart new file mode 100644 index 00000000..3c0a2b0b --- /dev/null +++ b/star_lock/lib/main_sky_lite.dart @@ -0,0 +1,9 @@ +import 'flavors.dart'; + +import 'main.dart' as runner; + +Future main() async { + F.appFlavor = Flavor.sky; + F.isLite = true; + await runner.main(); +} diff --git a/star_lock/lib/mine/mine/starLockMine_page.dart b/star_lock/lib/mine/mine/starLockMine_page.dart index 020c8953..d8d14814 100644 --- a/star_lock/lib/mine/mine/starLockMine_page.dart +++ b/star_lock/lib/mine/mine/starLockMine_page.dart @@ -146,14 +146,14 @@ class StarLockMinePageState extends State with BaseWidget { Get.toNamed(Routers.mineSetPage); }), //上架审核 - F.appFlavor == Flavor.sky + F.isLite ? Container() : mineItem('images/mine/icon_mine_main_vip.png', TranslationLoader.lanKeys!.valueAddedServices!.tr, () { Get.back(); Get.toNamed(Routers.valueAddedServicesPage); }), - F.appFlavor == Flavor.sky + F.isLite ? Container() : mineItem( 'images/mine/icon_mine_main_shoppingcart.png', "配件商城".tr, () { diff --git a/star_lock/lib/mine/mineSet/mineSet/mineSet_page.dart b/star_lock/lib/mine/mineSet/mineSet/mineSet_page.dart index 09d702d0..899022bb 100644 --- a/star_lock/lib/mine/mineSet/mineSet/mineSet_page.dart +++ b/star_lock/lib/mine/mineSet/mineSet/mineSet_page.dart @@ -204,7 +204,7 @@ class _MineSetPageState extends State with WidgetsBindingObserver { height: 10.h, ), //上架审核注释 - F.appFlavor == Flavor.sky + F.isLite ? Container() : CommonItem( leftTitel: "Amazon Alexa", @@ -214,7 +214,7 @@ class _MineSetPageState extends State with WidgetsBindingObserver { action: () { logic.showToast("功能暂未开放"); }), - F.appFlavor == Flavor.sky + F.isLite ? Container() : CommonItem( leftTitel: "Google Home", @@ -224,7 +224,7 @@ class _MineSetPageState extends State with WidgetsBindingObserver { action: () { logic.showToast("功能暂未开放"); }), - F.appFlavor == Flavor.sky + F.isLite ? Container() : CommonItem( leftTitel: TranslationLoader.lanKeys!.xiaomiIOTPlatform!.tr, diff --git a/star_lock/lib/network/api.dart b/star_lock/lib/network/api.dart index 7b933b14..b9f99203 100644 --- a/star_lock/lib/network/api.dart +++ b/star_lock/lib/network/api.dart @@ -180,4 +180,7 @@ abstract class Api { final String deletMessageURL = '/notifications/delete'; //删除消息 final String getVersionURL = '/app/getVersion'; //版本更新 + + final String updateCatEyeConfigURL = + '/lockSetting/updateCatEyeConfig'; //设置猫眼工作模式 } diff --git a/star_lock/lib/network/api_provider.dart b/star_lock/lib/network/api_provider.dart index 94305b93..337fc2b1 100644 --- a/star_lock/lib/network/api_provider.dart +++ b/star_lock/lib/network/api_provider.dart @@ -204,8 +204,17 @@ class ApiProvider extends BaseProvider { 'operatorUid': operatorUid, })); - Future updateKeyDate(String keyId, String lockId, String endDate, - String startDate, List weekDays, int keyType, int startTime, int endTime, int isOnlyManageSelf, int remoteEnable) => + Future updateKeyDate( + String keyId, + String lockId, + String endDate, + String startDate, + List weekDays, + int keyType, + int startTime, + int endTime, + int isOnlyManageSelf, + int remoteEnable) => post( updateKeyDateURL.toUrl, jsonEncode({ @@ -226,22 +235,20 @@ class ApiProvider extends BaseProvider { jsonEncode({'lockId': lockId, 'operatorUid': operatorUid})); Future lockRecordList( - { - required String endDate, - required String keyId, - required String keyStatus, - required String lockId, - required String operatorUid, - required String pageNo, - required String pageSize, - required String startDate, - required String recordType, - required String searchStr, - required String timezoneRawOffSet, - required String keyboardPwdId, - required String cardId, - required String fingerprintId - }) => + {required String endDate, + required String keyId, + required String keyStatus, + required String lockId, + required String operatorUid, + required String pageNo, + required String pageSize, + required String startDate, + required String recordType, + required String searchStr, + required String timezoneRawOffSet, + required String keyboardPwdId, + required String cardId, + required String fingerprintId}) => post( keyOperationRecordURL.toUrl, jsonEncode({ @@ -364,9 +371,15 @@ class ApiProvider extends BaseProvider { })); // 删除拥有的当前钥匙 - Future deletOwnerKeyInfo(String lockId, String keyId, int includeUnderlings) => post( - deleteElectronicKeyURL.toUrl, - jsonEncode({'lockId': lockId, 'keyId': keyId, 'includeUnderlings': includeUnderlings})); + Future deletOwnerKeyInfo( + String lockId, String keyId, int includeUnderlings) => + post( + deleteElectronicKeyURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'keyId': keyId, + 'includeUnderlings': includeUnderlings + })); // 检查账户密码 Future checkLoginPassword(String password) => post( @@ -515,7 +528,8 @@ class ApiProvider extends BaseProvider { setAppUnlockMustOnlineURL.toUrl, jsonEncode({'lockIdList': lockIdList})); Future deleteElectronicKey(String keyId, int includeUnderlings) => - post(deleteElectronicKeyURL.toUrl, + post( + deleteElectronicKeyURL.toUrl, jsonEncode({ 'keyId': keyId, 'includeUnderlings': includeUnderlings, @@ -538,40 +552,39 @@ class ApiProvider extends BaseProvider { })); // 设置授权管理员 - Future setAdministrator(String keyId) => - post(setAuthorizeURL.toUrl, - jsonEncode({ - 'keyId': keyId, - })); + Future setAdministrator(String keyId) => post( + setAuthorizeURL.toUrl, + jsonEncode({ + 'keyId': keyId, + })); // 取消授权管理员 - Future cancelAdministrator(String keyId) => - post(cancelAuthorizeURL.toUrl, - jsonEncode({ - 'keyId': keyId, - })); + Future cancelAdministrator(String keyId) => post( + cancelAuthorizeURL.toUrl, + jsonEncode({ + 'keyId': keyId, + })); // 冻结 - Future freezeKey(String keyId) => - post(freezeKeyURL.toUrl, - jsonEncode({ - 'keyId': keyId, - })); + Future freezeKey(String keyId) => post( + freezeKeyURL.toUrl, + jsonEncode({ + 'keyId': keyId, + })); // 取消冻结 - Future cancelFreeze(String keyId) => - post(cancelFreezeURL.toUrl, - jsonEncode({ - 'keyId': keyId, - })); + Future cancelFreeze(String keyId) => post( + cancelFreezeURL.toUrl, + jsonEncode({ + 'keyId': keyId, + })); - Future expireLockList(String pageNo, String pageSize) => - post( - expireLockListURL.toUrl, - jsonEncode({ - 'pageNo': pageNo, - 'pageSize': pageSize, - })); + Future expireLockList(String pageNo, String pageSize) => post( + expireLockListURL.toUrl, + jsonEncode({ + 'pageNo': pageNo, + 'pageSize': pageSize, + })); Future deleteKeyboardPwd( String lockId, String keyboardPwdId, int deleteType) => @@ -1009,9 +1022,9 @@ class ApiProvider extends BaseProvider { String isCoerced, String startDate, List weekDay, - int fingerRight, - int startTime, - int endTime, + int fingerRight, + int startTime, + int endTime, ) => post( addFingerprintURL.toUrl, @@ -1040,9 +1053,9 @@ class ApiProvider extends BaseProvider { String isCoerced, String fingerprintName, String changeType, - int startTime, - int endTime, - int fingerprintType) => + int startTime, + int endTime, + int fingerprintType) => post( editFingerprintURL.toUrl, jsonEncode({ @@ -1202,9 +1215,9 @@ class ApiProvider extends BaseProvider { String startDate, String isCoerced, List weekDay, - int startTime, - int endTime, - int cardRight, + int startTime, + int endTime, + int cardRight, ) => post( addICCardURL.toUrl, @@ -1225,17 +1238,18 @@ class ApiProvider extends BaseProvider { // 编辑ICCard Future editICCardData( - String lockId, - String cardId, - String cardName, - String startDate, - String endDate, - String isCoerced, - List weekDay, - String changeType, - int startTime, - int endTime, - int cardType,) => + String lockId, + String cardId, + String cardName, + String startDate, + String endDate, + String isCoerced, + List weekDay, + String changeType, + int startTime, + int endTime, + int cardType, + ) => post( editICCardURL.toUrl, jsonEncode({ @@ -1606,12 +1620,58 @@ class ApiProvider extends BaseProvider { })); // 获取最新版本号 - Future getVersionData(String brandName, String currentVersion) => post( - getVersionURL.toUrl, + Future getVersionData(String brandName, String currentVersion) => + post( + getVersionURL.toUrl, + jsonEncode({ + 'brandName': brandName, + 'currentVersion': currentVersion, + })); + + // 设置猫眼工作模式 + Future updateCatEyeModeConfig(int lockId, Map catEyeConfig) => post( + updateCatEyeConfigURL.toUrl, jsonEncode({ - 'brandName': brandName, - 'currentVersion': currentVersion, + 'lockId': lockId, + 'catEyeConfig': catEyeConfig, })); + + // 设置自动亮屏 + Future updateAutoLightScreenConfig( + int lockId, int autoLightScreen) => + post( + updateCatEyeConfigURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'autoLightScreen': autoLightScreen, + })); + + // 设置亮屏持续时间 + Future updateLightScreenTimeConfig( + int lockId, int autoLightScreenTime) => + post( + updateCatEyeConfigURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'autoLightScreenTime': autoLightScreenTime, + })); + +// 设置逗留警告 + Future updateStayWarnConfig(int lockId, int stayWarn) => post( + updateCatEyeConfigURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'stayWarn': stayWarn, + })); + + // 设置异常警告 + Future updateAbnormalWarnConfig(int lockId, int abnormalWarn) => + post( + updateCatEyeConfigURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'abnormalWarn': abnormalWarn, + })); } extension ExtensionString on String { diff --git a/star_lock/lib/network/api_repository.dart b/star_lock/lib/network/api_repository.dart index e46f2034..5f2662da 100644 --- a/star_lock/lib/network/api_repository.dart +++ b/star_lock/lib/network/api_repository.dart @@ -193,37 +193,35 @@ class ApiRepository { //钥匙详情-操作记录 Future lockRecordList( - { - required String endDate, - required String keyId, - required String keyStatus, - required String lockId, - required String operatorUid, - required String pageNo, - required String pageSize, - required String startDate, - required String recordType, - required String searchStr, - required String timezoneRawOffSet, - required String keyboardPwdId, - required String cardId, - required String fingerprintId - }) async { + {required String endDate, + required String keyId, + required String keyStatus, + required String lockId, + required String operatorUid, + required String pageNo, + required String pageSize, + required String startDate, + required String recordType, + required String searchStr, + required String timezoneRawOffSet, + required String keyboardPwdId, + required String cardId, + required String fingerprintId}) async { final res = await apiProvider.lockRecordList( - endDate:endDate, - keyId:keyId, - keyStatus:keyStatus, - lockId:lockId, - operatorUid:operatorUid, - pageNo:pageNo, - pageSize:pageSize, - startDate:startDate, - recordType:recordType, - searchStr:searchStr, - timezoneRawOffSet:timezoneRawOffSet, - keyboardPwdId:keyboardPwdId, - cardId:cardId, - fingerprintId:fingerprintId); + endDate: endDate, + keyId: keyId, + keyStatus: keyStatus, + lockId: lockId, + operatorUid: operatorUid, + pageNo: pageNo, + pageSize: pageSize, + startDate: startDate, + recordType: recordType, + searchStr: searchStr, + timezoneRawOffSet: timezoneRawOffSet, + keyboardPwdId: keyboardPwdId, + cardId: cardId, + fingerprintId: fingerprintId); return KeyOperationRecordEntity.fromJson(res.body); } @@ -397,8 +395,11 @@ class ApiRepository { // 删除钥匙 Future deletOwnerKeyData( - {required String lockId, required String keyId, required int includeUnderlings}) async { - final res = await apiProvider.deletOwnerKeyInfo(lockId, keyId, includeUnderlings); + {required String lockId, + required String keyId, + required int includeUnderlings}) async { + final res = + await apiProvider.deletOwnerKeyInfo(lockId, keyId, includeUnderlings); return LockListInfoEntity.fromJson(res.body); } @@ -586,7 +587,8 @@ class ApiRepository { } //即将到期的锁列表 - Future expireLockList(String pageNo, String pageSize) async { + Future expireLockList( + String pageNo, String pageSize) async { final res = await apiProvider.expireLockList(pageNo, pageSize); return ExpireLockListEntity.fromJson(res.body); } @@ -1191,18 +1193,28 @@ class ApiRepository { // 编辑指纹 Future editFingerprintsData( {required String fingerprintId, - required String lockId, - required List weekDay, - required String startDate, - required String endDate, - required String isCoerced, - required String fingerprintName, - required String changeType, - required int startTime, - required int endTime, - required int fingerprintType}) async { - final res = await apiProvider.editFingerprintsData(fingerprintId, lockId, - weekDay, startDate, endDate, isCoerced, fingerprintName, changeType, startTime, endTime, fingerprintType); + required String lockId, + required List weekDay, + required String startDate, + required String endDate, + required String isCoerced, + required String fingerprintName, + required String changeType, + required int startTime, + required int endTime, + required int fingerprintType}) async { + final res = await apiProvider.editFingerprintsData( + fingerprintId, + lockId, + weekDay, + startDate, + endDate, + isCoerced, + fingerprintName, + changeType, + startTime, + endTime, + fingerprintType); return LoginEntity.fromJson(res.body); } @@ -1359,26 +1371,48 @@ class ApiRepository { required int endTime, required int cardRight, }) async { - final res = await apiProvider.addICCardData(lockId, endDate, cardName, - cardNumber, cardType, addType, startDate, isCoerced, weekDay, startTime, endTime, cardRight); + final res = await apiProvider.addICCardData( + lockId, + endDate, + cardName, + cardNumber, + cardType, + addType, + startDate, + isCoerced, + weekDay, + startTime, + endTime, + cardRight); return AddICCardEntity.fromJson(res.body); } // 编辑IC卡 - Future editICCardData( - {required String lockId, - required String cardId, - required String cardName, - required String startDate, - required String endDate, - required String isCoerced, - required List weekDay, - required String changeType, - required int startTime, - required int endTime, - required int cardType,}) async { - final res = await apiProvider.editICCardData(lockId, cardId, cardName, - startDate, endDate, isCoerced, weekDay, changeType, startTime, endTime, cardType); + Future editICCardData({ + required String lockId, + required String cardId, + required String cardName, + required String startDate, + required String endDate, + required String isCoerced, + required List weekDay, + required String changeType, + required int startTime, + required int endTime, + required int cardType, + }) async { + final res = await apiProvider.editICCardData( + lockId, + cardId, + cardName, + startDate, + endDate, + isCoerced, + weekDay, + changeType, + startTime, + endTime, + cardType); return LoginEntity.fromJson(res.body); } @@ -1629,11 +1663,47 @@ class ApiRepository { } // 获取版本号 - Future getVersionData({ - required String brandName, - required String currentVersion - }) async { + Future getVersionData( + {required String brandName, required String currentVersion}) async { final res = await apiProvider.getVersionData(brandName, currentVersion); return VersionUndateEntity.fromJson(res.body); } + + // 设置猫眼工作模式 + Future updateCatEyeModeConfig( + {required int lockId, required Map catEyeConfig}) async { + final res = await apiProvider.updateCatEyeModeConfig(lockId, catEyeConfig); + return VersionUndateEntity.fromJson(res.body); + } + + // 设置自动亮屏 + Future updateAutoLightScreenConfig( + {required int lockId, required int autoLightScreen}) async { + final res = + await apiProvider.updateAutoLightScreenConfig(lockId, autoLightScreen); + return VersionUndateEntity.fromJson(res.body); + } + + // 设置亮屏持续时间 + Future updateLightScreenTimeConfig( + {required int lockId, required int autoLightScreenTime}) async { + final res = await apiProvider.updateLightScreenTimeConfig( + lockId, autoLightScreenTime); + return VersionUndateEntity.fromJson(res.body); + } + + // 设置逗留警告 + Future updateStayWarnConfig( + {required int lockId, required int stayWarn}) async { + final res = await apiProvider.updateStayWarnConfig(lockId, stayWarn); + return VersionUndateEntity.fromJson(res.body); + } + + // 设置异常警告 + Future updateAbnormalWarnConfig( + {required int lockId, required int abnormalWarn}) async { + final res = + await apiProvider.updateAbnormalWarnConfig(lockId, abnormalWarn); + return VersionUndateEntity.fromJson(res.body); + } } diff --git a/star_lock/lib/talk/call/callTalk.dart b/star_lock/lib/talk/call/callTalk.dart index 2f55b28e..a43e42a9 100644 --- a/star_lock/lib/talk/call/callTalk.dart +++ b/star_lock/lib/talk/call/callTalk.dart @@ -17,9 +17,7 @@ class CallTalk { static int ABUF_NUM = 100; static int FIRSTINDEX = 1; - int status = 0; // 假设有这个成员变量 IframeInfo? iframe; // 假设有这个成员变量 - bool getFirstFrame = false; //是否得到了第一帧 List allDataBytes = []; //音频数据 CallTalk._init() { @@ -73,12 +71,7 @@ class CallTalk { // print('获取帧序号 getIframeIndex:$getIframeIndex'); // 获取帧长度 65 - // int alen = bb[POS_alen] & 0xff; - // var alenList = bb.sublist(POS_alen, POS_alen + 4); - // int alen = ((0xff & alenList[(0)]) << 24 | - // (0xff & alenList[1]) << 16 | - // (0xff & alenList[2]) << 8 | - // (0xFF & alenList[3])); + int alen = bb[POS_alen] + bb[POS_alen + 1] * 256; // print('获取帧长度 alen:$alen'); // 当前包号 71 @@ -96,7 +89,7 @@ class CallTalk { iframe = IframeInfo(); iframe!.iframeIndex = getIframeIndex; iframe!.bagNum = getBagNum; - // iframe!.cur_len = alen; + iframe!.cur_len = alen; iframe!.bb = []; // growableList = iframe!.bb!.toList(growable: true); } @@ -105,15 +98,19 @@ class CallTalk { // 如果是同一帧就添加起来 if (getIframeIndex == iframe!.iframeIndex) { - var getList = bb.sublist(77, bb.length); + var getList = bb.sublist(POS_data, bb.length); iframe!.bb!.addAll(getList); } - // print('iframe.bagNum: ${iframe!.bagNum} iframe.bagReceive: ${iframe!.bagReceive}'); + // print( + // 'iframe.bagNum: ${iframe!.bagNum} iframe.bagReceive: ${iframe!.bagReceive}'); // 如果收到的包数等于总包数,说明这一帧数据已经接收完毕 if (iframe!.bagNum == iframe!.bagReceive) { // print('播放第${iframe!.iframeIndex}帧 一帧图片的hexStringData: ${Uint8List.fromList(growableList)}'); + // print('得到的一张图片的数据长度为${iframe!.bb!.length}'); eventBus.fire(GetTVDataRefreshUI(iframe!.bb!)); + } else { + // print('接收到的包数不等于总包数'); } } } diff --git a/star_lock/lib/talk/call/iFrameInfo.dart b/star_lock/lib/talk/call/iFrameInfo.dart index 5d0951ec..775c6a6f 100644 --- a/star_lock/lib/talk/call/iFrameInfo.dart +++ b/star_lock/lib/talk/call/iFrameInfo.dart @@ -1,7 +1,5 @@ -import 'dart:typed_data'; - class IframeInfo { - int iframeIndex = -1; + int iframeIndex = 0; int iframeTime = 0; int bagNum = 0; int bagReceive = 1; @@ -12,7 +10,7 @@ class IframeInfo { int codecMode = 0; IframeInfo() { - iframeIndex = -1; + iframeIndex = 0; bagNum = 0; bagReceive = 0; isFull = false; diff --git a/star_lock/lib/talk/udp/udp_reciverData.dart b/star_lock/lib/talk/udp/udp_reciverData.dart index 799d6ca0..5766989e 100644 --- a/star_lock/lib/talk/udp/udp_reciverData.dart +++ b/star_lock/lib/talk/udp/udp_reciverData.dart @@ -2,6 +2,8 @@ import 'dart:typed_data'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart'; +import 'package:star_lock/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart'; import 'package:star_lock/talk/udp/udp_manage.dart'; import '../../blue/io_tool/io_tool.dart'; @@ -33,7 +35,7 @@ class CommandUDPReciverManager { // print("心跳包反馈 在线状态"); } else if (data[7] == 3) { // [Toast.show(msg: "您已在其他设备登录")]; - EasyLoading.showToast("您已在其他设备登录",duration: 2000.milliseconds); + EasyLoading.showToast("您已在其他设备登录", duration: 2000.milliseconds); } } else if (data[6] == 150) { // if( [Pub getApp].isBack){ @@ -66,6 +68,7 @@ class CommandUDPReciverManager { // 停止声音 UDPTalkClass().stopLocalAudio(); eventBus.fire(GetUDPStatusRefreshUI(UDPTalkClass().status)); + print('接听反馈刷新UI1'); } } break; @@ -95,7 +98,7 @@ class CommandUDPReciverManager { print("appReceiveUDPData:$data"); if ((data[7] & 0x3) == 2) { print("开门成功"); - EasyLoading.showToast("开门成功",duration: 2000.milliseconds); + EasyLoading.showToast("开门成功", duration: 2000.milliseconds); } else { print("开门失败"); } @@ -117,6 +120,7 @@ class CommandUDPReciverManager { CallTalk().stopPcmSound(); eventBus.fire(GetUDPStatusRefreshUI(UDPTalkClass().status)); Get.back(); + print('挂断反馈刷新UI1'); } break; case 140: @@ -187,10 +191,10 @@ class CommandUDPReciverManager { if ((data[7] & 0x3) == 2) { print("开门成功"); // Toast.show(msg: "开门成功"); - EasyLoading.showToast("开门成功",duration: 2000.milliseconds); + EasyLoading.showToast("开门成功", duration: 2000.milliseconds); } else { print("开门失败"); - EasyLoading.showToast("开门失败",duration: 2000.milliseconds); + EasyLoading.showToast("开门失败", duration: 2000.milliseconds); } } break; diff --git a/star_lock/lib/talk/udp/udp_talkClass.dart b/star_lock/lib/talk/udp/udp_talkClass.dart index 8113bf71..69665e9c 100644 --- a/star_lock/lib/talk/udp/udp_talkClass.dart +++ b/star_lock/lib/talk/udp/udp_talkClass.dart @@ -1,8 +1,10 @@ import 'dart:async'; import 'package:audioplayers/audioplayers.dart'; import 'package:fast_gbk/fast_gbk.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart'; +import 'package:star_lock/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart'; import 'package:star_lock/talk/call/callTalk.dart'; import '../../appRouters.dart'; import '../../tools/storage.dart'; @@ -27,7 +29,11 @@ class UDPTalkClass { late Timer timer; // 该字段是为了判断是否跳转到接听界面 挂断或者退出接听界面要记得变更状态 var isBeCall = false; + var isEndCall = false; //是否已经调用结束对讲 final audioPlayer = AudioPlayer(); + var playLocalAudioSecond = 0; + Timer playLocalAudioTimer = + Timer.periodic(const Duration(seconds: 1), (timer) {}); beCallW({List? data, String? ip, int? port}) async { print("beCall status:$status"); @@ -70,17 +76,46 @@ class UDPTalkClass { Get.toNamed(Routers.lockMonitoringPage, arguments: {"lockId": "111"}); } - Timer(const Duration(minutes: 1), () { - stopLocalAudio(); - callNoAnswer(); - }); + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + _showNotification(flutterLocalNotificationsPlugin); playLocalAudio(); + + if (isEndCall == true) { + print('已经结束对讲'); + return; + } + playLocalAudioTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + playLocalAudioSecond++; + // 检查条件,如果达到60秒且未得到应答,则认为失败 + if (playLocalAudioSecond >= 60) { + playLocalAudioTimer.cancel(); // 取消定时器 + LockMonitoringLogic().initiateUdpHangUpAction(); + } + }); } else { // 忙 } } +//发送本地通知 + Future _showNotification( + FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin) async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails('1', 'flutter_channel', + importance: Importance.max, + priority: Priority.high, + playSound: true, + ticker: 'ticker'); + const NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + var getLockName = await Storage.getString(saveLockAlias); + await flutterLocalNotificationsPlugin.show( + 0, '呼叫提醒', '收到来自($getLockName)锁的呼叫。', platformChannelSpecifics, + payload: 'item x'); + } + // 判断是否是call的本人 Future isCallMe(List? data) async { final loginData = await Storage.getLoginData(); @@ -136,10 +171,13 @@ class UDPTalkClass { //呼叫有响铃无应答处理 void callNoAnswer() { + // print('无应答处理'); + stopLocalAudio(); + status = 0; + isBeCall = false; + isEndCall = true; + LockMonitoringState().isClickHangUp.value = false; CallTalk().stopPcmSound(); - // 挂断 - LockMonitoringLogic().udpHangUpAction(); - // 关闭当前界面 Get.back(); } } diff --git a/star_lock/lib/tools/storage.dart b/star_lock/lib/tools/storage.dart index 855d48e7..7238a460 100644 --- a/star_lock/lib/tools/storage.dart +++ b/star_lock/lib/tools/storage.dart @@ -6,7 +6,6 @@ import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; import '../login/login/entity/LoginData.dart'; -import '../login/login/entity/LoginEntity.dart'; const saveBluePublicKey = "BluePublicKey"; const saveBluePrivateKey = "BluePrivateKey"; @@ -20,6 +19,7 @@ const isAgreePosition = "isAgreePosition"; //是否同意获取位置弹窗 const isAgreeCamera = "isAgreeCamera"; //是否同意获取相机/相册弹窗 const isShowUpdateVersion = "isShowUpdateVersion"; //是否更新弹窗 +const saveLockAlias = "saveLockAlias"; //锁别名 const saveUserLoginData = "userLoginData"; diff --git a/star_lock/lib/tools/xs_jPhush.dart b/star_lock/lib/tools/xs_jPhush.dart index edd217dc..1ced70b1 100644 --- a/star_lock/lib/tools/xs_jPhush.dart +++ b/star_lock/lib/tools/xs_jPhush.dart @@ -15,7 +15,7 @@ class XSJPushProvider { appKey: "7ff37d174c1a568a89e98dad", channel: "flutter_channel", production: false, - debug: true, + debug: false, ); jpush.addEventHandler( diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index 6c027ca9..f7d0f79a 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -22,7 +22,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # 1.0.18+2024032002:修复注册页布局错乱;修复第二次才可以删除锁的问题;修改申请权限字符串 # 1.0.18+20240321(2024032101):打包给欧阳测试 # 1.0.20+2024032102:修复Apple Store App Tracking Transparency权限问题 -version: 1.0.20+2024032102 +# 1.0.21+2024032801:同为斯凯环境也区分删减版和完整版,通过main_sky_lite.dart/main_sky_full.dart切换 +version: 1.0.21+2024032801 environment: sdk: '>=2.12.0 <3.0.0'