diff --git a/lib/main.dart b/lib/main.dart index 10a2339e..52a85949 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,7 +12,7 @@ import 'package:star_lock/mine/about/debug/debug_tool.dart'; import 'package:star_lock/network/api_provider.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/start_chart_api.dart'; -import 'package:star_lock/talk/startChart/appLifecycle_observer.dart'; +import 'package:star_lock/talk/startChart/status/appLifecycle_observer.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/device_info_service.dart'; import 'package:star_lock/tools/platform_info_services.dart'; diff --git a/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart b/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart index 53a61e8d..ee0dd3c7 100755 --- a/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart +++ b/lib/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_logic.dart @@ -21,7 +21,7 @@ class CatEyeSetLogic extends BaseGetXController { } } - //设置自动亮屏 + //设置亮屏持续时间 Future updateLightScreenTimeConfig() async { final VersionUndateEntity entity = await ApiRepository.to.updateLightScreenTimeConfig( lockId: state.lockSetInfoData.value.lockId!, @@ -112,4 +112,6 @@ class CatEyeSetLogic extends BaseGetXController { } return entity; } + + } diff --git a/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart b/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart index a13f49d5..981a9d48 100755 --- a/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart +++ b/lib/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_logic.dart @@ -1,9 +1,14 @@ +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; +import 'package:star_lock/blue/blue_manage.dart'; +import 'package:star_lock/blue/io_tool/io_tool.dart'; +import 'package:star_lock/blue/sender_manage.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeWorkMode/catEyeWorkMode_state.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/versionUndate/versionUndate_entity.dart'; class CatEyeWorkModeLogic extends BaseGetXController { @@ -11,7 +16,8 @@ class CatEyeWorkModeLogic extends BaseGetXController { //设置猫眼工作模式 Future updateCatEyeModeConfig() async { - final VersionUndateEntity entity = await ApiRepository.to.updateCatEyeModeConfig( + final VersionUndateEntity entity = + await ApiRepository.to.updateCatEyeModeConfig( lockId: state.lockSetInfoData.value.lockId!, catEyeConfig: [ { @@ -53,9 +59,47 @@ class CatEyeWorkModeLogic extends BaseGetXController { } } + /// 处理蓝牙数据 + void _handlerBleData() { + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); + + final List? token = await Storage.getStringList(saveBlueToken); + final List getTokenList = changeStringListToIntList(token!); + + final List? publicKey = + await Storage.getStringList(saveBluePublicKey); + final List getPublicKeyList = + changeStringListToIntList(publicKey!); + + List featureData = []; + + IoSenderManage.setSupportFunctionsWithParametersCommand( + keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), + userID: await Storage.getUid(), + featureBit: 33, + featureParaLength: 1, + featureData: featureData, + token: getTokenList, + needAuthor: 1, + publicKey: getPublicKeyList, + privateKey: getPrivateKeyList); + } else if (connectionState == BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + } + }); + } + // 获取锁设置信息 Future getLockSettingInfoData() async { - final LockSetInfoEntity entity = await ApiRepository.to.getLockSettingInfoData( + final LockSetInfoEntity entity = + await ApiRepository.to.getLockSettingInfoData( lockId: state.lockSetInfoData.value.lockId.toString(), ); if (entity.errorCode!.codeIsSuccessful) { diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index eb6f1ccc..7635bbe4 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -105,10 +105,11 @@ class ConfiguringWifiLogic extends BaseGetXController { serversList.add(type2); } - final StarChartRegisterNodeEntity? registerNodeEntity = - await Storage.getStarChartRegisterNodeInfo(); + // 判断是否登录账户 + final loginData = await Storage.getLoginData(); + // 获取app用户的peerId - String appPeerId = registerNodeEntity?.peer?.id ?? ''; + String appPeerId = loginData?.starchart?.starchartId ?? ''; final List uidList = [Storage.getUid().toString()]; IoSenderManage.senderConfiguringWifiCommand( @@ -201,10 +202,11 @@ class ConfiguringWifiLogic extends BaseGetXController { final String? uidStr = await Storage.getUid(); final List uidList = [uidStr.toString()]; - final StarChartRegisterNodeEntity? registerNodeEntity = - await Storage.getStarChartRegisterNodeInfo(); + // 判断是否登录账户 + final loginData = await Storage.getLoginData(); + // 获取app用户的peerId - String appPeerId = registerNodeEntity?.peer?.id ?? ''; + String appPeerId = loginData?.starchart?.starchartId ?? ''; IoSenderManage.senderConfiguringWifiCommand( keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), userID: await Storage.getUid(), diff --git a/lib/main/lockMian/lockMain/lockMain_page.dart b/lib/main/lockMian/lockMain/lockMain_page.dart index 2390d0c3..0c655d42 100755 --- a/lib/main/lockMian/lockMain/lockMain_page.dart +++ b/lib/main/lockMian/lockMain/lockMain_page.dart @@ -230,31 +230,43 @@ class _StarLockMainPageState extends State height: 160.h, ), // _buildImage(), - SubmitBtn( - btnName: '发送地址', - onClick: () async { - StartChartManage().startSendingRbcuInfoMessages(); - // String assetPath = 'assets/test.jpg'; // 替换为你的图片路径 - // List imageBytes = await loadAssetImageAsBytes(assetPath); - // // String testStr = - // // '---天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈剑号巨阙珠称夜光果珍李柰菜重芥姜海咸河淡鳞潜羽翔龙师火帝鸟官人皇始制文字乃服衣裳推位让国有虞陶唐吊民伐罪周发殷汤坐朝问道垂拱平章爱育黎首臣伏戎羌遐迩体率宾归王鳴鳳翔兮神靈應和炫耀光芒照灼穹蒼迤邐岷峨嶢峻崢巍懿承緒劬勞育秩延佚賡孳蕃鑑識祗崇乾坤纘宵旰卿芮詒朔皎琲犂檄圮黯馭燎竈硎洮蠟胝攢囤嶇葺錡堯羲冕箕翬騏闡燮鸞蓊枘橐榘稟泗沂涖浹涔浣淇漱瀋潢瀾沚澮澆潦瀦瀌瀹灧炅焯燠燋爨熠焜煆烜燴炻熛燧牝牯犛犴牖牒疰疴痀癜痱癃皞皎盂盰盱盻眚眵瞋瞑瞷矙矧矬矰矞砟砉砥砣硇磑磲硤硭礌礞礡祀祚祜祧祼祺禋禡秭秣稃稞稹稷穈穄窀窆窠窸笄筇筌筅筮箦篑篯簟籀籝糅糗紵紽紾綃綈綬綣緜縞縰縻縴繢繇繙罟罾羝羶羸羼翊翕翥翡翳翽耖耜耠耱耦耧耩耨耬耵耶胂胼胬脘腽膦臢臬臾舂舄舡舸艋艏艟艤艚艨艪艭艴芏芊苣苴苕茌茱荄荃莛莪莶菰萁菸菽萸葶蒯蓍蓐蓬蓼蔌蔪蕈蕖蕙蕺蕻薷藦藨藭蘅蘧蘼虍虔虬虮虰虺虻蚨蚋蚱蛏蛘蜊蜍蜉蜣蜥蜩蜴蜱蜮蜾蝣蝤蝥螓螯螨蟒蟑蟛蠊蠋蠛蠡蠹衄衒衢衾袢袷裎裥裨裾褊褙褚褡褰褶襁襦襻觇觋觖觫觿訇訑訾詑詈詟詹誊誨誥誦誨諉諛謏謦譊譖譟譬譯譴讴讵讷诐诪诮诰诳诶谂谄谌谏谑谟谡谥谧谮谯谳谵豇豉豕豚豳豸貂貊貔賑賚賡贐赍赑赗赪赭赳趑趔趱趿跂跏跎跖跗跣跹跽踆踔踝踟踬踮踯蹀蹅蹇蹉蹐蹙蹦蹩躅躐躔躜躞軎軑軔軛軫軬軺輀輅輇輈輐輗輢輦輭輶轋轘轜辀辂辒辚辩迓迕迤迨迮逄逋逑逖逯遄遘遑遴遽邂邈邋邙邡邴邳邶郅郇郛郡郾鄌鄑鄘鄜鄞鄢鄣鄯鄹酃酆酈酖酗酘酢酤酴酹酽酾酾醅醊醑醚醢醪醭醮醯醵醴醶釃釅釐釜釡釴釸釾鉅鈦鈍鈹鈾鈿鉦鉬鉮鉻鉿銎銋銖銩銫銮銲鋈鋋鋌鋮鋯鋹鋻錎錡錣錤鍉鍐鍬鍱鍾鎏鎑鎒鎰鎵鎸鎿鏊鏖鏞鏟鏸鏹鏺鏽鐃鐋鐔鐛鐠鐣鐦鐭鐮鐯鐳鐴鐵鐼鐿鑌鑒鑔鑕鑞鑢鑬鑰鑱鑲鑴鑽鑾鑿钁钆钇钋钍钏钔钗钜钯钴钷钹钺钼钽钿铄铈铊铍铐铖铗铘铙铚铠铨铪铬铮铰铹铼铿锃锆锊锍锎锏锒锓锔锖锗锘锞锟锢锩锫锬锭锯锴锶锷锸锺锼锾镂镄镅镆镉镎镏镒镔镖镙镛镞镡镢镤镩镪镫镬镭镮镯镰镱镲镳镴镶镸长門閃閔閘閡闅闈闑闒闓闔闛闞闠闤闥闦闬闿阂阃阄阆阇阘阛阝队阡阯阱阪阽陀陂陉陔陘陞陟陧陬陲陴陶隃隋隍隒隓隗隦隰隱隳隵隶隽隿雎雋雐雚雝雟雤雩雯雱雿霈霅霌霎霏霗霙霛霝霡霣霤霧靂靅靆靉靎靏靐靕靗靛靡靺靻靽鞀鞉鞎鞑鞔鞖鞚鞝鞡鞤鞧鞨鞫鞬鞮鞯鞳鞴韁韃韈韉韋韐韒韓韗韙韝韟韢韡韣韦韧韨韩韪韫韬韭韮韯韲音頍頏頔頖頞頟頤頦頬頰頲頴頵頹頽頿顃顅顈顊顋顒顕顗顛顝顟顤顪顫顬顮顰顱顲顳顴页顶顷顸颃预颋颌颎颏颐频颓颔颕颙颖颛颟颡颢颣颤颥颦颧風颮颯颰颱颳颶颷颸颹颻颼颾飁飆飇飉飋飏飐飔飗飘飙飚飛飜飝飛飜飝飛飜飝飛飜飝雊霺霿靁靟鞲韞韭頫顴颿飌飡馺駃騑騜髐鬃鰩鳯鷊黴在古老的东方有一座美丽的城市名为锦绣锦绣城四季如春风景秀丽是人们心中的理想之地城中有一条清澈见底的小河河水潺潺流过滋养着两岸的花草树木河边有一座古老的石桥桥上雕刻着精美的图案见证了无数过往行人锦绣城的居民勤劳善良他们日出而作日落而息过着简单而幸福的生活城中有一位智者名叫慧心慧心先生博学多才深受人们的尊敬他常常在河边的亭子里给孩子们讲述历史故事传授知识和智慧孩子们围坐在他身边听得津津有味仿佛置身于一个个奇妙的世界在锦绣城的北边有一片茂密的森林森林里生活着各种各样的动物有活泼可爱的猴子它们在树上跳跃嬉戏有威武雄壮的老虎它们在林间巡视守护着森林的安宁还有许多不知名的鸟儿它们在枝头欢快地歌唱为森林增添了无限生机一天慧心先生带着几个学生走进森林进行一次生动的自然课他们观察着各种植物的生长了解它们的特性聆听鸟儿的鸣叫感受大自然的和谐学生们兴奋不已他们发现大自然是一个神奇的宝库蕴藏着无尽的奥秘在森林的深处有一片神秘的湖泊湖水碧绿如玉清澈见底传说中湖中住着一位美丽的水仙子她用神奇的力量保护着湖泊和周围的生灵慧心先生告诉学生们要爱护大自然与万物和谐共处才能得到大自然的馈赠锦绣城的居民们深知这一点他们珍惜每一滴水每一寸土地努力保护着这片美丽的家园他们相信只要人与自然和谐相处锦绣城将永远充满生机与活力锦绣城外群山环绕山间云雾缭绕宛如仙境山中有一处幽静的山谷谷中开满了五颜六色的花朵香气扑鼻引得蝴蝶翩翩起舞山谷中还有一条蜿蜒的小径两旁长满了奇花异草仿佛是一条通往神秘世界的通道慧心先生的学生们在一次探险中偶然发现了这个山谷他们惊叹于大自然的鬼斧神工纷纷拿出画笔将这美丽的景色描绘下来他们还发现了一种奇特的植物它的叶子呈现出透明的蓝色在阳光下闪闪发光仿佛蕴含着神秘的力量慧心先生告诉他们这种植物名为“梦幻草”只生长在特定的环境中非常稀有在锦绣城的东边有一片广阔的草原草原上绿草如茵牛羊成群草原上还有一座古老的风车风车的叶片随风旋转发出“吱呀吱呀”的声响仿佛在诉说着岁月的故事草原上的人们以放牧为生他们骑着骏马驰骋在广阔的天地间享受着自由自在的生活一天慧心先生带领学生们来到草原给他们上了一堂生动的地理课他指着远处的山脉告诉学生们山脉的形成过程以及它们对气候和生态环境的影响学生们听得入迷仿佛置身于大自然的怀抱中感受到了大自然的壮丽与神奇在锦绣城的南边有一片茂密的竹林竹林里竹子挺拔绿意盎然竹林中有一条清澈的小溪溪水潺潺流淌溪边长满了青苔竹林里还有一座精致的小亭子亭子的柱子上刻着优美的诗句让人感受到一种宁静与雅致慧心先生常常在竹林中的小亭子里静坐思考人生的哲理他告诉学生们竹子虽然柔弱但却有着坚韧不拔的精神无论遇到多大的困难都能顽强地生长学生们深受启发明白了在人生的道路上要像竹子一样勇敢地面对挑战坚持不懈地追求自己的理想锦绣城的居民们还擅长制作各种手工艺品他们的作品精美绝伦远近闻名有巧夺天工的陶瓷色彩斑斓形态各异有细腻精致的刺绣图案生动栩栩如生还有雕刻精美的木雕栩栩如生令人叹为观止这些手工艺品不仅展现了锦绣城居民的智慧和技艺也成为了他们与外界交流的纽带在锦绣城的中心有一座宏伟的宫殿宫殿的建筑风格独特气势恢宏宫殿的屋顶覆盖着金色的琉璃瓦在阳光下熠熠生辉宫殿的墙壁上雕刻着精美的图案栩栩如生仿佛在诉说着一个个古老的故事宫殿里住着一位英明的君主他以仁爱之心治理国家深受百姓的爱戴慧心先生常常受邀到宫殿中为君主出谋划策帮助他解决国家大事君主也非常尊重慧心先生的智慧常常向他请教治国之道在他们的共同努力下锦绣城国泰民安繁荣昌盛锦绣城的居民们还非常重视教育他们相信知识能够改变命运让孩子们拥有更加美好的未来城中有一座古老的书院书院的建筑古朴典雅环境优美书院里有许多博学的老师他们用心地教导学生传授知识和智慧学生们在这里努力学习汲取知识的养分,为将来的发展打下坚实的基础慧心先生也常常到书院授课他用自己的知识和智慧启迪学生们的思维引导他们去探索未知的世界学生们对慧心先生敬仰有加他们知道只有不断学习才能像慧心先生一样拥有渊博的知识和智慧为社会做出贡献锦绣城的故事还有很多这里的人们用自己的勤劳和智慧创造了一个充满生机与活力的美好家园他们相信只要人与自然和谐相处与他人携手共进锦绣城的明天一定会更加美好=='; - // - // // List imageBytes = utf8.encode(testStr).toList(); - // // List imageBytes = utf8.encode(testStr).toList(); - // // state.talkData.value = imageBytes; - // // setState(() {}); - // String toPeerId = - // '2vzXdjdzipJBpWpJxhiRzCFXrDKk54t3YJ7EjYPSRuij'; - // StartChartManage() - // .sendEchoMessage(payload: imageBytes, toPeerId: toPeerId); - }, - ), - SubmitBtn( - btnName: '停止', - onClick: () async { - StartChartManage().stopSendingRbcuInfoMessages(); - }, - ), + // SubmitBtn( + // btnName: '发送音视频数据', + // onClick: () { + // StartChartManage().sendTalkDataMessage( + // talkData: TalkData( + // content: [1, 2, 3, 4], + // contentType: TalkData_ContentTypeE.Image, + // durationMs: DateTime.now().millisecondsSinceEpoch ~/ 1000, + // ), + // ); + // }, + // ), + // SubmitBtn( + // btnName: '发送地址', + // onClick: () async { + // StartChartManage().startSendingRbcuInfoMessages(ToPeerId: 'A3HPybdRQYKRBxDneQ5gPX6Wk55CKGAAz2w2L2k4head'); + // // String assetPath = 'assets/test.jpg'; // 替换为你的图片路径 + // // List imageBytes = await loadAssetImageAsBytes(assetPath); + // // // String testStr = + // // // '---天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈剑号巨阙珠称夜光果珍李柰菜重芥姜海咸河淡鳞潜羽翔龙师火帝鸟官人皇始制文字乃服衣裳推位让国有虞陶唐吊民伐罪周发殷汤坐朝问道垂拱平章爱育黎首臣伏戎羌遐迩体率宾归王鳴鳳翔兮神靈應和炫耀光芒照灼穹蒼迤邐岷峨嶢峻崢巍懿承緒劬勞育秩延佚賡孳蕃鑑識祗崇乾坤纘宵旰卿芮詒朔皎琲犂檄圮黯馭燎竈硎洮蠟胝攢囤嶇葺錡堯羲冕箕翬騏闡燮鸞蓊枘橐榘稟泗沂涖浹涔浣淇漱瀋潢瀾沚澮澆潦瀦瀌瀹灧炅焯燠燋爨熠焜煆烜燴炻熛燧牝牯犛犴牖牒疰疴痀癜痱癃皞皎盂盰盱盻眚眵瞋瞑瞷矙矧矬矰矞砟砉砥砣硇磑磲硤硭礌礞礡祀祚祜祧祼祺禋禡秭秣稃稞稹稷穈穄窀窆窠窸笄筇筌筅筮箦篑篯簟籀籝糅糗紵紽紾綃綈綬綣緜縞縰縻縴繢繇繙罟罾羝羶羸羼翊翕翥翡翳翽耖耜耠耱耦耧耩耨耬耵耶胂胼胬脘腽膦臢臬臾舂舄舡舸艋艏艟艤艚艨艪艭艴芏芊苣苴苕茌茱荄荃莛莪莶菰萁菸菽萸葶蒯蓍蓐蓬蓼蔌蔪蕈蕖蕙蕺蕻薷藦藨藭蘅蘧蘼虍虔虬虮虰虺虻蚨蚋蚱蛏蛘蜊蜍蜉蜣蜥蜩蜴蜱蜮蜾蝣蝤蝥螓螯螨蟒蟑蟛蠊蠋蠛蠡蠹衄衒衢衾袢袷裎裥裨裾褊褙褚褡褰褶襁襦襻觇觋觖觫觿訇訑訾詑詈詟詹誊誨誥誦誨諉諛謏謦譊譖譟譬譯譴讴讵讷诐诪诮诰诳诶谂谄谌谏谑谟谡谥谧谮谯谳谵豇豉豕豚豳豸貂貊貔賑賚賡贐赍赑赗赪赭赳趑趔趱趿跂跏跎跖跗跣跹跽踆踔踝踟踬踮踯蹀蹅蹇蹉蹐蹙蹦蹩躅躐躔躜躞軎軑軔軛軫軬軺輀輅輇輈輐輗輢輦輭輶轋轘轜辀辂辒辚辩迓迕迤迨迮逄逋逑逖逯遄遘遑遴遽邂邈邋邙邡邴邳邶郅郇郛郡郾鄌鄑鄘鄜鄞鄢鄣鄯鄹酃酆酈酖酗酘酢酤酴酹酽酾酾醅醊醑醚醢醪醭醮醯醵醴醶釃釅釐釜釡釴釸釾鉅鈦鈍鈹鈾鈿鉦鉬鉮鉻鉿銎銋銖銩銫銮銲鋈鋋鋌鋮鋯鋹鋻錎錡錣錤鍉鍐鍬鍱鍾鎏鎑鎒鎰鎵鎸鎿鏊鏖鏞鏟鏸鏹鏺鏽鐃鐋鐔鐛鐠鐣鐦鐭鐮鐯鐳鐴鐵鐼鐿鑌鑒鑔鑕鑞鑢鑬鑰鑱鑲鑴鑽鑾鑿钁钆钇钋钍钏钔钗钜钯钴钷钹钺钼钽钿铄铈铊铍铐铖铗铘铙铚铠铨铪铬铮铰铹铼铿锃锆锊锍锎锏锒锓锔锖锗锘锞锟锢锩锫锬锭锯锴锶锷锸锺锼锾镂镄镅镆镉镎镏镒镔镖镙镛镞镡镢镤镩镪镫镬镭镮镯镰镱镲镳镴镶镸长門閃閔閘閡闅闈闑闒闓闔闛闞闠闤闥闦闬闿阂阃阄阆阇阘阛阝队阡阯阱阪阽陀陂陉陔陘陞陟陧陬陲陴陶隃隋隍隒隓隗隦隰隱隳隵隶隽隿雎雋雐雚雝雟雤雩雯雱雿霈霅霌霎霏霗霙霛霝霡霣霤霧靂靅靆靉靎靏靐靕靗靛靡靺靻靽鞀鞉鞎鞑鞔鞖鞚鞝鞡鞤鞧鞨鞫鞬鞮鞯鞳鞴韁韃韈韉韋韐韒韓韗韙韝韟韢韡韣韦韧韨韩韪韫韬韭韮韯韲音頍頏頔頖頞頟頤頦頬頰頲頴頵頹頽頿顃顅顈顊顋顒顕顗顛顝顟顤顪顫顬顮顰顱顲顳顴页顶顷顸颃预颋颌颎颏颐频颓颔颕颙颖颛颟颡颢颣颤颥颦颧風颮颯颰颱颳颶颷颸颹颻颼颾飁飆飇飉飋飏飐飔飗飘飙飚飛飜飝飛飜飝飛飜飝飛飜飝雊霺霿靁靟鞲韞韭頫顴颿飌飡馺駃騑騜髐鬃鰩鳯鷊黴在古老的东方有一座美丽的城市名为锦绣锦绣城四季如春风景秀丽是人们心中的理想之地城中有一条清澈见底的小河河水潺潺流过滋养着两岸的花草树木河边有一座古老的石桥桥上雕刻着精美的图案见证了无数过往行人锦绣城的居民勤劳善良他们日出而作日落而息过着简单而幸福的生活城中有一位智者名叫慧心慧心先生博学多才深受人们的尊敬他常常在河边的亭子里给孩子们讲述历史故事传授知识和智慧孩子们围坐在他身边听得津津有味仿佛置身于一个个奇妙的世界在锦绣城的北边有一片茂密的森林森林里生活着各种各样的动物有活泼可爱的猴子它们在树上跳跃嬉戏有威武雄壮的老虎它们在林间巡视守护着森林的安宁还有许多不知名的鸟儿它们在枝头欢快地歌唱为森林增添了无限生机一天慧心先生带着几个学生走进森林进行一次生动的自然课他们观察着各种植物的生长了解它们的特性聆听鸟儿的鸣叫感受大自然的和谐学生们兴奋不已他们发现大自然是一个神奇的宝库蕴藏着无尽的奥秘在森林的深处有一片神秘的湖泊湖水碧绿如玉清澈见底传说中湖中住着一位美丽的水仙子她用神奇的力量保护着湖泊和周围的生灵慧心先生告诉学生们要爱护大自然与万物和谐共处才能得到大自然的馈赠锦绣城的居民们深知这一点他们珍惜每一滴水每一寸土地努力保护着这片美丽的家园他们相信只要人与自然和谐相处锦绣城将永远充满生机与活力锦绣城外群山环绕山间云雾缭绕宛如仙境山中有一处幽静的山谷谷中开满了五颜六色的花朵香气扑鼻引得蝴蝶翩翩起舞山谷中还有一条蜿蜒的小径两旁长满了奇花异草仿佛是一条通往神秘世界的通道慧心先生的学生们在一次探险中偶然发现了这个山谷他们惊叹于大自然的鬼斧神工纷纷拿出画笔将这美丽的景色描绘下来他们还发现了一种奇特的植物它的叶子呈现出透明的蓝色在阳光下闪闪发光仿佛蕴含着神秘的力量慧心先生告诉他们这种植物名为“梦幻草”只生长在特定的环境中非常稀有在锦绣城的东边有一片广阔的草原草原上绿草如茵牛羊成群草原上还有一座古老的风车风车的叶片随风旋转发出“吱呀吱呀”的声响仿佛在诉说着岁月的故事草原上的人们以放牧为生他们骑着骏马驰骋在广阔的天地间享受着自由自在的生活一天慧心先生带领学生们来到草原给他们上了一堂生动的地理课他指着远处的山脉告诉学生们山脉的形成过程以及它们对气候和生态环境的影响学生们听得入迷仿佛置身于大自然的怀抱中感受到了大自然的壮丽与神奇在锦绣城的南边有一片茂密的竹林竹林里竹子挺拔绿意盎然竹林中有一条清澈的小溪溪水潺潺流淌溪边长满了青苔竹林里还有一座精致的小亭子亭子的柱子上刻着优美的诗句让人感受到一种宁静与雅致慧心先生常常在竹林中的小亭子里静坐思考人生的哲理他告诉学生们竹子虽然柔弱但却有着坚韧不拔的精神无论遇到多大的困难都能顽强地生长学生们深受启发明白了在人生的道路上要像竹子一样勇敢地面对挑战坚持不懈地追求自己的理想锦绣城的居民们还擅长制作各种手工艺品他们的作品精美绝伦远近闻名有巧夺天工的陶瓷色彩斑斓形态各异有细腻精致的刺绣图案生动栩栩如生还有雕刻精美的木雕栩栩如生令人叹为观止这些手工艺品不仅展现了锦绣城居民的智慧和技艺也成为了他们与外界交流的纽带在锦绣城的中心有一座宏伟的宫殿宫殿的建筑风格独特气势恢宏宫殿的屋顶覆盖着金色的琉璃瓦在阳光下熠熠生辉宫殿的墙壁上雕刻着精美的图案栩栩如生仿佛在诉说着一个个古老的故事宫殿里住着一位英明的君主他以仁爱之心治理国家深受百姓的爱戴慧心先生常常受邀到宫殿中为君主出谋划策帮助他解决国家大事君主也非常尊重慧心先生的智慧常常向他请教治国之道在他们的共同努力下锦绣城国泰民安繁荣昌盛锦绣城的居民们还非常重视教育他们相信知识能够改变命运让孩子们拥有更加美好的未来城中有一座古老的书院书院的建筑古朴典雅环境优美书院里有许多博学的老师他们用心地教导学生传授知识和智慧学生们在这里努力学习汲取知识的养分,为将来的发展打下坚实的基础慧心先生也常常到书院授课他用自己的知识和智慧启迪学生们的思维引导他们去探索未知的世界学生们对慧心先生敬仰有加他们知道只有不断学习才能像慧心先生一样拥有渊博的知识和智慧为社会做出贡献锦绣城的故事还有很多这里的人们用自己的勤劳和智慧创造了一个充满生机与活力的美好家园他们相信只要人与自然和谐相处与他人携手共进锦绣城的明天一定会更加美好=='; + // // + // // // List imageBytes = utf8.encode(testStr).toList(); + // // // List imageBytes = utf8.encode(testStr).toList(); + // // // state.talkData.value = imageBytes; + // // // setState(() {}); + // // String toPeerId = + // // '2vzXdjdzipJBpWpJxhiRzCFXrDKk54t3YJ7EjYPSRuij'; + // // StartChartManage() + // // .sendEchoMessage(payload: imageBytes, toPeerId: toPeerId); + // }, + // ), + // SubmitBtn( + // btnName: '停止', + // onClick: () async { + // StartChartManage().stopSendingRbcuInfoMessages(); + // }, + // ), if (F.isLite) Container() else diff --git a/lib/talk/startChart/command/message_command.dart b/lib/talk/startChart/command/message_command.dart index 784e3f67..e8ba8d03 100644 --- a/lib/talk/startChart/command/message_command.dart +++ b/lib/talk/startChart/command/message_command.dart @@ -6,6 +6,7 @@ import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart'; import 'package:star_lock/talk/startChart/constant/protocol_flag_constant.dart'; import 'package:star_lock/talk/startChart/constant/udp_constant.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart'; +import 'package:star_lock/talk/startChart/proto/ble_message.pb.dart'; import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart'; @@ -386,7 +387,7 @@ class MessageCommand { final payload = rbcuInfo.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, - MessageType: MessageTypeConstant.Resp, + MessageType: MessageTypeConstant.Req, MessageId: MessageId, SpTotal: 1, SpIndex: 1, @@ -401,6 +402,40 @@ class MessageCommand { return _hexToBytes(serializedBytesString); } + // 蓝牙消息 + static List bleMessage({ + required String FromPeerId, + required String ToPeerId, + required String bluetoothDeviceName, + required List bleStructData, + int? MessageId, + int? timeout = 30, + int? IdleTimeout = 0, + }) { + final bleReq = BleReq( + bluetoothDeviceName: bluetoothDeviceName, + structData: bleStructData, + timeout: timeout, + idleTimeout: 0, + ); + final payload = bleReq.writeToBuffer(); + ScpMessage message = ScpMessage( + ProtocolFlag: ProtocolFlagConstant.scp01, + MessageType: MessageTypeConstant.Req, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, + FromPeerId: FromPeerId, + ToPeerId: ToPeerId, + Payload: payload, + PayloadCRC: calculationCrc(Uint8List.fromList(payload)), + PayloadLength: payload.length, + PayloadType: PayloadTypeConstant.blePassthrough, + ); + String serializedBytesString = message.serialize(); + return _hexToBytes(serializedBytesString); + } + // 辅助方法:将16进制字符串转换为字节列表 static List _hexToBytes(String hex) { final bytes = []; diff --git a/lib/talk/startChart/entity/scp_message.dart b/lib/talk/startChart/entity/scp_message.dart index 2820ab61..411d9452 100644 --- a/lib/talk/startChart/entity/scp_message.dart +++ b/lib/talk/startChart/entity/scp_message.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/talk/startChart/exception/start_chart_message_exception.dart'; +import 'package:star_lock/talk/startChart/handle/impl/udp_heart_beat_handler.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handler_factory.dart'; diff --git a/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart b/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart index de492782..6e14815b 100644 --- a/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart @@ -1,8 +1,11 @@ +import 'dart:convert'; import 'dart:typed_data'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/talk/startChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; @@ -16,13 +19,16 @@ class UdpBlePassThroughHandler extends ScpMessageBaseHandle implements ScpMessageHandler { @override void handleReq(ScpMessage scpMessage) { - final BleResp bleResp = scpMessage.Payload; //TODO 收到蓝牙透传请求指令 } @override void handleResp(ScpMessage scpMessage) { - // TODO: 收到蓝牙透传指令回复 + final BleResp bleResp = scpMessage.Payload; + // 如果回复成功 + // if (bleResp.status == BleResp_StatusE.SUCCESS) { + AppLog.log('收到蓝牙消息回复:${bleResp.structData}'); + // } } @override @@ -41,8 +47,17 @@ class UdpBlePassThroughHandler extends ScpMessageBaseHandle int? spTotal, int? spIndex, int? messageId}) { - final BleResp bleResp = BleResp(); - bleResp.mergeFromBuffer(byte); - return bleResp; + if (messageType == MessageTypeConstant.Resp) { + final BleResp bleResp = BleResp(); + bleResp.mergeFromBuffer(byte); + return bleResp; + } else if (messageType == MessageTypeConstant.Req) { + final BleReq talkExpect = BleReq(); + talkExpect.mergeFromBuffer(byte); + return talkExpect; + } else { + String payload = utf8.decode(byte); + return payload; + } } } diff --git a/lib/talk/startChart/handle/impl/udp_rbcuInfo_handler.dart b/lib/talk/startChart/handle/impl/udp_rbcuInfo_handler.dart index 4d681588..ccdb7e42 100644 --- a/lib/talk/startChart/handle/impl/udp_rbcuInfo_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_rbcuInfo_handler.dart @@ -46,16 +46,20 @@ class UdpRbcuInfoHandler extends ScpMessageBaseHandle @override void handleReq(ScpMessage scpMessage) { - final RbcuInfo rbcuInfo = scpMessage.Payload(); + final RbcuInfo rbcuInfo = scpMessage.Payload; if (rbcuInfo.isResp) { // 如果是回复的消息 _handleResultRbcuInfo(rbcuInfo); + } else { + // 回复 + startChartManage.replyRbcuInfoMessage(ToPeerId: scpMessage.FromPeerId!); } + replySuccessMessage(scpMessage); } @override void handleResp(ScpMessage scpMessage) { - final GenericResp genericResp = scpMessage.Payload(); + final GenericResp genericResp = scpMessage.Payload; if (checkGenericRespSuccess(genericResp)) { // 收到回复之后停止重发 startChartManage.stopSendingRbcuInfoMessages(); @@ -65,5 +69,6 @@ class UdpRbcuInfoHandler extends ScpMessageBaseHandle /// 处理回复的rbcuInfo消息 void _handleResultRbcuInfo(RbcuInfo rbcuInfo) { P2pManage().communicationObjectRbcuInfo = rbcuInfo; + startChartManage.stopSendingRbcuInfoMessages(); } } diff --git a/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart index cc3977d7..f6ec6c8a 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart @@ -12,25 +12,21 @@ import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; +import 'package:star_lock/talk/startChart/views/talkView/talk_view_logic.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; import '../../start_chart_manage.dart'; class UdpTalkExpectHandler extends ScpMessageBaseHandle implements ScpMessageHandler { - final TalkViewState talkViewState = TalkViewState(); + final TalkViewState talkViewState = Get.put(TalkViewLogic()).state; @override void handleReq(ScpMessage scpMessage) { // 收到预期音视频数据请求 final TalkExpectReq talkExpect = scpMessage.Payload; - print('收到预期音视频数据请求:$talkExpect'); - // 回复请求 replySuccessMessage(scpMessage); - - // 启动发送通话数据 - // startChartManage.startTalkDataTimer(); } @override @@ -38,10 +34,13 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle // 收到预期音视频数据回复 final TalkExpectResp talkExpectResp = scpMessage.Payload; if (talkExpectResp != null) { - print('收到预期音视频数据回复'); + // print('收到预期音视频数据回复,scpMessage:$scpMessage'); // 停止发送预期数据的定时器 startChartManage.stopTalkExpectMessageTimer(); talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0; + // 收到预期数据的应答后,代表建立了连接,启动通话保持的监听 + // 启动通话保持监听定时器(用来判断如果x秒内没有收到通话保持则执行的操作); + talkePingOverTimeTimerManager.start(); } } diff --git a/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart index a2261aa3..d0355198 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart @@ -15,17 +15,17 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle implements ScpMessageHandler { @override void handleReq(ScpMessage scpMessage) { - if (talkStatus.status != TalkStatus.answeredSuccessfully) { - // 如果不是接听中,不处理通话中挂断请求 - return; - } + // if (talkStatus.status != TalkStatus.answeredSuccessfully) { + // // 如果不是接听中,不处理通话中挂断请求 + // return; + // } + print('收到通话中挂断请求'); // 回复请求 replySuccessMessage(scpMessage); talkStatus.setHangingUpDuring(); stopRingtone(); StartChartManage().stopTalkExpectMessageTimer(); StartChartManage().stopTalkPingMessageTimer(); - } @override diff --git a/lib/talk/startChart/handle/impl/udp_talk_ping_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_ping_handler.dart index e3230f6f..59cbabeb 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_ping_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_ping_handler.dart @@ -15,15 +15,13 @@ class UdpTalkPingHandler extends ScpMessageBaseHandle void handleReq(ScpMessage scpMessage) { // 收到通话保持请求,回复成功消息 replySuccessMessage(scpMessage); + talkePingOverTimeTimerManager.renew(); } @override void handleResp(ScpMessage scpMessage) { - // 收到通话保持回复 - // print('收到通话保持回复'); final GenericResp genericResp = scpMessage.Payload; if (checkGenericRespSuccess(genericResp)) { - // 收到消息,续签定时器 talkePingOverTimeTimerManager.renew(); } } diff --git a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart index 7436fa10..cc664390 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart @@ -20,6 +20,8 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle implements ScpMessageHandler { @override void handleReq(ScpMessage scpMessage) async { + // 回复成功 + replySuccessMessage(scpMessage); // 判断是否登录账户 final loginData = await Storage.getLoginData(); if (loginData == null || @@ -28,11 +30,8 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle // 如果已经是等待接听了,就不在处理剩下的请求 return; } - // 回复成功 - replySuccessMessage(scpMessage); // 收到对讲请求 final TalkReq talkReq = scpMessage.Payload; - startChartManage.FromPeerId = scpMessage.ToPeerId!; startChartManage.ToPeerId = scpMessage.FromPeerId!; // 处理收到接听请求后的事件 @@ -64,8 +63,6 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle _showTalkRequestNotification(talkObjectName: talkObjectName); // 设置为等待接听状态 talkStatus.setWaitingAnswer(); - // 启动通话保持 - _handleStartTalkPing(); // 启动对讲请求超时定时器 talkeRequestOverTimeTimerManager.start(); // 收到呼叫请求,跳转到接听页面 @@ -123,12 +120,4 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle // 修改预期数据并启动发送预期数据定时器,在收到回复时停止 startChartManage.sendOnlyImageVideoTalkExpectData(); } - - // 启动通话保持,判断x秒内是否收到通话保持 - void _handleStartTalkPing() { - // 启动通话保持 - startChartManage.startTalkPingMessageTimer(); - // 启动通话保持监听定时器(用来判断如果x秒内没有收到通话保持则执行的操作) - talkePingOverTimeTimerManager.start(); - } } diff --git a/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart index 8e06288b..4e9921d4 100644 --- a/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart @@ -5,7 +5,8 @@ import 'package:get/get.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; +import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; + class TalkDataOverTimeTimerManager { // 单例实例 diff --git a/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart index d2510c2c..12cc2e51 100644 --- a/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart @@ -5,7 +5,7 @@ import 'package:get/get.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; +import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; class TalkePingOverTimeTimerManager { // 单例实例 @@ -41,6 +41,8 @@ class TalkePingOverTimeTimerManager { // 启动定时器 void start() { + // 取消之前的定时器 + _timer?.cancel(); _timer = Timer(timeout, onTimeout); } diff --git a/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart index 264c6f5c..6db54119 100644 --- a/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart @@ -5,7 +5,7 @@ import 'package:get/get.dart'; import 'package:star_lock/talk/startChart/constant/talk_constant.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; +import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; class TalkeRequestOverTimeTimerManager { // 单例实例 @@ -31,6 +31,7 @@ class TalkeRequestOverTimeTimerManager { EasyLoading.showToast('通话未接通,以挂断', duration: 2000.milliseconds); // 超时未接听,发送挂断请求 StartChartManage().sendTalkRejectMessage(); + talkStatus.setInitializationCompleted(); Get.back(); } } diff --git a/lib/talk/startChart/handle/scp_message_base_handle.dart b/lib/talk/startChart/handle/scp_message_base_handle.dart index b34860c3..281c2738 100644 --- a/lib/talk/startChart/handle/scp_message_base_handle.dart +++ b/lib/talk/startChart/handle/scp_message_base_handle.dart @@ -22,7 +22,8 @@ import 'package:star_lock/talk/startChart/handle/other/talke_request_over_time_t import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; + +import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; class ScpMessageBaseHandle { /// 使用单例 TimerManager diff --git a/lib/talk/startChart/handle/scp_message_handler_factory.dart b/lib/talk/startChart/handle/scp_message_handler_factory.dart index 8818da28..1a57c7cb 100644 --- a/lib/talk/startChart/handle/scp_message_handler_factory.dart +++ b/lib/talk/startChart/handle/scp_message_handler_factory.dart @@ -1,5 +1,6 @@ import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_ble_passthrough_handler.dart'; +import 'package:star_lock/talk/startChart/handle/impl/udp_rbcuInfo_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_talk_request_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_echo_test_handler.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_gateway_reset_handler.dart'; @@ -55,7 +56,7 @@ class ScpMessageHandlerFactory { case PayloadTypeConstant.talkHangup: return UdpTalkHangUpHandler(); case PayloadTypeConstant.RbcuInfo: - return UdpTalkHangUpHandler(); + return UdpRbcuInfoHandler(); default: return UnKnowPayloadTypeHandler(); } diff --git a/lib/talk/startChart/p2p/p2p_manage.dart b/lib/talk/startChart/p2p/p2p_manage.dart index 20f4c551..54e3e1a7 100644 --- a/lib/talk/startChart/p2p/p2p_manage.dart +++ b/lib/talk/startChart/p2p/p2p_manage.dart @@ -1,14 +1,25 @@ +import 'dart:async'; +import 'dart:io'; + import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart'; class P2pManage { + // 常量定义 + static const String testMessage = 'Hello'; // 测试消息 + static const int localPort = 0; // 绑定本地端口(0 表示由系统分配) + static const Duration connectionTimeout = Duration(seconds: 5); // 连接超时时间 + static const List localNetworkPrefixes = [ + '192.168.', + '10.', + '172.' + ]; // 局域网 IP 前缀 + RbcuInfo? communicationObjectRbcuInfo; - - void init(){ - + void init() { + // 初始化逻辑 } - // 解析 address 属性,提取对方的 IP 和端口 List> parseRemoteAddresses() { final addresses = communicationObjectRbcuInfo?.address ?? []; @@ -18,4 +29,80 @@ class P2pManage { }).toList(); } + // 判断是否为局域网 IP + bool _isLocalNetworkIp(String ip) { + for (final prefix in localNetworkPrefixes) { + if (ip.startsWith(prefix)) { + // 处理 172.16.x.x 到 172.31.x.x + if (prefix == '172.') { + final secondOctet = int.tryParse(ip.split('.')[1]) ?? 0; + if (secondOctet >= 16 && secondOctet <= 31) { + return true; + } + } else { + return true; + } + } + } + return false; + } + + // 创建 UDP 连接 + Future createUdpConnection() async { + final addresses = parseRemoteAddresses(); + + // 优先使用局域网 IP + addresses.sort((a, b) { + final isALocal = _isLocalNetworkIp(a['ip']!); + final isBLocal = _isLocalNetworkIp(b['ip']!); + if (isALocal && !isBLocal) return -1; // a 是局域网 IP,优先级更高 + if (!isALocal && isBLocal) return 1; // b 是局域网 IP,优先级更高 + return 0; // 优先级相同 + }); + + // 尝试连接 + for (final addr in addresses) { + final ip = addr['ip']!; + final port = int.parse(addr['port']!); + + try { + final socket = await RawDatagramSocket.bind( + InternetAddress.anyIPv4, localPort); // 绑定本地端口 + + // 发送测试数据 + final testData = testMessage.codeUnits; + socket.send(testData, InternetAddress(ip), port); + + // 设置超时时间 + final completer = Completer(); + + // 监听响应 + socket.listen((event) { + if (event == RawSocketEvent.read) { + final datagram = socket.receive(); + if (datagram != null) { + final response = String.fromCharCodes(datagram.data); + print('收到来自 $ip:$port 的响应: $response'); + completer.complete(); // 收到响应,完成 Future + } + } + }); + + // 等待响应或超时 + try { + await completer.future.timeout(connectionTimeout); + print('成功连接到 $ip:$port'); + return; // 连接成功,退出循环 + } on TimeoutException { + print('连接到 $ip:$port 超时'); + } finally { + socket.close(); // 关闭 socket + } + } catch (e) { + print('连接到 $ip:$port 失败: $e'); + } + } + + print('无法连接到任何地址'); + } } diff --git a/lib/talk/startChart/proto/ble_message.pb.dart b/lib/talk/startChart/proto/ble_message.pb.dart index dafffacc..8cb6d168 100644 --- a/lib/talk/startChart/proto/ble_message.pb.dart +++ b/lib/talk/startChart/proto/ble_message.pb.dart @@ -17,18 +17,27 @@ import 'ble_message.pbenum.dart'; export 'ble_message.pbenum.dart'; +/// 用于蓝牙透传的数据结构 class BleReq extends $pb.GeneratedMessage { factory BleReq({ + $core.int? timeout, $core.String? bluetoothDeviceName, $core.List<$core.int>? structData, + $core.int? idleTimeout, }) { final $result = create(); + if (timeout != null) { + $result.timeout = timeout; + } if (bluetoothDeviceName != null) { $result.bluetoothDeviceName = bluetoothDeviceName; } if (structData != null) { $result.structData = structData; } + if (idleTimeout != null) { + $result.idleTimeout = idleTimeout; + } return $result; } BleReq._() : super(); @@ -36,8 +45,10 @@ class BleReq extends $pb.GeneratedMessage { factory BleReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleReq', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create) + ..a<$core.int>(1, _omitFieldNames ? '' : 'Timeout', $pb.PbFieldType.OU3, protoName: 'Timeout') ..aOS(2, _omitFieldNames ? '' : 'bluetoothDeviceName', protoName: 'bluetoothDeviceName') ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData') + ..a<$core.int>(6, _omitFieldNames ? '' : 'IdleTimeout', $pb.PbFieldType.OU3, protoName: 'IdleTimeout') ..hasRequiredFields = false ; @@ -62,25 +73,45 @@ class BleReq extends $pb.GeneratedMessage { static BleReq getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static BleReq? _defaultInstance; + /// 扫描+发送+接受的总超时时间,单位为秒 + @$pb.TagNumber(1) + $core.int get timeout => $_getIZ(0); + @$pb.TagNumber(1) + set timeout($core.int v) { $_setUnsignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasTimeout() => $_has(0); + @$pb.TagNumber(1) + void clearTimeout() => clearField(1); + /// 用唯一的设备名来进行匹配而不是mac地址 @$pb.TagNumber(2) - $core.String get bluetoothDeviceName => $_getSZ(0); + $core.String get bluetoothDeviceName => $_getSZ(1); @$pb.TagNumber(2) - set bluetoothDeviceName($core.String v) { $_setString(0, v); } + set bluetoothDeviceName($core.String v) { $_setString(1, v); } @$pb.TagNumber(2) - $core.bool hasBluetoothDeviceName() => $_has(0); + $core.bool hasBluetoothDeviceName() => $_has(1); @$pb.TagNumber(2) void clearBluetoothDeviceName() => clearField(2); /// 下面是蓝牙结构内容,未加密状态 @$pb.TagNumber(3) - $core.List<$core.int> get structData => $_getN(1); + $core.List<$core.int> get structData => $_getN(2); @$pb.TagNumber(3) - set structData($core.List<$core.int> v) { $_setBytes(1, v); } + set structData($core.List<$core.int> v) { $_setBytes(2, v); } @$pb.TagNumber(3) - $core.bool hasStructData() => $_has(1); + $core.bool hasStructData() => $_has(2); @$pb.TagNumber(3) void clearStructData() => clearField(3); + + /// 空闲断开时间(秒),0为立即断开 + @$pb.TagNumber(6) + $core.int get idleTimeout => $_getIZ(3); + @$pb.TagNumber(6) + set idleTimeout($core.int v) { $_setUnsignedInt32(3, v); } + @$pb.TagNumber(6) + $core.bool hasIdleTimeout() => $_has(3); + @$pb.TagNumber(6) + void clearIdleTimeout() => clearField(6); } class BleResp extends $pb.GeneratedMessage { @@ -103,7 +134,7 @@ class BleResp extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BleResp', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create) ..e(1, _omitFieldNames ? '' : 'Status', $pb.PbFieldType.OE, protoName: 'Status', defaultOrMaker: BleResp_StatusE.SUCCESS, valueOf: BleResp_StatusE.valueOf, enumValues: BleResp_StatusE.values) - ..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData') + ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'StructData', $pb.PbFieldType.OY, protoName: 'StructData') ..hasRequiredFields = false ; @@ -138,15 +169,15 @@ class BleResp extends $pb.GeneratedMessage { @$pb.TagNumber(1) void clearStatus() => clearField(1); - /// 下面是蓝牙结构内容,未加密状态 - @$pb.TagNumber(4) + /// 下面是蓝牙结构内容 + @$pb.TagNumber(2) $core.List<$core.int> get structData => $_getN(1); - @$pb.TagNumber(4) + @$pb.TagNumber(2) set structData($core.List<$core.int> v) { $_setBytes(1, v); } - @$pb.TagNumber(4) + @$pb.TagNumber(2) $core.bool hasStructData() => $_has(1); - @$pb.TagNumber(4) - void clearStructData() => clearField(4); + @$pb.TagNumber(2) + void clearStructData() => clearField(2); } diff --git a/lib/talk/startChart/proto/ble_message.pbenum.dart b/lib/talk/startChart/proto/ble_message.pbenum.dart index 1ee7e541..783c475b 100644 --- a/lib/talk/startChart/proto/ble_message.pbenum.dart +++ b/lib/talk/startChart/proto/ble_message.pbenum.dart @@ -18,16 +18,16 @@ class BleResp_StatusE extends $pb.ProtobufEnum { static const BleResp_StatusE SUCCESS = BleResp_StatusE._(0, _omitEnumNames ? '' : 'SUCCESS'); static const BleResp_StatusE FAIL = BleResp_StatusE._(1, _omitEnumNames ? '' : 'FAIL'); static const BleResp_StatusE NOT_FOUND = BleResp_StatusE._(2, _omitEnumNames ? '' : 'NOT_FOUND'); - static const BleResp_StatusE CANNOT_CONNECT = BleResp_StatusE._(3, _omitEnumNames ? '' : 'CANNOT_CONNECT'); - static const BleResp_StatusE CANNOT_SEND = BleResp_StatusE._(4, _omitEnumNames ? '' : 'CANNOT_SEND'); + static const BleResp_StatusE CONNECT_FAIL = BleResp_StatusE._(3, _omitEnumNames ? '' : 'CONNECT_FAIL'); + static const BleResp_StatusE SEND_FAIL = BleResp_StatusE._(4, _omitEnumNames ? '' : 'SEND_FAIL'); static const BleResp_StatusE TIMEOUT = BleResp_StatusE._(5, _omitEnumNames ? '' : 'TIMEOUT'); static const $core.List values = [ SUCCESS, FAIL, NOT_FOUND, - CANNOT_CONNECT, - CANNOT_SEND, + CONNECT_FAIL, + SEND_FAIL, TIMEOUT, ]; diff --git a/lib/talk/startChart/proto/ble_message.pbjson.dart b/lib/talk/startChart/proto/ble_message.pbjson.dart index d37f2fd4..24cf64d9 100644 --- a/lib/talk/startChart/proto/ble_message.pbjson.dart +++ b/lib/talk/startChart/proto/ble_message.pbjson.dart @@ -19,20 +19,23 @@ const BleReq$json = { '2': [ {'1': 'bluetoothDeviceName', '3': 2, '4': 1, '5': 9, '10': 'bluetoothDeviceName'}, {'1': 'StructData', '3': 3, '4': 1, '5': 12, '10': 'StructData'}, + {'1': 'Timeout', '3': 1, '4': 1, '5': 13, '10': 'Timeout'}, + {'1': 'IdleTimeout', '3': 6, '4': 1, '5': 13, '10': 'IdleTimeout'}, ], }; /// Descriptor for `BleReq`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List bleReqDescriptor = $convert.base64Decode( 'CgZCbGVSZXESMAoTYmx1ZXRvb3RoRGV2aWNlTmFtZRgCIAEoCVITYmx1ZXRvb3RoRGV2aWNlTm' - 'FtZRIeCgpTdHJ1Y3REYXRhGAMgASgMUgpTdHJ1Y3REYXRh'); + 'FtZRIeCgpTdHJ1Y3REYXRhGAMgASgMUgpTdHJ1Y3REYXRhEhgKB1RpbWVvdXQYASABKA1SB1Rp' + 'bWVvdXQSIAoLSWRsZVRpbWVvdXQYBiABKA1SC0lkbGVUaW1lb3V0'); @$core.Deprecated('Use bleRespDescriptor instead') const BleResp$json = { '1': 'BleResp', '2': [ {'1': 'Status', '3': 1, '4': 1, '5': 14, '6': '.main.BleResp.StatusE', '10': 'Status'}, - {'1': 'StructData', '3': 4, '4': 1, '5': 12, '10': 'StructData'}, + {'1': 'StructData', '3': 2, '4': 1, '5': 12, '10': 'StructData'}, ], '4': [BleResp_StatusE$json], }; @@ -44,8 +47,8 @@ const BleResp_StatusE$json = { {'1': 'SUCCESS', '2': 0}, {'1': 'FAIL', '2': 1}, {'1': 'NOT_FOUND', '2': 2}, - {'1': 'CANNOT_CONNECT', '2': 3}, - {'1': 'CANNOT_SEND', '2': 4}, + {'1': 'CONNECT_FAIL', '2': 3}, + {'1': 'SEND_FAIL', '2': 4}, {'1': 'TIMEOUT', '2': 5}, ], }; @@ -53,7 +56,7 @@ const BleResp_StatusE$json = { /// Descriptor for `BleResp`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List bleRespDescriptor = $convert.base64Decode( 'CgdCbGVSZXNwEi0KBlN0YXR1cxgBIAEoDjIVLm1haW4uQmxlUmVzcC5TdGF0dXNFUgZTdGF0dX' - 'MSHgoKU3RydWN0RGF0YRgEIAEoDFIKU3RydWN0RGF0YSJhCgdTdGF0dXNFEgsKB1NVQ0NFU1MQ' - 'ABIICgRGQUlMEAESDQoJTk9UX0ZPVU5EEAISEgoOQ0FOTk9UX0NPTk5FQ1QQAxIPCgtDQU5OT1' - 'RfU0VORBAEEgsKB1RJTUVPVVQQBQ=='); + 'MSHgoKU3RydWN0RGF0YRgCIAEoDFIKU3RydWN0RGF0YSJdCgdTdGF0dXNFEgsKB1NVQ0NFU1MQ' + 'ABIICgRGQUlMEAESDQoJTk9UX0ZPVU5EEAISEAoMQ09OTkVDVF9GQUlMEAMSDQoJU0VORF9GQU' + 'lMEAQSCwoHVElNRU9VVBAF'); diff --git a/lib/talk/startChart/proto/ble_message.proto b/lib/talk/startChart/proto/ble_message.proto index a93c011c..4a2e0b13 100644 --- a/lib/talk/startChart/proto/ble_message.proto +++ b/lib/talk/startChart/proto/ble_message.proto @@ -3,26 +3,29 @@ package main; option go_package = "./spb"; // 用于蓝牙透传的数据结构 - message BleReq { // 用唯一的设备名来进行匹配而不是mac地址 string bluetoothDeviceName = 2; // 下面是蓝牙结构内容,未加密状态 bytes StructData = 3; + // 扫描+发送+接受的总超时时间,单位为秒 + uint32 Timeout = 1; + // 空闲断开时间(秒),0为立即断开 + uint32 IdleTimeout = 6; } message BleResp { // 定义一个枚举状态【成功,失败,找不到设备,无法建立连接,无法发送数据,超时】 enum StatusE { - SUCCESS = 0; - FAIL = 1; - NOT_FOUND = 2; - CANNOT_CONNECT = 3; - CANNOT_SEND = 4; - TIMEOUT = 5; + SUCCESS = 0; // 成功 + FAIL = 1; // 其他失败(需要错误消息) + NOT_FOUND = 2; // 找不到设备 + CONNECT_FAIL = 3; // 建立连接失败 + SEND_FAIL = 4; // 发送数据失败 + TIMEOUT = 5; // 超时 } // 状态 StatusE Status = 1; - // 下面是蓝牙结构内容,未加密状态 - bytes StructData = 4; + // 下面是蓝牙结构内容 + bytes StructData = 2; } diff --git a/lib/talk/startChart/start_chart_manage.dart b/lib/talk/startChart/start_chart_manage.dart index 2462bb0e..1d6b366e 100644 --- a/lib/talk/startChart/start_chart_manage.dart +++ b/lib/talk/startChart/start_chart_manage.dart @@ -29,7 +29,7 @@ import 'package:star_lock/talk/startChart/proto/rbcu.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pbserver.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; +import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/deviceInfo_utils.dart'; import 'package:star_lock/tools/storage.dart'; @@ -221,7 +221,8 @@ class StartChartManage { } // 发送RbcuInfo 地址交换消息 - void _sendRbcuInfoMessage() async { + void _sendRbcuInfoMessage( + {required String ToPeerId, bool isResp = false}) async { final uuid = _uuid.v1(); final int timestamp = DateTime.now().millisecondsSinceEpoch; final Int64 int64Timestamp = Int64(timestamp); // 使用构造函数 @@ -252,7 +253,7 @@ class StartChartManage { name: uuid, address: address, time: int64Timestamp, - isResp: false, + isResp: isResp, ); final message = MessageCommand.genericRbcuInfoMessage( ToPeerId: ToPeerId, @@ -264,12 +265,12 @@ class StartChartManage { } // 启动定时任务 - void startSendingRbcuInfoMessages() { + void startSendingRbcuInfoMessages({required String ToPeerId}) { // 每隔 1 秒执行一次 _sendRbcuInfoMessage rbcuInfoTimer ??= Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) { // 发送RbcuInfo 地址交换消息 - _sendRbcuInfoMessage(); + _sendRbcuInfoMessage(ToPeerId: ToPeerId); }); } @@ -279,6 +280,11 @@ class StartChartManage { rbcuInfoTimer = null; } + // 回复RbcuInfo + void replyRbcuInfoMessage({required String ToPeerId}) { + _sendRbcuInfoMessage(ToPeerId: ToPeerId, isResp: true); + } + // 发送上线消息 Future _sendOnlineMessage() async { if (isOnlineStartChartServer) { @@ -329,7 +335,7 @@ class StartChartManage { MessageCommand.getNextMessageId(ToPeerId, increment: false); // 组装分包数据 final message = MessageCommand.talkDataMessage( - ToPeerId: ToPeerId, + ToPeerId: 'D78Fo4CjNzUXz8DxuUhLtcRpnGFXhSzhzs191XzhJttS', FromPeerId: FromPeerId, payload: packet, SpTotal: totalPackets, @@ -891,8 +897,36 @@ class StartChartManage { talkExpect: talkExpectReq); } + /// 发送远程开锁 + void sendRemoteUnLockMessage({ + required String bluetoothDeviceName, + required List openLockCommand, + }) { + sendBleMessage( + bluetoothDeviceName: bluetoothDeviceName, + bleStructData: openLockCommand, + ); + } + + /// 发送蓝牙透传消息 + void sendBleMessage({ + required String bluetoothDeviceName, + required List bleStructData, + }) { + // 组装上线消息 + final message = MessageCommand.bleMessage( + FromPeerId: FromPeerId, + ToPeerId: ToPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), + bluetoothDeviceName: bluetoothDeviceName, + bleStructData: bleStructData, + ); + _sendMessage(message: message); + } + /// 销毁资源 void destruction() async { + sendTalkHangupMessage(); isOnlineStartChartServer = false; stopHeartbeat(); stopTalkExpectMessageTimer(); diff --git a/lib/talk/startChart/appLifecycle_observer.dart b/lib/talk/startChart/status/appLifecycle_observer.dart similarity index 96% rename from lib/talk/startChart/appLifecycle_observer.dart rename to lib/talk/startChart/status/appLifecycle_observer.dart index 9f4dab42..7100e71c 100644 --- a/lib/talk/startChart/appLifecycle_observer.dart +++ b/lib/talk/startChart/status/appLifecycle_observer.dart @@ -25,7 +25,7 @@ class AppLifecycleObserver extends WidgetsBindingObserver { void onAppPaused() { // 处理应用程序进入后台的逻辑 print('App has entered the background.'); - StartChartManage().destruction(); + // StartChartManage().destruction(); } void onAppResumed() { diff --git a/lib/talk/startChart/start_chart_talk_status.dart b/lib/talk/startChart/status/start_chart_talk_status.dart similarity index 100% rename from lib/talk/startChart/start_chart_talk_status.dart rename to lib/talk/startChart/status/start_chart_talk_status.dart diff --git a/lib/talk/startChart/views/talkView/talk_view_logic.dart b/lib/talk/startChart/views/talkView/talk_view_logic.dart index 8f4e92a4..e29393d2 100644 --- a/lib/talk/startChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/startChart/views/talkView/talk_view_logic.dart @@ -16,6 +16,13 @@ import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/blue/blue_manage.dart'; +import 'package:star_lock/blue/io_protocol/io_openLock.dart'; +import 'package:star_lock/blue/io_tool/io_tool.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_logic.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_state.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/lockNetToken_entity.dart'; +import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; @@ -24,12 +31,16 @@ import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; +import 'package:star_lock/talk/udp/udp_manage.dart'; +import 'package:star_lock/talk/udp/udp_senderManage.dart'; +import 'package:star_lock/tools/bugly/bugly_tool.dart'; +import 'package:star_lock/tools/storage.dart'; import '../../../../tools/baseGetXController.dart'; class TalkViewLogic extends BaseGetXController { final TalkViewState state = TalkViewState(); - + final LockDetailState lockDetailState = Get.find().state; Timer? _syncTimer; // 音视频播放刷新率定时器 int _startTime = 0; // 开始播放时间戳,用于判断帧数据中的时间戳位置 final int bufferSize = 20; // 缓冲区大小(以帧为单位) @@ -258,7 +269,61 @@ class TalkViewLogic extends BaseGetXController { } /// 开门 - udpOpenDoorAction(List list) async {} + udpOpenDoorAction() async { + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = changeStringListToIntList(privateKey!); + + final List? signKey = await Storage.getStringList(saveBlueSignKey); + final List signKeyDataList = changeStringListToIntList(signKey!); + + final List? token = await Storage.getStringList(saveBlueToken); + final List getTokenList = changeStringListToIntList(token!); + + await _getLockNetToken(); + + final OpenLockCommand openLockCommand = OpenLockCommand( + lockID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + openMode: lockDetailState.openDoorModel, + openTime: _getUTCNetTime(), + onlineToken: lockDetailState.lockNetToken, + token: getTokenList, + needAuthor: 1, + signKey: signKeyDataList, + privateKey: getPrivateKeyList, + ); + final messageDetail = openLockCommand.messageDetail(); + // 发送远程开门消息 + StartChartManage().sendRemoteUnLockMessage( + bluetoothDeviceName: BlueManage().connectDeviceName, + openLockCommand: messageDetail, + ); + showToast('已发送开门通知'); + } + + int _getUTCNetTime() { + if (lockDetailState.isHaveNetwork) { + return DateTime.now().millisecondsSinceEpoch ~/ 1000 + + lockDetailState.differentialTime; + } else { + return 0; + } + } + + // 获取手机联网token,根据锁设置里面获取的开锁时是否联网来判断是否调用这个接口 + Future _getLockNetToken() async { + final LockNetTokenEntity entity = await ApiRepository.to.getLockNetToken( + lockId: lockDetailState.keyInfos.value.lockId.toString()); + if (entity.errorCode!.codeIsSuccessful) { + lockDetailState.lockNetToken = entity.data!.token!.toString(); + AppLog.log('从服务器获取联网token:${lockDetailState.lockNetToken}'); + } else { + BuglyTool.uploadException( + message: '点击了需要联网开锁', detail: '点击了需要联网开锁 获取连网token失败', upload: true); + showToast('网络访问失败,请检查网络是否正常'.tr, something: () {}); + } + } /// 获取权限状态 Future getPermissionStatus() async { @@ -285,6 +350,55 @@ class TalkViewLogic extends BaseGetXController { } } + Future requestPermissions() async { + // 申请存储权限 + var storageStatus = await Permission.storage.request(); + // 申请录音权限 + var microphoneStatus = await Permission.microphone.request(); + + if (storageStatus.isGranted && microphoneStatus.isGranted) { + print("Permissions granted"); + } else { + print("Permissions denied"); + // 如果权限被拒绝,可以提示用户或跳转到设置页面 + if (await Permission.storage.isPermanentlyDenied) { + openAppSettings(); // 跳转到应用设置页面 + } + } + } + + Future startRecording() async { + requestPermissions(); + if (state.isRecordingScreen.value) { + showToast('录屏已开始,请勿重复点击'); + } + bool start = await FlutterScreenRecording.startRecordScreen( + "Screen Recording", // 视频文件名 + titleNotification: "Recording in progress", // 通知栏标题 + messageNotification: "Tap to stop recording", // 通知栏内容 + ); + + if (start) { + state.isRecordingScreen.value = true; + } + } + + Future stopRecording() async { + String path = await FlutterScreenRecording.stopRecordScreen; + print("Recording saved to: $path"); + + // 将视频保存到系统相册 + bool? success = await GallerySaver.saveVideo(path); + if (success == true) { + print("Video saved to gallery"); + } else { + print("Failed to save video to gallery"); + } + + showToast('录屏结束,已保存到系统相册'); + state.isRecordingScreen.value = false; + } + @override void onReady() { super.onReady(); @@ -310,12 +424,16 @@ class TalkViewLogic extends BaseGetXController { // 初始化录音控制器 _initAudioRecorder(); + + requestPermissions(); } @override void onClose() { _stopPlayG711Data(); state.listData.value = Uint8List(0); + state.audioBuffer.clear(); + state.videoBuffer.clear(); _syncTimer?.cancel(); _syncTimer = null; } @@ -387,32 +505,6 @@ class TalkViewLogic extends BaseGetXController { } } - /// 开始录屏 - Future startRecording() async { - getPermissionStatus(); - bool started = - await FlutterScreenRecording.startRecordScreenAndAudio("Recording"); - if (started) { - state.isRecordingScreen.value = true; - } - } - - /// 停止录屏 - Future stopRecording() async { - String path = await FlutterScreenRecording.stopRecordScreen; - if (path != null) { - state.isRecordingScreen.value = false; - // 保存录制的视频到相册 - // await GallerySaver.saveVideo(path).then((bool? success) {}); - // 将截图保存到相册 - await ImageGallerySaver.saveFile(path); - showToast('录屏已保存到相册'.tr); - } else { - state.isRecordingScreen.value = false; - print("Recording failed"); - } - } - /// 初始化音频录制器 void _initAudioRecorder() { state.voiceProcessor = VoiceProcessor.instance; diff --git a/lib/talk/startChart/views/talkView/talk_view_page.dart b/lib/talk/startChart/views/talkView/talk_view_page.dart index bc64d9cc..dad73f75 100644 --- a/lib/talk/startChart/views/talkView/talk_view_page.dart +++ b/lib/talk/startChart/views/talkView/talk_view_page.dart @@ -1,6 +1,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'dart:math'; +import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -15,6 +17,7 @@ import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_logic.dart'; import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; +import 'package:star_lock/talk/udp/udp_manage.dart'; import '../../../../app_settings/app_colors.dart'; import '../../../../tools/showTFView.dart'; @@ -35,6 +38,7 @@ class _TalkViewPageState extends State void initState() { super.initState(); + state.listData.value = Uint8List(0); //写一个定时器,三十秒后页面自动返回 // state.autoBackTimer = Timer(const Duration(seconds: 30), Get.back); @@ -65,43 +69,61 @@ class _TalkViewPageState extends State alignment: Alignment.center, children: [ Obx( - () => state.listData.value.isEmpty - ? Image.asset( - 'images/main/monitorBg.png', - width: ScreenUtil().screenWidth, - height: ScreenUtil().screenHeight, - fit: BoxFit.cover, - ) - : Container( - decoration: state.isRecordingScreen.value - ? BoxDecoration( - border: Border.all(color: Colors.red, width: 1)) - : BoxDecoration(), - child: PopScope( + () { + final screenWidth = MediaQuery.of(context).size.width; + final screenHeight = MediaQuery.of(context).size.height; + + final logicalWidth = MediaQuery.of(context).size.width; + final logicalHeight = MediaQuery.of(context).size.height; + final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; + + // 计算物理像素值 + final physicalWidth = logicalWidth * devicePixelRatio; + final physicalHeight = logicalHeight * devicePixelRatio; + + // 旋转后的图片尺寸 + final rotatedImageWidth = 480; // 原始高度 + final rotatedImageHeight = 864; // 原始宽度 + + // 计算缩放比例 + final scaleWidth = physicalWidth / rotatedImageWidth; + final scaleHeight = physicalHeight / rotatedImageHeight; + final scale = max(scaleWidth, scaleHeight); // 选择较大的缩放比例 + + return state.listData.value.isEmpty + ? Image.asset( + 'images/main/monitorBg.png', + width: screenWidth, + height: screenHeight, + fit: BoxFit.cover, + ) + : PopScope( canPop: false, child: RepaintBoundary( key: state.globalKey, - child: RotatedBox( - quarterTurns: 1, // 顺时针旋转 90 度(1 个四分之一圈) - child: Image.memory( - state.listData.value, - gaplessPlayback: true, - width: 1.sw, - height: 1.sh, - fit: BoxFit.cover, - filterQuality: FilterQuality.high, - errorBuilder: ( - BuildContext context, - Object error, - StackTrace? stackTrace, - ) { - return Container(color: Colors.transparent); - }, + child: Transform.rotate( + angle: + state.rotateAngle.value * (pi / 180), // 旋转 90 度 + child: Transform.scale( + scale: scale, // 动态计算的缩放比例 + child: Image.memory( + state.listData.value, + gaplessPlayback: true, + fit: BoxFit.cover, + filterQuality: FilterQuality.high, + errorBuilder: ( + BuildContext context, + Object error, + StackTrace? stackTrace, + ) { + return Container(color: Colors.transparent); + }, + ), ), ), ), - ), - ), + ); + }, ), Obx(() => state.listData.value.isEmpty ? Positioned( @@ -200,13 +222,12 @@ class _TalkViewPageState extends State GestureDetector( onTap: () async { logic.showToast('功能暂未开放'.tr); - // if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { + // if ( + // state.talkStatus.value == TalkStatus.answeredSuccessfully) { // if (state.isRecordingScreen.value) { // await logic.stopRecording(); - // print('停止录屏'); // } else { // await logic.startRecording(); - // print('开始录屏'); // } // } }, @@ -276,7 +297,14 @@ class _TalkViewPageState extends State 'images/main/icon_lockDetail_monitoringUnlock.png', '开锁', AppColors.mainColor, - onClick: () {}, + onClick: () { + if (UDPManage().remoteUnlock == 1) { + logic.udpOpenDoorAction(); + // showDeletPasswordAlertDialog(context); + } else { + logic.showToast('请在锁设置中开启远程开锁'.tr); + } + }, ) ]); } @@ -342,7 +370,7 @@ class _TalkViewPageState extends State context: context, builder: (BuildContext context) { return ShowTFView( - title: '请输入六位数字开锁密码'.tr, + title: '请输入6位数字开锁密码'.tr, tipTitle: '', controller: state.passwordTF, inputFormatters: [ @@ -350,22 +378,23 @@ class _TalkViewPageState extends State FilteringTextInputFormatter.allow(RegExp('[0-9]')), ], sureClick: () async { - // //发送删除锁请求 + //发送删除锁请求 // if (state.passwordTF.text.isEmpty) { // logic.showToast('请输入开锁密码'.tr); // return; // } - // - // // List numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList(); - // // 开锁 - // // lockID - // List numbers = []; - // List lockIDData = utf8.encode(state.passwordTF.text); + + // List numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList(); + // 开锁 + // lockID + // final List numbers = []; + // final List lockIDData = utf8.encode(state.passwordTF.text); // numbers.addAll(lockIDData); // // topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length); // for (int i = 0; i < 6 - lockIDData.length; i++) { // numbers.add(0); // } + logic.udpOpenDoorAction(); }, cancelClick: () { Get.back(); @@ -409,6 +438,8 @@ class _TalkViewPageState extends State state.animationController.dispose(); state.realTimePicTimer.cancel(); state.autoBackTimer.cancel(); + state.videoBuffer.clear(); + state.listData.value = Uint8List(0); CallTalk().finishAVData(); super.dispose(); } diff --git a/lib/talk/startChart/views/talkView/talk_view_state.dart b/lib/talk/startChart/views/talkView/talk_view_state.dart index eb3593ed..05029877 100644 --- a/lib/talk/startChart/views/talkView/talk_view_state.dart +++ b/lib/talk/startChart/views/talkView/talk_view_state.dart @@ -10,7 +10,7 @@ import 'package:network_info_plus/network_info_plus.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; +import 'package:star_lock/talk/startChart/status/start_chart_talk_status.dart'; import '../../../../tools/storage.dart';