Merge branch 'release_sky' into 'master_sky'

Release sky

See merge request StarlockTeam/app-starlock!229
This commit is contained in:
李仪 2025-07-30 02:36:33 +00:00
commit dcd1b9a140
89 changed files with 3412 additions and 242 deletions

View File

@ -1153,5 +1153,11 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. تمكين وظيفة الفتح عن بعد للقفل في APP (يتم إيقاف هذه الوظيفة بشكل افتراضي). إذا كان هذا الخيار غير متاح، لن يدعم القفل جوجل هوم",
"3.安装Google Home APP点击左上角的加号按钮": "3. قم بتثبيت تطبيق Google Home وانقر فوق الزر زائد في الزاوية العلوية اليسرى",
"暂无最新记录": "لا توجد حاليا أحدث السجلات المتاحة",
"请将手机切换至2.4G WiFi进行手动连接": "الرجاء تحويل هاتفك إلى \"واي فاي 2.4\" للاتصال اليدوي"
"请将手机切换至2.4G WiFi进行手动连接": "الرجاء تحويل هاتفك إلى \"واي فاي 2.4\" للاتصال اليدوي",
"第三方平台设置": "الطرف الثالث منصة الإعداد",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "قفل مجموعة صوت",
"(中国台湾)": "(中国台湾)",
"男声": "ذكر صوت",
"女声": "صوت بنات"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Активирайте функцията за дистанционно отключване на ключалката в приложението (тази функция е изключена по подразбиране). Ако тази опция не е налице, заключването няма да поддържа Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Инсталирайте приложението Google Home и щракнете върху бутона плюс в горния ляв ъгъл",
"暂无最新记录": "В момента няма най-новите налични записи",
"请将手机切换至2.4G WiFi进行手动连接": "Моля, превключете телефона си на 2.4G WiFi за ръчно свързване"
"请将手机切换至2.4G WiFi进行手动连接": "Моля, превключете телефона си на 2.4G WiFi за ръчно свързване",
"语音包设置": "Настройки на гласовите пакети",
"第三方平台设置": "Настройки на платформи на трети страни",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Заключване на настройките на гласовия пакет",
"(中国台湾)": "(中国台湾)",
"男声": "Мъжки глас",
"女声": "Женски глас"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. অ্যাপে লকের রিমোট আনলকিং ফাংশন সক্ষম করুন (এই ফাংশনটি ডিফল্টরূপে বন্ধ রয়েছে)। যদি এই বিকল্পটি উপলভ্য না হয় তবে লকটি গুগল হোম সমর্থন করবে না",
"3.安装Google Home APP点击左上角的加号按钮": "গুগল হোম অ্যাপ্লিকেশনটি ইনস্টল করুন এবং উপরের বাম কোণে প্লাস বোতামটি ক্লিক করুন",
"暂无最新记录": "বর্তমানে কোনও সাম্প্রতিকতম রেকর্ড সুলভ নেই",
"请将手机切换至2.4G WiFi进行手动连接": "ম্যানুয়াল সংযোগের জন্য দয়া করে আপনার ফোনটি 2.4 জি ওয়াইফাইতে স্যুইচ করুন"
"请将手机切换至2.4G WiFi进行手动连接": "ম্যানুয়াল সংযোগের জন্য দয়া করে আপনার ফোনটি 2.4 জি ওয়াইফাইতে স্যুইচ করুন",
"语音包设置": "ভয়েস প্যাকেজ সেটিংস",
"第三方平台设置": "তৃতীয় পক্ষের প্ল্যাটফর্ম সেটিংস",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "ভয়েস প্যাকেজ সেটিংস লক করুন",
"(中国台湾)": "(中国台湾)",
"男声": "পুরুষের কণ্ঠ",
"女声": "নারী কণ্ঠ"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Povolte funkci dálkového odemykání zámku v APP (tato funkce je ve výchozím nastavení vypnutá). Pokud tato možnost není k dispozici, zámek nebude podporovat Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Nainstalujte aplikaci Google Home a klikněte na tlačítko plus v levém horním rohu",
"暂无最新记录": "Momentálně nejsou k dispozici žádné nejnovější záznamy",
"请将手机切换至2.4G WiFi进行手动连接": "Přepněte prosím svůj telefon na 2.4G WiFi pro ruční připojení"
"请将手机切换至2.4G WiFi进行手动连接": "Přepněte prosím svůj telefon na 2.4G WiFi pro ruční připojení",
"语音包设置": "Nastavení hlasového balíčku",
"第三方平台设置": "Nastavení platformy třetích stran",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Zamknout nastavení hlasového balíčku",
"(中国台湾)": "(中国台湾)",
"男声": "Mužský hlas",
"女声": "Ženský hlas"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Aktiver fjernoplåsningsfunktionen for låsen i APP'en (denne funktion er slået fra som standard). Hvis denne mulighed ikke er tilgængelig, understøtter låsen ikke Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installer Google Home-appen, og klik på plusknappen i øverste venstre hjørne",
"暂无最新记录": "Der er i øjeblikket ingen nyeste optegnelser tilgængelige",
"请将手机切换至2.4G WiFi进行手动连接": "Skift venligst din telefon til 2.4G WiFi for manuel forbindelse"
"请将手机切换至2.4G WiFi进行手动连接": "Skift venligst din telefon til 2.4G WiFi for manuel forbindelse",
"语音包设置": "Indstillinger af stemmepakke",
"第三方平台设置": "Indstillinger af tredjepartsplatforme",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Lås stemmepakkeindstillinger",
"(中国台湾)": "(中国台湾)",
"男声": "Mandlige stemmer",
"女声": "Kvindelige stemmer"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Entsichern in einer APP, die ein schloss öffnet (standard abschalten) Wenn diese option nicht verfügbar ist, wird das schloss google nicht unterstützen",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installiert die google-app und klicken auf den knopf hinzufügen in der oberen linken ecke",
"暂无最新记录": "Wir haben keine neuen daten",
"请将手机切换至2.4G WiFi进行手动连接": "Wenn manuelle verbindung hergestellt wird, schalten sie das handy auf 2,4 G WiFi"
"请将手机切换至2.4G WiFi进行手动连接": "Wenn manuelle verbindung hergestellt wird, schalten sie das handy auf 2,4 G WiFi",
"语音包设置": "Sprachpaketeinstellungen",
"第三方平台设置": "Einstellungen von Drittanbieterplattformen",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Sperren von Sprachpaketeinstellungen",
"(中国台湾)": "(中国台湾)",
"男声": "Männliche Stimme",
"女声": "Frauenstimme"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Ενεργοποιήστε τη λειτουργία απομακρυσμένου ξεκλειδώματος της κλειδαριάς στην εφαρμογή (αυτή η λειτουργία είναι απενεργοποιημένη από προεπιλογή). Εάν αυτή η επιλογή δεν είναι διαθέσιμη, το κλείδωμα δεν θα υποστηρίζει το Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Εγκαταστήστε την εφαρμογή Google Home και κάντε κλικ στο κουμπί συν στην επάνω αριστερή γωνία",
"暂无最新记录": "Προς το παρόν δεν υπάρχουν διαθέσιμες τελευταίες εγγραφές",
"请将手机切换至2.4G WiFi进行手动连接": "Αλλάξτε το τηλέφωνό σας σε 2.4G WiFi για χειροκίνητη σύνδεση"
"请将手机切换至2.4G WiFi进行手动连接": "Αλλάξτε το τηλέφωνό σας σε 2.4G WiFi για χειροκίνητη σύνδεση",
"语音包设置": "Ρυθμίσεις πακέτου φωνής",
"第三方平台设置": "Ρυθμίσεις πλατφόρμας τρίτων",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Ρυθμίσεις κλειδώματος πακέτου φωνής",
"(中国台湾)": "(中国台湾)",
"男声": "Ανδρική φωνή",
"女声": "Γυναικεία φωνή"
}

View File

@ -1159,5 +1159,12 @@
"请确认后再继续": "Please confirm before continuing",
"需要相机权限": "Camera permission required",
"此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "The activation and deactivation of this feature can only be done through Bluetooth on the phone near the lock",
"网关添加成功": "Gateway added successfully"
"网关添加成功": "Gateway added successfully",
"语音包设置": "Voice packet settings",
"第三方平台设置": "Third party platform settings",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Lock voice package settings",
"(中国台湾)": "(中国台湾)",
"男声": "male voice",
"女声": "female voice"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Habilitar la función de desbloqueo remoto del bloqueo en la aplicación (esta función se desactiva por defecto). Si esta opción no está disponible, el bloqueo no será compatible con Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Instale la aplicación de Google Home y haga clic en el botón más en la esquina superior izquierda",
"暂无最新记录": "Actualmente no hay registros más recientes disponibles",
"请将手机切换至2.4G WiFi进行手动连接": "Por favor cambia tu teléfono a 2.4G WiFi para la conexión manual"
"请将手机切换至2.4G WiFi进行手动连接": "Por favor cambia tu teléfono a 2.4G WiFi para la conexión manual",
"语音包设置": "Configuración del paquete de voz",
"第三方平台设置": "Configuración de la Plataforma de terceros",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Configuración del paquete de voz de bloqueo",
"(中国台湾)": "(中国台湾)",
"男声": "Voz masculina",
"女声": "Voz femenina"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Lubage rakenduses APP luku kaugavamise funktsioon (see funktsioon on vaikimisi välja lülitatud). Kui see valik pole saadaval, ei toeta lukk Google Home'i",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installige rakendus Google Home ja klõpsake vasakus ülanurgas plussnuppu",
"暂无最新记录": "Praegu pole uusimaid andmeid saadaval",
"请将手机切换至2.4G WiFi进行手动连接": "Käsitsi ühendamiseks lülitage telefon 2.4G WiFi-le"
"请将手机切换至2.4G WiFi进行手动连接": "Käsitsi ühendamiseks lülitage telefon 2.4G WiFi-le",
"语音包设置": "Häälepaketi seadistused",
"第三方平台设置": "Kolmanda osapoole platvormi seaded",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Lukustage häälepaketi seaded",
"(中国台湾)": "(中国台湾)",
"男声": "Meeste hääl",
"女声": "Naiste hääl"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Ota lukon etälukituksen avaustoiminto käyttöön APP:ssa (tämä toiminto on oletuksena pois päältä). Jos tämä vaihtoehto ei ole käytettävissä, lukko ei tue Google Homea",
"3.安装Google Home APP点击左上角的加号按钮": "3. Asenna Google Home -sovellus ja napsauta vasemmassa yläkulmassa olevaa pluspainiketta",
"暂无最新记录": "Viimeisimpiä tietoja ei ole tällä hetkellä saatavilla",
"请将手机切换至2.4G WiFi进行手动连接": "Vaihda puhelimesi 2.4G WiFi-verkkoon manuaalista yhteyttä varten"
"请将手机切换至2.4G WiFi进行手动连接": "Vaihda puhelimesi 2.4G WiFi-verkkoon manuaalista yhteyttä varten",
"语音包设置": "Äänipaketin asetukset",
"第三方平台设置": "Kolmannen osapuolen alustan asetukset",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Lukitse äänipaketin asetukset",
"(中国台湾)": "(中国台湾)",
"男声": "Miehen ääni",
"女声": "Naisten ääni"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Activez la fonction de déverrouillage à distance de la serrure dans lapplication (cette fonction est désactivée par défaut). Si cette option nest pas disponible, le verrou ne prendra pas en charge Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installez lapplication Google Home et cliquez sur le bouton plus dans le coin supérieur gauche",
"暂无最新记录": "Il ny a actuellement aucun dernier enregistrement disponible",
"请将手机切换至2.4G WiFi进行手动连接": "Veuillez passer votre téléphone à 2.4G WiFi pour une connexion manuelle"
"请将手机切换至2.4G WiFi进行手动连接": "Veuillez passer votre téléphone à 2.4G WiFi pour une connexion manuelle",
"语音包设置": "Paramètres du pack vocal",
"第三方平台设置": "Paramètres de plate - forme tierce",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Paramètres du pack Lock Voice",
"(中国台湾)": "(中国台湾)",
"男声": "Voix masculine",
"女声": "Voix de femmes"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. הפעל את פונקציית ביטול הנעילה מרחוק של המנעול באפליקציה (פונקציה זו כבויה כברירת מחדל). אם אפשרות זו אינה זמינה, המנעול לא יתמוך ב-Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. התקן את אפליקציית Google Home ולחץ על כפתור הפלוס בפינה השמאלית העליונה",
"暂无最新记录": "אין כרגע רשומות עדכניות זמינות",
"请将手机切换至2.4G WiFi进行手动连接": "אנא העבר את הטלפון שלך ל- WiFi 2.4G לחיבור ידני"
"请将手机切换至2.4G WiFi进行手动连接": "אנא העבר את הטלפון שלך ל- WiFi 2.4G לחיבור ידני",
"语音包设置": "הגדרות חבילת קול",
"第三方平台设置": "הגדרות פלטפורמות של צד שלישי",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "הגדרות חבילת קול לנעול",
"(中国台湾)": "(中国台湾)",
"男声": "קול גבר",
"女声": "קול נשי"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. एप्लिकेशन में लॉक का रिमोट अनलॉकिंग फ़ंक्शन सक्षम करें (यह फ़ंक्शन डिफ़ॉल्ट रूप से बंद है). यदि यह विकल्प उपलब्ध नहीं है, तो लॉक आपके गूगल होम को सपोर्ट नहीं करेगा।",
"3.安装Google Home APP点击左上角的加号按钮": "3. गूगल होम ऐप को इंस्टॉल करें और ऊपरी बाएं कोने में प्लस बटन पर क्लिक करें।",
"暂无最新记录": "वर्तमान में कोई नवीनतम रिकॉर्ड उपलब्ध नहीं हैं",
"请将手机切换至2.4G WiFi进行手动连接": "मैन्युअल कनेक्शन के लिए कृपया अपना फोन 2.4 जी वाईफ़ाई पर स्विच करें।"
"请将手机切换至2.4G WiFi进行手动连接": "मैन्युअल कनेक्शन के लिए कृपया अपना फोन 2.4 जी वाईफ़ाई पर स्विच करें।",
"语音包设置": "आवाज पैकेज सेटिंग्स",
"第三方平台设置": "तृतीय पक्ष मंच सेटिंग्स",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "आवाज पैकेज सेटिंग्स ताला लगाएँ",
"(中国台湾)": "(中国台湾)",
"男声": "पुरुष आवाज",
"女声": "महिला आवाज"
}

View File

@ -1154,5 +1154,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2.喺APP中開啟鎖嘅遠程解鎖功能此功能默認關閉。 如果此選項不可用則鎖將唔撐Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3.安裝Google Home應用點擊左上角嘅加號掣",
"暂无最新记录": "目前冇可用嘅最新記錄",
"请将手机切换至2.4G WiFi进行手动连接": "請把手機切換到2.4G WiFi進行手動連接"
"请将手机切换至2.4G WiFi进行手动连接": "請把手機切換到2.4G WiFi進行手動連接",
"语音包设置": "語音包設定",
"第三方平台设置": "協力廠商領獎臺設定",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "鎖語音包設定",
"(中国台湾)": "(中国台湾)",
"男声": "男聲",
"女声": "女聲"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Omogućite funkciju daljinskog otključavanja brave u APP-u (ova je funkcija prema zadanim postavkama isključena). Ako ova opcija nije dostupna, zaključavanje neće podržavati Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Instalirajte aplikaciju Google Home i kliknite gumb plus u gornjem lijevom kutu",
"暂无最新记录": "Trenutno nema dostupnih najnovijih podataka",
"请将手机切换至2.4G WiFi进行手动连接": "Prebacite telefon na 2.4G WiFi za ručno povezivanje"
"请将手机切换至2.4G WiFi进行手动连接": "Prebacite telefon na 2.4G WiFi za ručno povezivanje",
"语音包设置": "Postavke glasovnog paketa",
"第三方平台设置": "Postavljanje podiuma treće strane",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Postavke zaključavanja glasovnog paketa",
"(中国台湾)": "(中国台湾)",
"男声": "Muški glas",
"女声": "Ženski glas"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Engedélyezze a zár távoli feloldási funkcióját az APP-ban (ez a funkció alapértelmezés szerint ki van kapcsolva). Ha ez az opció nem érhető el, a zár nem támogatja a Google Home szolgáltatást",
"3.安装Google Home APP点击左上角的加号按钮": "3. Telepítse a Google Home alkalmazást, és kattintson a plusz gombra a bal felső sarokban",
"暂无最新记录": "Jelenleg nem állnak rendelkezésre legfrissebb rekordok",
"请将手机切换至2.4G WiFi进行手动连接": "Kérjük, kapcsolja át telefonját 2.4G WiFi-re a kézi csatlakozáshoz"
"请将手机切换至2.4G WiFi进行手动连接": "Kérjük, kapcsolja át telefonját 2.4G WiFi-re a kézi csatlakozáshoz",
"语音包设置": "Hangcsomag beállításai",
"第三方平台设置": "Harmadik fél platformjának beállítása",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Hangcsomag zárolási beállításai",
"(中国台湾)": "(中国台湾)",
"男声": "Férfi hang",
"女声": "női hang"
}

View File

@ -1159,5 +1159,12 @@
"请确认后再继续": "Խնդրում ենք հաստատել շարունակելուց առաջ",
"需要相机权限": "Պահանջվում է տեսախցիկի թույլտվություն",
"此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "Այս գործառույթի ակտիվացումը եւ ապաակտիվացումը կարելի է կատարել միայն կողպեքի մոտ գտնվող հեռախոսի Bluetooth-ի միջոցով",
"网关添加成功": "Gateway հաջողությամբ ավելացվել է"
"网关添加成功": "Gateway հաջողությամբ ավելացվել է",
"语音包设置": "Ձայնային փաթեթի պարամետրեր",
"第三方平台设置": "Երրորդ կողմի հարթակի կարգավորումներ",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Փակել ձայնային փաթեթի պարամետրերը",
"(中国台湾)": "(中国台湾)",
"男声": "տղամարդկանց ձայն",
"女声": "կանանց ձայն"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Aktifkan fungsi kunci pengunci jarak jauh di aplikasi (fungsi ini dimatikan secara standar). Jika opsi ini tidak tersedia, kunci tidak akan mendukung Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Instal aplikasi Google Home dan klik tombol plus di sudut kiri atas",
"暂无最新记录": "Saat ini tidak ada catatan terbaru yang tersedia",
"请将手机切换至2.4G WiFi进行手动连接": "Silahkan beralih ke 2.4G WiFi untuk koneksi manual"
"请将手机切换至2.4G WiFi进行手动连接": "Silahkan beralih ke 2.4G WiFi untuk koneksi manual",
"语音包设置": "Pengaturan paket suara",
"第三方平台设置": "Platform pihak ketiga diatur",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Mengunci paket suara",
"(中国台湾)": "(中国台湾)",
"男声": "6 tahun sebelumnya",
"女声": "Suara wanita"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Abilita la funzione di sblocco remoto del lock nella APP (questa funzione è disattivata in modo predefinito). Se questa opzione non è disponibile, il lock non supporta Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installa lapplicazione Home di Google e fai clic sul pulsante più nellangolo in alto a sinistra",
"暂无最新记录": "Attualmente non sono disponibili dati più recenti",
"请将手机切换至2.4G WiFi进行手动连接": "Passa il telefono a 2,4g WiFi per la connessione manuale"
"请将手机切换至2.4G WiFi进行手动连接": "Passa il telefono a 2,4g WiFi per la connessione manuale",
"语音包设置": "Impostazioni pacchetto vocalea",
"第三方平台设置": "Impostazioni di piattaforme di terze parti",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Impostazioni pacchetto vocale blocco",
"(中国台湾)": "(中国台湾)",
"男声": "voce maschile",
"女声": "voce femminile"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. アプリでロックのリモートロック解除機能を有効にします(この機能はデフォルトでオフになっています)。このオプションが利用できない場合、ロックはgoogle homeをサポートしません",
"3.安装Google Home APP点击左上角的加号按钮": "3. google homeアプリをインストールし、左上隅のプラスボタンをクリックします",
"暂无最新记录": "最新の記録は残っていない",
"请将手机切换至2.4G WiFi进行手动连接": "手動接続のため、携帯電話を2.4 g wifiに切り替えてください"
"请将手机切换至2.4G WiFi进行手动连接": "手動接続のため、携帯電話を2.4 g wifiに切り替えてください",
"语音包设置": "ボイスパックの設定",
"第三方平台设置": "サードパーティ製プラットフォームの設定",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "ロック音声パケット設定",
"(中国台湾)": "(中国台湾)",
"男声": "男声",
"女声": "女声"
}

View File

@ -1159,5 +1159,12 @@
"请确认后再继续": "გაგრძელებამდე გთხოვთ დაადასტუროთ",
"需要相机权限": "კამერის ნებართვა საჭიროა",
"此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "ამ ფუნქციის გააქტიურება და დეაქტივაცია შეიძლება გაკეთდეს მხოლოდ Bluetooth ის საშუალებით ტელეფონით დაბლოკვის მახლობლად",
"网关添加成功": "კარიბჭე წარმატებით დაემატა"
"网关添加成功": "კარიბჭე წარმატებით დაემატა",
"语音包设置": "ხმის პაკეტის პარამეტრები",
"第三方平台设置": "მესამე მხარის პლატფორმის პარამეტრები",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "ხმის პაკეტის პარამეტრები",
"(中国台湾)": "(中国台湾)",
"男声": "მამაკაცის ხმა",
"女声": "ქალის ხმა"
}

View File

@ -1101,7 +1101,7 @@
"支持的国家": "支持的国家",
"支持的国家值": "美国、加拿大、英国、澳大利亚、印度、德国、法国、意大利、西班牙、日本",
"操作流程": "操作流程",
"操作流程值":"1 用智能锁APP添加锁和网关\n\n2 在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Alexa \n\n3 在Alexa中添加Skill并用智能锁APP的账号和密码进行授权。授权成功后就可以发现账号下的设备\n\n4 在Alexa app里找到锁开启语音开锁的功能并设置语言密码\n\n5 可以通过Alexa操作锁了",
"操作流程值": "1 用智能锁APP添加锁和网关\n\n2 在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Alexa \n\n3 在Alexa中添加Skill并用智能锁APP的账号和密码进行授权。授权成功后就可以发现账号下的设备\n\n4 在Alexa app里找到锁开启语音开锁的功能并设置语言密码\n\n5 可以通过Alexa操作锁了",
"Google Home": "Google Home",
"Action name": "Action name",
"ScienerSmart": "ScienerSmart",
@ -1164,5 +1164,12 @@
"请确认后再继续": "请确认后再继续",
"需要相机权限": "需要相机权限",
"此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "此功能的开启和关闭只能在锁附近通过手机蓝牙进行",
"网关添加成功": "网关添加成功"
"网关添加成功": "网关添加成功",
"第三方平台设置": "第三方平台设置",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "锁语音包设置",
"语音包设置": "语音包设置",
"(中国台湾)": "(中国台湾)",
"男声": "男声",
"女声": "女声"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. APP бағдарламасында құлыпты қашықтан ашу функциясын қосу (бұл функция әдепкі бойынша өшіріледі). Егер бұл параметр қол жетімді болмаса, бұғаттау Google Home-ды қолдамайды",
"3.安装Google Home APP点击左上角的加号按钮": "3. Google Home бағдарламасын орнатып, жоғарғы сол жақ бұрыштағы қосу түймешігін басыңыз",
"暂无最新记录": "Қазіргі уақытта қол жетімді соңғы жазбалар жоқ",
"请将手机切换至2.4G WiFi进行手动连接": "Телефонды қолмен қосу үшін 2.4G WiFi бағдарламасына ауыстыруыңызды сұраймыз"
"请将手机切换至2.4G WiFi进行手动连接": "Телефонды қолмен қосу үшін 2.4G WiFi бағдарламасына ауыстыруыңызды сұраймыз",
"语音包设置": "Дауыстық бума параметрлері",
"第三方平台设置": "Үшінші тарап платформасының параметрлері",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Дауыстық бума параметрлерін құлыптау",
"(中国台湾)": "(中国台湾)",
"男声": "ер дауысы",
"女声": "Әйел дауысы"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. 앱에서 잠금의 원격 잠금 해제 기능을 활성화합니다 (이 기능은 기본적으로 꺼져 있습니다).이 옵션을 사용할 수 없는 경우 잠금은 Google Home을 지원하지 않습니다",
"3.安装Google Home APP点击左上角的加号按钮": "3. 구글 홈 앱을 설치하고 왼쪽 상단 모서리에 있는 더하기 버튼을 클릭합니다",
"暂无最新记录": "현재 사용 가능한 최신 레코드가 없습니다",
"请将手机切换至2.4G WiFi进行手动连接": "수동 연결을 위해 핸드폰을 2.4G WiFi로 바꿔주세요"
"请将手机切换至2.4G WiFi进行手动连接": "수동 연결을 위해 핸드폰을 2.4G WiFi로 바꿔주세요",
"语音包设置": "음성 팩 설정",
"第三方平台设置": "타사 플랫폼 설정",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "음성팩 설정 잠금",
"(中国台湾)": "(中国台湾)",
"男声": "남성",
"女声": "여성 목소리"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Įjunkite užrakto nuotolinio atrakinimo funkciją APP (ši funkcija yra išjungta pagal numatytuosius nustatymus). Jei ši parinktis nepasiekiama, užraktas nepalaikys \"Google Home\"",
"3.安装Google Home APP点击左上角的加号按钮": "3. Įdiekite \"Google Home\" programą ir spustelėkite pliuso mygtuką viršutiniame kairiajame kampe",
"暂无最新记录": "Šiuo metu nėra naujausių įrašų",
"请将手机切换至2.4G WiFi进行手动连接": "Perjunkite telefoną į 2.4G WiFi, kad galėtumėte prisijungti rankiniu būdu"
"请将手机切换至2.4G WiFi进行手动连接": "Perjunkite telefoną į 2.4G WiFi, kad galėtumėte prisijungti rankiniu būdu",
"语音包设置": "Balso paketo nustatymai",
"第三方平台设置": "Trečiosios šalies platformos nustatymai",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Balso paketo nustatymų užrakinimas",
"(中国台湾)": "(中国台湾)",
"男声": "vyriškas balsas",
"女声": "Moteriškas balsas"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Dayakan fungsi buka kunci jauh kunci dalam APP (fungsi ini dimatikan secara lalai). Jika pilihan ini tidak tersedia, kunci tidak akan menyokong Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Pasang apl Google Home dan klik butang tambah di penjuru kiri sebelah atas",
"暂无最新记录": "Pada masa ini tiada rekod terkini tersedia",
"请将手机切换至2.4G WiFi进行手动连接": "Sila tukar telefon anda kepada WiFi 2.4G untuk sambungan manual"
"请将手机切换至2.4G WiFi进行手动连接": "Sila tukar telefon anda kepada WiFi 2.4G untuk sambungan manual",
"语音包设置": "Balso paketo nustatymai",
"第三方平台设置": "Trečiosios šalies platformos nustatymai",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Balso paketo nustatymų užrakinimas",
"(中国台湾)": "(中国台湾)",
"男声": "vyriškas balsas",
"女声": "Moteriškas balsas"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Open het slot op afstand in de APP (standaard uitgeschakeld). Als deze optie niet beschikbaar is, wordt google Home niet ondersteund",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installeer de google home-app en klik op de plus-knop in de linkerbovenhoek",
"暂无最新记录": "Er zijn momenteel geen recente gegevens beschikbaar",
"请将手机切换至2.4G WiFi进行手动连接": "Stel uw telefoon in op 2. 4g WiFi bij handmatige verbinding"
"请将手机切换至2.4G WiFi进行手动连接": "Stel uw telefoon in op 2. 4g WiFi bij handmatige verbinding",
"语音包设置": "Voice Pack-instellingen",
"第三方平台设置": "Instellingen voor platforms van derden",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Instellingen voor spraakpakket vergrendelen",
"(中国台湾)": "(中国台湾)",
"男声": "mannelijke stem",
"女声": "Vrouwelijke stem"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Włącz funkcję zdalnego odblokowywania zamka w aplikacji (ta funkcja jest domyślnie wyłączona). Jeśli ta opcja nie jest dostępna, zamek nie będzie obsługiwał Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Zainstaluj aplikację Google Home i kliknij przycisk plusa w lewym górnym rogu",
"暂无最新记录": "Obecnie nie ma dostępnych najnowszych rekordów",
"请将手机切换至2.4G WiFi进行手动连接": "Przełącz telefon na 2.4G Wi-Fi, aby uzyskać ręczne połączenie"
"请将手机切换至2.4G WiFi进行手动连接": "Przełącz telefon na 2.4G Wi-Fi, aby uzyskać ręczne połączenie",
"语音包设置": "Ustawienia pakietu głosowego",
"第三方平台设置": "Ustawienia platformy stron trzecich",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Ustawienia blokowania pakietu głosowego",
"(中国台湾)": "(中国台湾)",
"男声": "Mężczyzna",
"女声": "Głos kobiecy"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Ative a função de desbloqueio remoto da fechadura no APP (esta função está desativada por padrão). Se esta opção não estiver disponível, o bloqueio não será compatível com o Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Instale o aplicativo Google Home e clique no botão de adição no canto superior esquerdo",
"暂无最新记录": "Atualmente não há registros mais recentes disponíveis",
"请将手机切换至2.4G WiFi进行手动连接": "Mude seu telefone para WiFi 2.4G para conexão manual"
"请将手机切换至2.4G WiFi进行手动连接": "Mude seu telefone para WiFi 2.4G para conexão manual",
"语音包设置": "Configurações do pacote de voz",
"第三方平台设置": "Configurações de plataformas de terceiros",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Configurações do pacote de voz bloqueada",
"(中国台湾)": "(中国台湾)",
"男声": "Voz masculina",
"女声": "voz feminina"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Activați funcția de deblocare de la distanță a încuietorului în aplicație (această funcție este dezactivată în mod implicit). Dacă această opțiune nu este disponibilă, blocarea nu va accepta Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Instalați aplicația Google Home și faceți clic pe butonul plus din colțul din stânga sus",
"暂无最新记录": "În prezent nu există cele mai recente înregistrări disponibile",
"请将手机切换至2.4G WiFi进行手动连接": "Vă rugăm să comutați telefonul la WiFi 2.4G pentru conectarea manuală"
"请将手机切换至2.4G WiFi进行手动连接": "Vă rugăm să comutați telefonul la WiFi 2.4G pentru conectarea manuală",
"语音包设置": "Setări pachet vocal",
"第三方平台设置": "Setarea platformei terțelor părți",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Configurarea pachetului vocal de blocare",
"(中国台湾)": "(中国台湾)",
"男声": "vocea bărbatului",
"女声": "Voce feminină"
}

View File

@ -1157,5 +1157,12 @@
"请确保网络是2.4GHz Wi-Fi": "Убедитесь, что сеть имеет 2,4 ГГц Wi - Fi",
"已选": "Выбранные",
"是否要远程开锁": "Нужно ли удалённо открывать замок",
"请将手机切换至2.4G WiFi进行手动连接": "Пожалуйста, переключите телефон на 2.4G WiFi для ручного подключения"
"请将手机切换至2.4G WiFi进行手动连接": "Пожалуйста, переключите телефон на 2.4G WiFi для ручного подключения",
"语音包设置": "Настройка голосового пакета",
"第三方平台设置": "Настройка платформы третьей стороны",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Запустить настройки голосового пакета",
"(中国台湾)": "(中国台湾)",
"男声": "Мужской голос",
"女声": "Женские голоса"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Povoľte funkciu diaľkového odomykania zámku v aplikácii APP (táto funkcia je predvolene vypnutá). Ak táto možnosť nie je k dispozícii, zámok nebude podporovať Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Nainštalujte si aplikáciu Google Home a kliknite na tlačidlo plus v ľavom hornom rohu",
"暂无最新记录": "Momentálne nie sú k dispozícii žiadne najnovšie záznamy",
"请将手机切换至2.4G WiFi进行手动连接": "Pre manuálne pripojenie prepnite telefón na 2.4G WiFi"
"请将手机切换至2.4G WiFi进行手动连接": "Pre manuálne pripojenie prepnite telefón na 2.4G WiFi",
"语音包设置": "Nastavenie hlasového balíka",
"第三方平台设置": "Nastavenie platformy tretích strán",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Zamknutie nastavení hlasového balíka",
"(中国台湾)": "(中国台湾)",
"男声": "mužský hlas",
"女声": "Ženský hlas"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2 . Омогућите функцију даљинског откључавања браве у АПП-у (ова функција је подразумевано искључена). Ако ова опција није доступна, брава неће подржати Гоогле Хоме",
"3.安装Google Home APP点击左上角的加号按钮": "3 . Инсталирајте апликацију Гоогле Хоме и кликните на дугме плус у горњем левом углу",
"暂无最新记录": "Тренутно нема доступних најновијих података",
"请将手机切换至2.4G WiFi进行手动连接": "Пребаците телефон на КСНУМКСГ ВиФи за ручно повезивање"
"请将手机切换至2.4G WiFi进行手动连接": "Пребаците телефон на КСНУМКСГ ВиФи за ручно повезивање",
"语音包设置": "Подешавања гласовног пакета",
"第三方平台设置": "Подешавања платформе трећих страна",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Закључајте подешавања говорног пакета",
"(中国台湾)": "(中国台湾)",
"男声": "мушки глас",
"女声": "женски глас"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Aktivera fjärrupplåsningsfunktionen för låset i APP (den här funktionen är avstängd som standard). Om det här alternativet inte är tillgängligt kommer låset inte att stödja Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Installera Google Home-appen och klicka på plusknappen i det övre vänstra hörnet",
"暂无最新记录": "Det finns för närvarande inga senaste poster tillgängliga",
"请将手机切换至2.4G WiFi进行手动连接": "Byt din telefon till 2.4G WiFi för manuell anslutning"
"请将手机切换至2.4G WiFi进行手动连接": "Byt din telefon till 2.4G WiFi för manuell anslutning",
"语音包设置": "Inställningar för röstpaket",
"第三方平台设置": "Inställningar för tredjepartsplattformar",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Lås inställningar för röstpaket",
"(中国台湾)": "(中国台湾)",
"男声": "Mänsklig röst",
"女声": "Kvinnlig röst"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. เปิดใช้งานฟังก์ชันการปลดล็อคระยะไกลของการล็อคในแอพ (ฟังก์ชันนี้ จะถูกปิดโดยค่าเริ่มต้น) หากไม่มีตัวเลือกนี้ การล็อคจะไม่สนับสนุนกูเกิ้ลโฮม",
"3.安装Google Home APP点击左上角的加号按钮": "3. ติดตั้ง googlehome แอพ และคลิกปุ่มบวก ที่มุมบนซ้าย",
"暂无最新记录": "ปัจจุบันยังไม่มีบันทึกล่าสุด ที่มีอยู่",
"请将手机切换至2.4G WiFi进行手动连接": "กรุณาเปลี่ยนโทรศัพท์เป็น 2.4 GWiFi สำหรับการเชื่อมต่อด้วยตนเอง"
"请将手机切换至2.4G WiFi进行手动连接": "กรุณาเปลี่ยนโทรศัพท์เป็น 2.4 GWiFi สำหรับการเชื่อมต่อด้วยตนเอง",
"语音包设置": "การตั้งค่าแพ็กเกจเสียง",
"第三方平台设置": "การตั้งค่าแพลตฟอร์มของบุคคลที่สาม",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "ล็อคการตั้งค่า Voice Pack",
"(中国台湾)": "(中国台湾)",
"男声": "เสียงผู้ชาย",
"女声": "เสียงผู้หญิง"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. APP'de kilidin uzaktan kilit açma işlevini etkinleştirin (bu işlev varsayılan olarak kapalıdır). Bu seçenek mevcut değilse, kilit Google Home'u desteklemeyecektir",
"3.安装Google Home APP点击左上角的加号按钮": "3. Google Home uygulamasını yükleyin ve sol üst köşedeki artı düğmesini tıklayın",
"暂无最新记录": "Şu anda en son kayıt mevcut değil",
"请将手机切换至2.4G WiFi进行手动连接": "Manuel bağlantı için lütfen telefonunuzu 2.4G WiFi'ye getirin"
"请将手机切换至2.4G WiFi进行手动连接": "Manuel bağlantı için lütfen telefonunuzu 2.4G WiFi'ye getirin",
"语音包设置": "Ses Paketi Ayarları",
"第三方平台设置": "Üçüncü Taraf Platform Ayarları",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Ses Paketi Ayarlarını Kilitle",
"(中国台湾)": "(中国台湾)",
"男声": "Erkek Sesi",
"女声": "Kadın Sesi"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. 在APP中開啓鎖的遠程開鎖功能默認關閉。如果這個選項不可用鎖將不支持谷歌Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. 安裝谷歌Home應用程序並單擊左上角的加號按鈕",
"暂无最新记录": "目前沒有最新的記錄",
"请将手机切换至2.4G WiFi进行手动连接": "手動連接時請將手機調至2.4G WiFi"
"请将手机切换至2.4G WiFi进行手动连接": "手動連接時請將手機調至2.4G WiFi",
"语音包设置": "語音包設定",
"第三方平台设置": "協力廠商領獎臺設定",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "鎖語音包設定",
"(中国台湾)": "(中国台湾)",
"男声": "男聲",
"女声": "女聲"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Увімкніть функцію дистанційного розблокування замка в APP (ця функція вимкнена за замовчуванням). Якщо ця опція недоступна, замок не підтримуватиме Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Встановіть програму Google Home і натисніть кнопку плюс у верхньому лівому кутку",
"暂无最新记录": "Наразі немає останніх доступних записів",
"请将手机切换至2.4G WiFi进行手动连接": "Будь ласка, перемкніть свій телефон на 2.4G WiFi для ручного підключення"
"请将手机切换至2.4G WiFi进行手动连接": "Будь ласка, перемкніть свій телефон на 2.4G WiFi для ручного підключення",
"语音包设置": "Параметри голосового пакету",
"第三方平台设置": "Налаштування платформи третьої сторони",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Параметри блокування голосового пакету",
"(中国台湾)": "(中国台湾)",
"男声": "Чоловічий голос",
"女声": "жіночий голос"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. اے پی پی میں لاک کے ریموٹ ان لاکنگ فنکشن کو فعال کریں (یہ فنکشن ڈیفالٹ طور پر بند ہے)۔ اگر یہ آپشن دستیاب نہیں ہے تو ، لاک گوگل ہوم کو سپورٹ نہیں کرے گا۔",
"3.安装Google Home APP点击左上角的加号按钮": "3. گوگل ہوم ایپ انسٹال کریں اور اوپری بائیں کونے میں پلس بٹن پر کلک کریں۔",
"暂无最新记录": "فی الحال کوئی تازہ ترین ریکارڈ دستیاب نہیں ہے",
"请将手机切换至2.4G WiFi进行手动连接": "براہ کرم دستی کنکشن کے لئے اپنے فون کو 2.4 جی وائی فائی پر سوئچ کریں"
"请将手机切换至2.4G WiFi进行手动连接": "براہ کرم دستی کنکشن کے لئے اپنے فون کو 2.4 جی وائی فائی پر سوئچ کریں",
"语音包设置": "صوتی پیکیج ترتیبات",
"第三方平台设置": "تھرڈ پارٹی پلیٹ فارم کی ترتیبات",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "صوتی پیکیج کی ترتیبات لاک کریں",
"(中国台湾)": "(中国台湾)",
"男声": "مردوں کی آواز",
"女声": "خواتین کی آواز"
}

View File

@ -1153,5 +1153,12 @@
"2.在APP里开启锁的远程开锁功能这个功能默认是关闭的。如果没有这个选项则锁不支持Google Home": "2. Kích hoạt chức năng mở khóa từ xa trong ứng dụng (chức năng này bị tắt theo mặc định). Nếu tùy chọn này không có sẵn, khóa sẽ không hỗ trợ Google Home",
"3.安装Google Home APP点击左上角的加号按钮": "3. Cài đặt ứng dụng Google Home và nhấn nút Plus ở góc trên bên trái",
"暂无最新记录": "Hiện tại không có hồ sơ mới nhất",
"请将手机切换至2.4G WiFi进行手动连接": "Vui lòng chuyển điện thoại sang 2.4G WiFi để kết nối bằng tay"
"请将手机切换至2.4G WiFi进行手动连接": "Vui lòng chuyển điện thoại sang 2.4G WiFi để kết nối bằng tay",
"语音包设置": "Thiết lập gói thoại",
"第三方平台设置": "Cài đặt nền tảng của bên thứ ba",
"涂鸦智能": "Tuya Smart",
"锁语音包设置": "Khóa cài đặt gói thoại",
"(中国台湾)": "(中国台湾)",
"男声": "Giọng nam",
"女声": "Giọng nữ"
}

View File

@ -1166,5 +1166,12 @@
"请确认后再继续": "请确认后再继续",
"需要相机权限": "需要相机权限",
"一键登录": "一键登录",
"网关添加成功": "网关添加成功"
"网关添加成功": "网关添加成功",
"第三方平台设置": "第三方平台设置",
"涂鸦智能": "涂鸦智能",
"锁语音包设置": "锁语音包设置",
"语音包设置": "语音包设置",
"(中国台湾)": "(中国台湾)",
"男声": "男声",
"女声": "女声"
}

View File

@ -71,21 +71,45 @@ class FirebaseHelper {
}
Future<void> initSdk() async {
FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
}
}
Future<void> login(String userId) async {
FirebaseAnalytics.instance.setUserId(id: userId);
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.setUserId(id: userId);
}
}
Future<void> trackEvent(
String eventName, Map<String, Object>? parameters) async {
FirebaseAnalytics.instance
.logEvent(name: eventName, parameters: parameters);
String eventName,
Map<String, Object>? parameters,
) async {
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.logEvent(
name: eventName,
parameters: parameters,
);
}
}
Future<void> logout() async {
FirebaseAnalytics.instance.setUserId(id: '');
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.setUserId(id: '');
}
}
}
//</com>

View File

@ -26,6 +26,8 @@ import 'package:star_lock/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dar
import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/openDoorDirection/openDoorDirection_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart';
import 'package:star_lock/main/lockDetail/messageWarn/addFamily/addFamily_page.dart';
import 'package:star_lock/main/lockDetail/messageWarn/lockUser/lockUser_page.dart';
import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpenDoor/coerceFingerprint/coerceFingerprint_page.dart';
@ -41,6 +43,7 @@ import 'package:star_lock/main/lockDetail/palm/palmList/palmList_page.dart';
import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetailChangeDate/passwordKeyDetailChangeDate_page.dart';
import 'package:star_lock/main/lockMian/lockMain/xhj/lockMain_xhj_page.dart';
import 'package:star_lock/mine/about/webviewShow_page.dart';
import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart';
import 'package:star_lock/mine/mine/safeVerify/safeVerify_page.dart';
import 'package:star_lock/mine/minePersonInfo/minePersonInfoEmail/mineBindPhoneOrEmail_page.dart';
import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart';
@ -59,6 +62,7 @@ import 'package:star_lock/mine/mineSet/transferSmartLock/selectBranch/selectBran
import 'package:star_lock/mine/mineSet/transferSmartLock/transferSmartLockList/transferSmartLock_page.dart';
import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_page.dart';
import 'package:star_lock/mine/valueAddedServices/advancedFunctionRecord/advancedFunctionRecord_page.dart';
import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_page.dart';
import 'package:star_lock/mine/valueAddedServices/valueAddedServicesRecord/value_added_services_record_page.dart';
import 'package:star_lock/talk/starChart/views/guide/permission_guidance_page.dart';
import 'package:star_lock/talk/starChart/views/native/talk_view_native_decode_page.dart';
@ -368,6 +372,8 @@ abstract class Routers {
'/valueAddedServicesRecordPage'; // -
static const String valueAddedServicesHighFunctionPage =
'/ValueAddedServicesHighFunctionPage'; // -
static const String valueAddedCloudStoragePage =
'/valueAddedCloudStoragePage'; // -
static const String valueAddedServicesBuyPage =
'/ValueAddedServicesBuyPage'; // -
static const String customSMSTemplateListPage =
@ -436,6 +442,10 @@ abstract class Routers {
'/AddLockSelectCountryPage'; //
static const String faceUnlockPage = '/faceUnlockPage'; //
static const String motorPowerPage = '/motorPowerPage'; //
static const String speechLanguageSettingsPage =
'/speechLanguageSettingsPage'; //
static const String thirdPartyPlatformPage =
'/thirdPartyPlatformPage'; //
static const String openDoorDirectionPage = '/openDoorDirectionPage'; //
static const String catEyeWorkModePage = '/catEyeWorkModePage'; //
static const String msgNotificationPage = '/msgNotificationPage'; //
@ -521,6 +531,7 @@ abstract class Routers {
'/imageTransmissionView'; //()
static const String permissionGuidancePage =
'/permissionGuidancePage'; //
static const String lockVoiceSettingPage = '/lockVoiceSetting'; //
}
abstract class AppRouters {
@ -904,6 +915,10 @@ abstract class AppRouters {
name: Routers.valueAddedServicesHighFunctionPage,
page: () => const ValueAddedServicesHighFunctionPage(),
),
GetPage<dynamic>(
name: Routers.valueAddedCloudStoragePage,
page: () => const CloudStoragePage(),
),
GetPage<dynamic>(
name: Routers.customSMSTemplateListPage,
page: () => const CustomSMSTemplateListPage(),
@ -1024,6 +1039,9 @@ abstract class AppRouters {
name: Routers.faceUnlockPage, page: () => const FaceUnlockPage()),
GetPage<dynamic>(
name: Routers.motorPowerPage, page: () => const MotorPowerPage()),
GetPage<dynamic>(
name: Routers.speechLanguageSettingsPage,
page: () => const SpeechLanguageSettingsPage()),
GetPage<dynamic>(
name: Routers.openDoorDirectionPage,
page: () => const OpenDoorDirectionPage()),
@ -1201,6 +1219,11 @@ abstract class AppRouters {
GetPage<dynamic>(
name: Routers.permissionGuidancePage,
page: () => PermissionGuidancePage()),
GetPage<dynamic>(
name: Routers.lockVoiceSettingPage, page: () => LockVoiceSetting()),
GetPage<dynamic>(
name: Routers.thirdPartyPlatformPage,
page: () => ThirdPartyPlatformPage()),
//
// GetPage<dynamic>(name: Routers.h264View, page: () => H264WebView()), // webview播放页面
];

View File

@ -348,21 +348,43 @@ class BlueManage {
} else {
// 128834
if (cleanUuid.length >= 32) {
final String thirdAndFourth = cleanUuid.substring(2, 4); // 23
for (final prefix in prefixes) {
if (thirdAndFourth == prefix) {
if (isSingle) {
return true; // isSingle为truetrue
} else {
// UUID的第31321
if (cleanUuid.length >= 32) {
String pairStatus =
cleanUuid.substring(30, 32); // 31321
// 00=01=
if (pairStatus == '00') {
return true; // true
if (deviceType == DeviceType.blue) {
final String thirdAndFourth = cleanUuid.substring(6, 8); // 23
for (final prefix in prefixes) {
if (thirdAndFourth == prefix) {
if (isSingle) {
return true; // isSingle为truetrue
} else {
// UUID的第31321
if (cleanUuid.length >= 32) {
String pairStatus =
cleanUuid.substring(30, 32); // 31321
// 00=01=
if (pairStatus == '00') {
return true; // true
}
// 01trueuuid
}
}
}
}
} else if (deviceType == DeviceType.gateway) {
final String thirdAndFourth = cleanUuid.substring(6, 8); // 23
for (final prefix in prefixes) {
if (thirdAndFourth == prefix) {
if (isSingle) {
return true; // isSingle为truetrue
} else {
// UUID的第31321
if (cleanUuid.length >= 32) {
String pairStatus =
cleanUuid.substring(30, 32); // 31321
// 00=01=
if (pairStatus == '00') {
return true; // true
}
// 01trueuuid
}
// 01trueuuid
}
}
}

View File

@ -0,0 +1,48 @@
import 'dart:convert';
import '../io_reply.dart';
import '../io_sender.dart';
import '../io_tool/io_tool.dart';
import '../io_type.dart';
class GetDeviceModelCommand extends SenderProtocol {
GetDeviceModelCommand({
this.lockID,
}) : super(CommandType.getDeviceModel);
String? lockID;
@override
String toString() {
return 'GetDeviceModelCommand{lockID: $lockID}';
}
@override
List<int> messageDetail() {
List<int> data = [];
//
final int type = commandType!.typeValue;
final double typeDouble = type / 256;
final int type1 = typeDouble.toInt();
final int type2 = type % 256;
data.add(type1);
data.add(type2);
final int length = utf8.encode(lockID!).length;
data.addAll(utf8.encode(lockID!));
data = getFixedLengthList(data, 40 - length);
printLog(data);
return data;
}
}
class GetDeviceModelReply extends Reply {
GetDeviceModelReply.parseData(CommandType commandType, List<int> dataDetail)
: super.parseData(commandType, dataDetail) {
status = dataDetail[2];
data = dataDetail;
}
}

View File

@ -0,0 +1,163 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:crypto/crypto.dart' as crypto;
import '../io_reply.dart';
import '../io_sender.dart';
import '../io_tool/io_tool.dart';
import '../io_type.dart';
import '../sm4Encipher/sm4.dart';
//oat升级
class VoicePackageConfigure extends SenderProtocol {
VoicePackageConfigure(
{this.lockID,
this.userID,
this.keyID,
this.platform,
this.product,
this.fwSize,
this.fwMD5,
this.needAuthor,
this.signKey,
this.privateKey,
this.token,
this.encrypt = true})
: super(CommandType.startVoicePackageConfigure);
String? lockID;
String? userID;
String? keyID;
int? platform;
int? product;
int? fwSize;
String? fwMD5;
int? needAuthor;
List<int>? signKey;
List<int>? privateKey;
List<int>? token;
bool encrypt;
@override
String toString() {
return 'VoicePackageConfigure{lockID: $lockID, userID: $userID, '
'keyID: $keyID, platform: $platform, product: $product, '
' fwSize: $fwSize, '
'fwMD5: $fwMD5, needAuthor: $needAuthor, signKey: $signKey, '
'privateKey: $privateKey, token: $token}';
}
@override
int identifierValue() {
if (encrypt) {
return super.identifierValue();
} else {
return 0x20;
}
}
@override
List<int> messageDetail() {
List<int> data = <int>[];
List<int> ebcData = <int>[];
//
final int type = commandType!.typeValue;
final double typeDouble = type / 256;
final int type1 = typeDouble.toInt();
final int type2 = type % 256;
data.add(type1);
data.add(type2);
// id 40
final int lockIDLength = utf8.encode(lockID!).length;
data.addAll(utf8.encode(lockID!));
data = getFixedLengthList(data, 40 - lockIDLength);
//userID 20
final int userIDLength = utf8.encode(userID!).length;
data.addAll(utf8.encode(userID!));
data = getFixedLengthList(data, 20 - userIDLength);
//platform 2
final int platform0 = (platform! & 0xFF00) >> 8;
final int platform1 = platform! & 0xFF;
data.add(platform0);
data.add(platform1);
//product 2
data.addAll(<int>[0, 1]); // 01
//fwSize 4
final ByteData bytes = ByteData(4); // 4
bytes.setInt32(0, fwSize!);
final List<int> byteList = bytes.buffer.asUint8List();
data.addAll(byteList);
// 16
final Uint8List result = Uint8List(16);
// 4
for (int i = 0; i < fwMD5!.length; i += 2) {
final String hex = fwMD5!.substring(i, i + 2);
final int byteValue = int.parse(hex, radix: 16);
result[i ~/ 2] = byteValue;
}
data.addAll(result);
// token 4 Token 0 token失效或者第一次发送的时候token为0
data.addAll(token!);
if (needAuthor == 0) {
//AuthCodeLen 1
data.add(0);
} else {
final List<int> authCodeData = <int>[];
//KeyID
authCodeData.addAll(utf8.encode(keyID!));
//UserID
authCodeData.addAll(utf8.encode(userID!));
//token 4 Token 0
authCodeData.addAll(token ?? <int>[]);
authCodeData.addAll(signKey ?? <int>[]);
// KeyIDauthUserIDmd5加密之后就是authCode
final crypto.Digest authCode = crypto.md5.convert(authCodeData);
data.add(authCode.bytes.length);
data.addAll(authCode.bytes);
}
if ((data.length % 16) != 0) {
final int add = 16 - data.length % 16;
for (int i = 0; i < add; i++) {
data.add(0);
}
}
printLog(data);
if (encrypt) {
// LockId进行SM4 ECB加密 key:544d485f633335373034383064613864
ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB);
return ebcData;
} else {
data.add(0);
return data;
}
}
}
class VoicePackageConfigureReply extends Reply {
VoicePackageConfigureReply.parseData(
CommandType commandType, List<int> dataDetail)
: super.parseData(commandType, dataDetail) {
data = dataDetail;
token = data.sublist(2, 6);
status = data[6];
errorWithStstus(status);
}
List<int> token = <int>[];
}

View File

@ -0,0 +1,73 @@
import 'dart:typed_data';
import '../io_reply.dart';
import '../io_sender.dart';
import '../io_type.dart';
//oat升级
class VoicePackageConfigureProcess extends SenderProtocol {
VoicePackageConfigureProcess({
this.index,
this.size,
this.data,
}) : super(CommandType.voicePackageConfigureProcess);
int? index;
int? size;
List<int>? data;
@override
String toString() {
return 'VoicePackageConfigureProcess{index: $index, size: $size, data: $data}';
}
@override
List<int> messageDetail() {
final List<int> data = [];
//
final int type = commandType!.typeValue;
final double typeDouble = type / 256;
final int type1 = typeDouble.toInt();
final int type2 = type % 256;
data.add(type1);
data.add(type2);
//index 2
final ByteData indexBytes = ByteData(2); // 4
indexBytes.setInt16(0, index!);
final List<int> indexList = indexBytes.buffer.asUint8List();
data.addAll(indexList);
//size 2
final ByteData bytes = ByteData(2); // 4
bytes.setInt16(0, size!);
final List<int> byteList = bytes.buffer.asUint8List();
data.addAll(byteList);
data.addAll(this.data!);
printLog(data);
//
return data;
}
}
class VoicePackageConfigureProcessReply extends Reply {
VoicePackageConfigureProcessReply.parseData(
CommandType commandType, List<int> dataDetail)
: super.parseData(commandType, dataDetail) {
data = dataDetail;
status = data[2];
errorWithStstus(status);
}
}
class VoicePackageConfigureConfirmationReply extends Reply {
VoicePackageConfigureConfirmationReply.parseData(
CommandType commandType, List<int> dataDetail)
: super.parseData(commandType, dataDetail) {
data = dataDetail;
status = data[2];
errorWithStstus(status);
}
}

View File

@ -288,16 +288,27 @@ String asciiString(List<int> codeUnits) {
}
String utf8String(List<int> codeUnits) {
codeUnits.reversed;
final List<int> uniqueList = <int>[];
for (int i = 0; i < codeUnits.length; i++) {
if (codeUnits[i] != 0) {
uniqueList.add(codeUnits[i]);
}
try {
// 0
int realLen = codeUnits.indexWhere((b) => b == 0);
List<int> validBytes = (realLen == -1) ? codeUnits : codeUnits.sublist(0, realLen);
return utf8.decode(validBytes);
} catch (e) {
//
return '';
}
uniqueList.reversed;
return utf8.decode(uniqueList).toString();
}
// String utf8String(List<int> codeUnits) {
// codeUnits.reversed;
// final List<int> uniqueList = <int>[];
// for (int i = 0; i < codeUnits.length; i++) {
// if (codeUnits[i] != 0) {
// uniqueList.add(codeUnits[i]);
// }
// }
// uniqueList.reversed;
// return utf8.decode(uniqueList).toString();
// }
bool compareTwoList({List<int>? list1, List<int>? list2}) {
if (list1!.length != list2!.length) {

View File

@ -9,10 +9,10 @@ List<String> getDeviceType(DeviceType deviceType) {
List<String> t = ['758824'];
switch (deviceType) {
case DeviceType.blue:
t = ['758824', '75', '768824', '76'];
t = ['758824', '75', '768824', '76','24'];
break;
case DeviceType.gateway:
t = ['758825'];
t = ['758825','25'];
break;
}
return t;
@ -41,6 +41,10 @@ enum CommandType {
startOATUpgrade, //OTA升级开始 0x30E0
processOTAUpgrade, //OTA升级过程 0x30E1
confirmationOTAUpgrade, //OTA升级确认 0x30E2
startVoicePackageConfigure, // 0x30A1
voicePackageConfigureProcess, // 0x30A2
voicePackageConfigureConfirmation, // 0x30A3
getDeviceModel, // 0x30A4
gatewayConfiguringWifi, // 0x30F4
gatewayConfiguringWifiResult, // 0x30F5
@ -189,6 +193,26 @@ extension ExtensionCommandType on CommandType {
type = CommandType.confirmationOTAUpgrade;
}
break;
case 0x30A1:
{
type = CommandType.startVoicePackageConfigure;
}
break;
case 0x30A2:
{
type = CommandType.voicePackageConfigureProcess;
}
break;
case 0x30A3:
{
type = CommandType.voicePackageConfigureConfirmation;
}
break;
case 0x30A4:
{
type = CommandType.getDeviceModel;
}
break;
case 0x30F4:
{
type = CommandType.gatewayConfiguringWifi;
@ -307,6 +331,18 @@ extension ExtensionCommandType on CommandType {
case CommandType.gatewayGetStatus:
type = 0x30F8;
break;
case CommandType.startVoicePackageConfigure:
type = 0x30A1;
break;
case CommandType.voicePackageConfigureProcess:
type = 0x30A2;
break;
case CommandType.voicePackageConfigureConfirmation:
type = 0x30A3;
break;
case CommandType.getDeviceModel:
type = 0x30A4;
break;
default:
type = 0x300A;
break;
@ -322,9 +358,11 @@ extension ExtensionCommandType on CommandType {
switch (this) {
case CommandType.getLockPublicKey:
case CommandType.processOTAUpgrade:
case CommandType.voicePackageConfigureProcess:
case CommandType.gatewayGetWifiList:
case CommandType.gatewayConfiguringWifi:
case CommandType.gatewayGetStatus:
case CommandType.getDeviceModel:
//
type = 0x20;
break;
@ -428,6 +466,18 @@ extension ExtensionCommandType on CommandType {
case 0x30F8:
t = '获取网关状态';
break;
case 0x30A1:
t = '语音包配置开始';
break;
case 0x30A2:
t = '语音包配置过程';
break;
case 0x30A3:
t = '语音包配置确认';
break;
case 0x30A4:
t = '获取设备型号';
break;
default:
t = '读星锁状态信息';
break;

View File

@ -12,6 +12,7 @@ import 'package:star_lock/blue/io_protocol/io_cleanUpUsers.dart';
import 'package:star_lock/blue/io_protocol/io_deletUser.dart';
import 'package:star_lock/blue/io_protocol/io_editUser.dart';
import 'package:star_lock/blue/io_protocol/io_factoryDataReset.dart';
import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart';
import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart';
import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart';
import 'package:star_lock/blue/io_protocol/io_readAdminPassword.dart';
@ -21,6 +22,8 @@ import 'package:star_lock/blue/io_protocol/io_referEventRecordTime.dart';
import 'package:star_lock/blue/io_protocol/io_setSupportFunctionsNoParameters.dart';
import 'package:star_lock/blue/io_protocol/io_setSupportFunctionsWithParameters.dart';
import 'package:star_lock/blue/io_protocol/io_timing.dart';
import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart';
import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart';
import '../tools/storage.dart';
import 'io_gateway/io_gateway_getStatus.dart';
@ -292,6 +295,28 @@ class CommandReciverManager {
reply = GatewayGetStatusReply.parseData(commandType, data);
}
break;
case CommandType.getDeviceModel:
{
reply = GetDeviceModelReply.parseData(commandType, data);
}
break;
case CommandType.startVoicePackageConfigure:
{
reply = VoicePackageConfigureReply.parseData(commandType, data);
}
break;
case CommandType.voicePackageConfigureProcess:
{
reply =
VoicePackageConfigureProcessReply.parseData(commandType, data);
}
break;
case CommandType.voicePackageConfigureConfirmation:
{
reply = VoicePackageConfigureConfirmationReply.parseData(
commandType, data);
}
break;
case CommandType.generalExtendedCommond:
{
//

View File

@ -90,6 +90,7 @@ class XSConstantMacro {
static int webBuyTypeVip = 3; //VIP购买
static int webBuyTypeAuth = 4; //
static int webBuyTypeShop = 5; //
static int webBuyTypeCloudStorage = 6; //
//
Future<Map<String, dynamic>> getDeviceInfoData() async {

View File

@ -783,7 +783,7 @@ class LockDetailLogic extends BaseGetXController {
// }
///
void sendMonitorMessage() {
void sendMonitorMessage() async {
final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? [];
final network = state.keyInfos.value.network;
if (catEyeConfig.isNotEmpty &&
@ -840,24 +840,48 @@ class LockDetailLogic extends BaseGetXController {
state.DetailLockInfo = eventBus
.on<PassCurrentLockInformationEvent>()
.listen((PassCurrentLockInformationEvent event) {
if (event.lockSetInfoData.lockSettingInfo != null &&
event.lockSetInfoData.lockSettingInfo!.catEyeConfig != null &&
event.lockSetInfoData.lockSettingInfo!.catEyeConfig!.length > 0) {
if (state.keyInfos.value.lockSetting!.catEyeConfig == null ||
state.keyInfos.value.lockSetting!.catEyeConfig!.length == 0) {
state.keyInfos.value.lockSetting!.catEyeConfig!.add(CatEyeConfig(
//
final lockSettingInfo = event.lockSetInfoData.lockSettingInfo;
final lockBasicInfo = event.lockSetInfoData.lockBasicInfo;
final networkInfo = lockBasicInfo?.networkInfo;
final targetCatEyeConfig = lockSettingInfo?.catEyeConfig;
if (lockBasicInfo != null && networkInfo != null) {
state.keyInfos.value.network?.peerId = networkInfo.peerId;
state.keyInfos.value.network?.wifiName = networkInfo.wifiName;
}
// catEyeConfig
if (lockSettingInfo != null &&
targetCatEyeConfig != null &&
targetCatEyeConfig.isNotEmpty) {
// catEyeConfig
final stateCatEyeConfig =
state.keyInfos.value.lockSetting?.catEyeConfig;
// catEyeConfig
if (stateCatEyeConfig == null || stateCatEyeConfig.isEmpty) {
state.keyInfos.value.lockSetting?.catEyeConfig ??= [];
state.keyInfos.value.lockSetting!.catEyeConfig!.add(
CatEyeConfig(
catEyeMode: 0,
catEyeModeConfig: CatEyeModeConfig(
realTimeMode: 0,
recordEndTime: 0,
recordMode: 0,
recordStartTime: 0,
recordTime: '0',
detectionDistance: '0')));
realTimeMode: 0,
recordEndTime: 0,
recordMode: 0,
recordStartTime: 0,
recordTime: '0',
detectionDistance: '0',
),
),
);
}
state.keyInfos.value.lockSetting!.catEyeConfig![0].catEyeMode = event
.lockSetInfoData.lockSettingInfo!.catEyeConfig![0].catEyeMode ??
1;
// catEyeMode使 1
state.keyInfos.value.lockSetting!.catEyeConfig![0].catEyeMode =
targetCatEyeConfig[0].catEyeMode ?? 1;
//
state.keyInfos.refresh();
}
});

View File

@ -0,0 +1,296 @@
//
import 'package:get/get.dart';
class TimbreItem {
final String timbre;
final String name;
final String timbrePackUrl;
final int isFemale;
TimbreItem({
required this.timbre,
required this.name,
required this.timbrePackUrl,
required this.isFemale,
});
factory TimbreItem.fromJson(Map<String, dynamic> json) {
return TimbreItem(
timbre: json['timbre'] ?? '',
name: json['name'] ?? '',
timbrePackUrl: json['timbrePackUrl'] ?? '',
isFemale: json['isFemale'] ?? 0,
);
}
Map<String, dynamic> toJson() {
return {
'timbre': timbre,
'name': name,
'timbrePackUrl': timbrePackUrl,
'isFemale': isFemale,
};
}
@override
String toString() {
return 'TimbreItem{timbre: $timbre, name: $name, timbrePackUrl: '
'$timbrePackUrl},isFemale: $isFemale}';
}
}
//
class PassthroughItem {
final String lang;
final String langText;
final String name;
final List<TimbreItem> timbres;
PassthroughItem({
required this.lang,
required this.timbres,
required this.langText,
required this.name,
});
factory PassthroughItem.fromJson(Map<String, dynamic> json) {
var timbresJson = json['timbres'] as List<dynamic>?;
List<TimbreItem> timbresList = timbresJson != null
? timbresJson
.map((e) => TimbreItem.fromJson(e as Map<String, dynamic>))
.toList()
: <TimbreItem>[];
return PassthroughItem(
lang: json['lang'] ?? '',
langText: json['langText'] ?? '',
name: json['name'] ?? '',
timbres: timbresList,
);
}
Map<String, dynamic> toJson() {
return {
'lang': lang,
'langText': langText,
'name': name,
'timbres': timbres.map((e) => e.toJson()).toList(),
};
}
@override
String toString() {
return 'PassthroughItem{lang: $lang, name: $name, timbres: $timbres, '
'langText: '
'$langText}';
}
}
class PassthroughListResponse {
PassthroughListResponse({
this.description,
this.errorCode,
this.data,
this.errorMsg,
});
String? description;
int? errorCode;
List<PassthroughItem>? data;
String? errorMsg;
PassthroughListResponse.fromJson(dynamic json) {
description = json['description'];
errorCode = json['errorCode'];
if (json['data'] != null && json['data'] is List) {
data = (json['data'] as List)
.map((e) => PassthroughItem.fromJson(e as Map<String, dynamic>))
.toList();
} else {
data = null;
}
errorMsg = json['errorMsg'];
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['description'] = description;
map['errorCode'] = errorCode;
if (data != null) {
map['data'] = data!.map((e) => e.toJson()).toList();
}
map['errorMsg'] = errorMsg;
return map;
}
}
///
/// 'zh_CN' -> '简体中文'.tr'en_US' -> '英文'.tr
class PassthroughLangHelper {
static String getLangText(String langCode) {
switch (langCode.toLowerCase()) {
case 'zh_cn':
return '简体中文'.tr;
case 'zh_tw':
return '繁体中文(中国台湾)'.tr;
case 'zh_hk':
return '繁体中文(中国香港)'.tr;
case 'en_us':
return '英文'.tr;
case 'fr_fr':
return '法语'.tr;
case 'ru_ru':
return '俄语'.tr;
case 'de_de':
return '德语'.tr;
case 'ja_jp':
return '日语'.tr;
case 'ko_kr':
return '韩语'.tr;
case 'it_it':
return '意大利语'.tr;
case 'pt_pt':
return '葡萄牙语'.tr;
case 'es_es':
return '西班牙语'.tr;
case 'ar_sa':
return '阿拉伯语'.tr;
case 'vi_vn':
return '越南语'.tr;
case 'ms_my':
return '马来语'.tr;
case 'nl_nl':
return '荷兰语'.tr;
case 'ro_ro':
return '罗马尼亚语'.tr;
case 'lt_lt':
return '立陶宛语'.tr;
case 'sv_se':
return '瑞典语'.tr;
case 'et_ee':
return '爱沙尼亚语'.tr;
case 'pl_pl':
return '波兰语'.tr;
case 'sk_sk':
return '斯洛伐克语'.tr;
case 'cs_cz':
return '捷克语'.tr;
case 'el_gr':
return '希腊语'.tr;
case 'he_il':
return '希伯来语'.tr;
case 'sr_rs':
return '塞尔维亚语'.tr;
case 'tr_tr':
return '土耳其语'.tr;
case 'hu_hu':
return '匈牙利语'.tr;
case 'bg_bg':
return '保加利亚语'.tr;
case 'kk_kz':
return '哈萨克斯坦语'.tr;
case 'bn_bd':
return '孟加拉语'.tr;
case 'hr_hr':
return '克罗地亚语'.tr;
case 'th_th':
return '泰语'.tr;
case 'id_id':
return '印度尼西亚语'.tr;
case 'fi_fi':
return '芬兰语'.tr;
case 'da_dk':
return '丹麦语'.tr;
case 'uk_ua':
return '乌克兰语'.tr;
case 'hi_in':
return '印地语'.tr;
case 'ur_pk':
return '乌尔都语'.tr;
case 'hy_am':
return '亚美尼亚语'.tr;
case 'ka_ge':
return '格鲁吉亚语'.tr;
default:
return '未知语言'.tr;
}
}
}
class ValidityPeriodResponse {
ValidityPeriodResponse({
this.description,
this.errorCode,
this.data,
this.errorMsg,
});
String? description;
int? errorCode;
ValidityPeriod? data;
String? errorMsg;
ValidityPeriodResponse.fromJson(dynamic json) {
description = json['description'];
errorCode = json['errorCode'];
if (json['data'] != null) {
data = ValidityPeriod.fromJson(json['data']);
} else {
data = null;
}
errorMsg = json['errorMsg'];
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['description'] = description;
map['errorCode'] = errorCode;
if (data != null) {
map['data'] = data!.toJson();
}
map['errorMsg'] = errorMsg;
return map;
}
}
class ValidityPeriod {
final int lockId;
final int status;
final String validityPeriodStart;
final String validityPeriodEnd;
final int rollingStorageDays;
final int remainingDays;
ValidityPeriod({
required this.lockId,
required this.status,
required this.validityPeriodStart,
required this.validityPeriodEnd,
required this.rollingStorageDays,
required this.remainingDays,
});
//
factory ValidityPeriod.fromJson(Map<String, dynamic> json) {
return ValidityPeriod(
lockId: json['lockId'] as int? ?? 0,
// 0
status: json['status'] as int? ?? 0,
validityPeriodStart: json['validityPeriodStart'] as String? ?? '',
validityPeriodEnd: json['validityPeriodEnd'] as String? ?? '',
rollingStorageDays: json['rollingStorageDays'] as int? ?? 0,
remainingDays: json['remainingDays'] as int? ?? 0,
);
}
//
Map<String, dynamic> toJson() {
return {
'lockId': lockId,
'status': status,
'validityPeriodStart': validityPeriodStart,
'validityPeriodEnd': validityPeriodEnd,
'rollingStorageDays': rollingStorageDays,
'remainingDays': remainingDays,
};
}
}

View File

@ -161,11 +161,12 @@ class ConfiguringWifiLogic extends BaseGetXController {
// - : sureBtnState updateNetworkInfo
final info = await updateNetworkInfo(
peerId: peerId,
wifiName: wifiName ?? '',
secretKey: secretKey,
deviceMac: deviceMac ?? '',
networkMac: networkMac ?? '');
peerId: peerId,
wifiName: wifiName ?? '',
secretKey: secretKey,
deviceMac: deviceMac ?? '',
networkMac: networkMac ?? '',
);
if (info.errorCode!.codeIsSuccessful) {
// peerID
StartChartManage().lockNetworkInfo = DeviceNetworkInfo(
@ -175,6 +176,11 @@ class ConfiguringWifiLogic extends BaseGetXController {
peerId: peerId,
);
state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.peerId =
peerId;
state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.wifiName =
wifiName;
/// ,peerId
StartChartManage().lockPeerId = peerId;
@ -189,7 +195,9 @@ class ConfiguringWifiLogic extends BaseGetXController {
Get.offAllNamed(Routers.starLockMain);
}
eventBus.fire(SuccessfulDistributionNetwork());
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
eventBus.fire(RefreshLockListInfoDataEvent(
clearScanDevices: true, isUnShowLoading: true));
eventBus.fire(RefreshLockDetailInfoDataEvent());
});
//
@ -589,7 +597,6 @@ class ConfiguringWifiLogic extends BaseGetXController {
recordType: recordType,
records: records,
isUnShowLoading: true);
if (entity.errorCode!.codeIsSuccessful) {
eventBus
.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value));

View File

@ -158,6 +158,7 @@ class LockFeature {
this.isElectronicAntiLock,
this.isVisualDoorBellCode,
this.isDoubleLockLinkage,
this.languageSpeech,
});
LockFeature.fromJson(Map<String, dynamic> json) {
@ -218,6 +219,7 @@ class LockFeature {
isElectronicAntiLock = json['isElectronicAntiLock'];
isVisualDoorBellCode = json['isVisualDoorBellCode'];
isDoubleLockLinkage = json['isDoubleLockLinkage'];
languageSpeech = json['languageSpeech'];
}
int? password;
@ -277,6 +279,7 @@ class LockFeature {
int? isElectronicAntiLock;
int? isVisualDoorBellCode;
int? isDoubleLockLinkage;
int? languageSpeech;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
@ -337,6 +340,7 @@ class LockFeature {
data['isElectronicAntiLock'] = isElectronicAntiLock;
data['isVisualDoorBellCode'] = isVisualDoorBellCode;
data['isDoubleLockLinkage'] = isDoubleLockLinkage;
data['languageSpeech'] = languageSpeech;
return data;
}
}
@ -348,6 +352,8 @@ class LockBasicInfo {
this.keyId,
this.model,
this.electricQuantity,
this.hwVersion,
this.fwVersion,
this.electricQuantityStandby,
this.indate,
this.isLockOwner,
@ -376,6 +382,8 @@ class LockBasicInfo {
keyId = json['keyId'];
model = json['model'];
electricQuantity = json['electricQuantity'];
hwVersion = json['hwVersion'];
fwVersion = json['fwVersion'];
electricQuantityStandby = json['electricQuantityStandby'];
indate = json['indate'];
isLockOwner = json['isLockOwner'];
@ -411,6 +419,8 @@ class LockBasicInfo {
int? keyId;
String? model;
int? electricQuantity;
String? fwVersion;
String? hwVersion;
int? electricQuantityStandby;
int? indate;
int? isLockOwner;
@ -440,6 +450,8 @@ class LockBasicInfo {
data['keyId'] = keyId;
data['model'] = model;
data['electricQuantity'] = electricQuantity;
data['hwVersion'] = hwVersion;
data['fwVersion'] = fwVersion;
data['electricQuantityStandby'] = electricQuantityStandby;
data['indate'] = indate;
data['isLockOwner'] = isLockOwner;
@ -523,6 +535,7 @@ class LockSettingInfo {
this.autoLightScreen,
this.autoLightScreenTime,
this.faceEnErrUnlock,
this.currentVoiceTimbre,
});
LockSettingInfo.fromJson(Map<String, dynamic> json) {
@ -570,6 +583,10 @@ class LockSettingInfo {
autoLightScreen = json['autoLightScreen'];
autoLightScreenTime = json['autoLightScreenTime'];
faceEnErrUnlock = json['faceEnErrUnlock'];
if (json['currentVoiceTimbre'] != null) {
currentVoiceTimbre =
CurrentVoiceTimbre.fromJson(json['currentVoiceTimbre']);
}
}
int? remoteUnlock;
@ -605,6 +622,7 @@ class LockSettingInfo {
int? autoLightScreen; //- 0: 1:
int? autoLightScreenTime; //-
int? faceEnErrUnlock;
CurrentVoiceTimbre? currentVoiceTimbre;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
@ -645,7 +663,9 @@ class LockSettingInfo {
data['autoLightScreen'] = autoLightScreen;
data['autoLightScreenTime'] = autoLightScreenTime;
data['faceEnErrUnlock'] = faceEnErrUnlock;
if (currentVoiceTimbre != null) {
data['currentVoiceTimbre'] = currentVoiceTimbre!.toJson();
}
return data;
}
}
@ -757,3 +777,29 @@ class CatEyeModeConfig {
return data;
}
}
class CurrentVoiceTimbre {
String? lang;
String? timbre;
CurrentVoiceTimbre({
this.lang,
this.timbre,
});
// JSON
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['lang'] = lang;
data['timbre'] = timbre;
return data;
}
// JSON
factory CurrentVoiceTimbre.fromJson(Map<String, dynamic> json) {
return CurrentVoiceTimbre(
timbre: json['timbre'],
lang: json['lang'],
);
}
}

View File

@ -4,6 +4,7 @@ import 'package:flutter/scheduler.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:get/get.dart';
import 'package:star_lock/apm/apm_helper.dart';
import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart';
import 'package:star_lock/login/login/entity/LoginEntity.dart';
import 'package:star_lock/main/lockMian/entity/lockListInfo_entity.dart';
@ -680,7 +681,7 @@ class LockSetLogic extends BaseGetXController {
updataLockSet(getTokenList);
} else if (connectionState == BluetoothConnectionState.disconnected) {
// cancelBlueConnetctToastTimer();
// if(state.ifCurrentScreen.value == true){
// if (state.ifCurrentScreen.value == true) {
// showBlueConnetctToast();
// }
}
@ -728,6 +729,7 @@ class LockSetLogic extends BaseGetXController {
getUpdataLockSet();
_initReplySubscription();
// _scanListDiscoveredDeviceSubscriptionAction();
}
@ -737,4 +739,10 @@ class LockSetLogic extends BaseGetXController {
_passCurrentLockInformationEvent!.cancel();
// _scanListDiscoveredDeviceSubscription.cancel();
}
@override
void dispose() {
_replySubscription.cancel();
super.dispose();
}
}

View File

@ -526,6 +526,33 @@ class _LockSetPageState extends State<LockSetPage>
'lockSetInfoData': state.lockSetInfoData.value
});
})),
//
Visibility(
visible: state.lockFeature.value.languageSpeech == 1,
child: CommonItem(
leftTitel: '语音包设置'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.speechLanguageSettingsPage,
arguments: <String, LockSetInfoData>{
'lockSetInfoData': state.lockSetInfoData.value
});
})),
//
CommonItem(
leftTitel: '第三方平台设置'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.thirdPartyPlatformPage,
arguments: <String, LockSetInfoData>{
'lockSetInfoData': state.lockSetInfoData.value
});
},
),
// 广使
/* 2024-01-12 广 by DaisyWu
Obx(() => Visibility(
@ -592,7 +619,7 @@ class _LockSetPageState extends State<LockSetPage>
state.lockFeature.value.appUnlockOnline == 1,
child: otherItem(
leftTitle: '开锁时是否需联网'.tr,
isHaveLine: false,
isHaveLine: true,
rightWidget: _openLockNeedOnlineSwitch()),
),
),

View File

@ -0,0 +1,464 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.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_getDeviceModel.dart';
import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart';
import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart';
import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart';
import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart';
import 'package:star_lock/blue/io_reply.dart';
import 'package:star_lock/blue/io_tool/io_tool.dart';
import 'package:star_lock/blue/io_tool/manager_event_bus.dart';
import 'package:star_lock/login/login/entity/LoginEntity.dart';
import 'package:star_lock/login/selectCountryRegion/common/index.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart';
import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import 'package:http/http.dart' as http;
import 'package:star_lock/tools/commonDataManage.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/storage.dart';
import 'package:star_lock/translations/app_dept.dart';
import 'package:star_lock/translations/current_locale_tool.dart';
class SpeechLanguageSettingsLogic extends BaseGetXController {
final SpeechLanguageSettingsState state = SpeechLanguageSettingsState();
StreamSubscription<Reply>? _replySubscription;
//
Timer? _sendTimeoutTimer;
//
bool _isTimeout = false;
@override
void onInit() async {
super.onInit();
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
if (reply is VoicePackageConfigureReply) {
//
_handlerStartVoicePackageConfigure(reply);
} else if (reply is VoicePackageConfigureProcessReply) {
_handlerVoicePackageConfigureProcess(reply);
} else if (reply is VoicePackageConfigureConfirmationReply) {
handleVoiceConfigureThrottled(reply);
}
});
await initList();
}
///
/// //{ "vendor": "XL", "model": "JL-BLE-01"}
initList() async {
showEasyLoading();
try {
final vendor = state.lockSetInfoData.value.lockBasicInfo?.vendor;
final model = state.lockSetInfoData.value.lockBasicInfo?.model;
final PassthroughListResponse entity =
await ApiRepository.to.getPassthroughList(data: {
'vendor': vendor!,
'model': model!,
});
if (entity.errorCode!.codeIsSuccessful) {
final data = entity.data;
final locales = appDept.deptSupportedLocales;
state.languages.clear();
state.languages.add(
PassthroughItem(
lang: 'system',
timbres: [],
langText: '跟随系统'.tr,
name: '跟随系统'.tr,
),
);
data?.forEach((element) {
final lang = element.lang;
if (lang == 'zh_TW') {
//
List<String> parts = lang.split('_');
final indexOf = locales.indexOf(Locale(parts[0], parts[1]));
final passthroughItem = PassthroughItem(
lang: element.lang,
timbres: element.timbres,
langText: '简体中文'.tr + '(中国台湾)'.tr,
name: element.name,
);
state.languages.add(passthroughItem);
} else {
List<String> parts = lang.split('_');
final indexOf = locales.indexOf(Locale(parts[0], parts[1]));
final passthroughItem = PassthroughItem(
lang: element.lang,
timbres: element.timbres,
langText:
ExtensionLanguageType.fromLocale(locales[indexOf]).lanTitle,
name: element.name,
);
state.languages.add(passthroughItem);
}
});
state.languages.refresh();
final lang = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
final timbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
// for 访
for (int i = 0; i < state.languages.length; i++) {
final language = state.languages[i]; //
if (language.lang == lang) {
print('匹配到下标:$i,元素:$language');
final timbres = language.timbres;
for (int j = 0; j < timbres.length; j++) {
final item = timbres[j];
if (lang == language.lang && item.timbre == timbre) {
state.selectSoundTypeIndex.value = item.isFemale;
state.selectPassthroughListIndex.value = i;
break;
}
}
}
}
}
} catch (e) {
debugPrint('获取语音包出现错误:$e');
} finally {
dismissEasyLoading();
}
}
void saveSpeechLanguageSettings() async {
var language = state.languages[state.selectPassthroughListIndex.value];
if (language.lang == 'system') {
//
//
// print(CurrentLocaleTool.convertLocale(Get.deviceLocale!));
// APP层的语言
Locale? currentLocale = Get.locale; //
if (currentLocale != null) {
final indexWhere = state.languages
.indexWhere((element) => element.lang == currentLocale.toString());
state.selectPassthroughListIndex.value = indexWhere;
}
}
language = state.languages[state.selectPassthroughListIndex.value];
final value = state.selectSoundTypeIndex.value;
state.tempLangStr.value = language.lang;
AppLog.log('下载的语言是:${state.tempLangStr}');
language.timbres.forEach((element) async {
if (element.isFemale == value) {
await downloadFile(element.timbrePackUrl);
state.tempTimbreStr.value = element.timbre;
return;
}
});
}
void changeSelectIndex(int index) {
state.selectLanguageIndex.value = index;
}
//
Future<void> downloadFile(String url) async {
final http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
state.data = response.bodyBytes;
sendFileToDevice(response.bodyBytes, <int>[0, 0, 0, 0]);
}
}
sendFileToDevice(Uint8List data, List<int> token) {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? signKey =
await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList = changeStringListToIntList(signKey!);
final String uid = await Storage.getUid() ?? '';
final String md5Str = md5.convert(data).toString().toUpperCase();
BlueManage().writeCharacteristicWithResponse(
VoicePackageConfigure(
lockID: BlueManage().connectDeviceName,
userID: uid,
keyID: BlueManage().connectDeviceName,
platform: 0,
product: 0,
fwSize: data.length,
fwMD5: md5Str,
needAuthor: 1,
token: token,
signKey: signKeyDataList,
privateKey: getPrivateKeyList)
.packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
}
});
}
//
sendGetDeviceModelBleMessage() {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
BlueManage().writeCharacteristicWithResponse(
GetDeviceModelCommand(
lockID: BlueManage().connectDeviceName,
).packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
}
});
}
//
void _handlerStartVoicePackageConfigure(
VoicePackageConfigureReply reply) async {
final int status = reply.data[6];
switch (status) {
case 0x00:
//
cancelBlueConnetctToastTimer();
_startSendLanguageFile();
break;
case 0x06:
//
final List<int> token = reply.data.sublist(2, 6);
print('收到token:$token');
if (state.data != null) {
sendFileToDevice(state.data!, token);
}
break;
default:
showToast('获取设备型号失败'.tr);
break;
}
}
void _startSendLanguageFile() {
if (state.data == null) return;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount =
(state.data!.length + state.voiceSubcontractingSize - 1) ~/
state.voiceSubcontractingSize;
state.progress.value = 0.0; //
_sendNextPackage();
}
void _handleSendTimeout() {
_isTimeout = true; //
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
//
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
state.progress.value = 0.0;
_isTimeout = false; //
}
void _sendNextPackage() async {
//
if (_isTimeout) return;
//
_sendTimeoutTimer?.cancel();
//
if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) {
print('所有分包已发送完成');
state.progress.value = 1.0;
return;
}
// 3
_sendTimeoutTimer = Timer(Duration(seconds: 3), () {
_handleSendTimeout(); //
});
if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) {
print('所有分包已发送完成');
state.progress.value = 1.0; //
// UI或做后续处理
return;
}
int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize;
int end = start + state.voiceSubcontractingSize;
if (end > state.data!.length) end = state.data!.length;
Uint8List packageData = state.data!.sublist(start, end);
//
state.progress.value =
(state.voiceSubcontractingIndex + 1) / state.voiceSubcontractingCount;
EasyLoading.showProgress(state.progress.value,
status: '正在发送数据 ${(state.progress.value * 100).toStringAsFixed(0)}%');
await _sendLanguageFileBleMessage(
index: state.voiceSubcontractingIndex,
data: packageData,
);
}
_sendLanguageFileBleMessage(
{required int index, required Uint8List data}) async {
await BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
await BlueManage().writeCharacteristicWithResponse(
VoicePackageConfigureProcess(
index: index,
size: data.length,
data: data,
).packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
}
});
}
void _handlerVoicePackageConfigureProcess(
VoicePackageConfigureProcessReply reply) {
//
_sendTimeoutTimer?.cancel();
_isTimeout = false; //
final int status = reply.data[2];
switch (status) {
case 0x00:
cancelBlueConnetctToastTimer();
state.voiceSubcontractingIndex++;
_sendNextPackage();
break;
default:
showToast('发送分包数据不成功'.tr);
break;
}
}
@override
void dispose() async {
await _replySubscription?.cancel();
_replySubscription = null;
await BlueManage().disconnect();
dismissEasyLoading();
cancelBlueConnetctToastTimer();
EasyLoading.dismiss();
//
state.progress.value = 0.0;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
super.dispose();
}
@override
void onClose() async {
await _replySubscription?.cancel();
_replySubscription = null;
await BlueManage().disconnect();
dismissEasyLoading();
cancelBlueConnetctToastTimer();
EasyLoading.dismiss();
//
state.progress.value = 0.0;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
super.onClose();
}
bool _isThrottled = false;
void handleVoiceConfigureThrottled(
VoicePackageConfigureConfirmationReply reply,
) {
if (_isThrottled) return;
_isThrottled = true;
//
_executeLogic(reply);
// 1
Future.delayed(Duration(seconds: 1), () {
_isThrottled = false;
});
}
Future<void> _executeLogic(
VoicePackageConfigureConfirmationReply reply) async {
await _handlerVoicePackageConfigureConfirmation(reply);
}
_handlerVoicePackageConfigureConfirmation(
VoicePackageConfigureConfirmationReply reply,
) async {
final int status = reply.data[2];
switch (status) {
case 0x00:
cancelBlueConnetctToastTimer();
final LoginEntity entity =
await ApiRepository.to.settingCurrentVoiceTimbre(
data: {
'lang': state.tempLangStr.value,
'timbre': state.tempTimbreStr.value,
},
lockId: state.lockSetInfoData.value.lockId!,
);
if (entity.errorCode!.codeIsSuccessful) {
showSuccess('设置成功'.tr, something: () {
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.lang = state.tempLangStr.value;
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.timbre = state.tempTimbreStr.value;
eventBus.fire(
PassCurrentLockInformationEvent(state.lockSetInfoData.value));
});
}
dismissEasyLoading();
break;
default:
showToast('设置'.tr + '失败'.tr);
break;
}
}
}

View File

@ -0,0 +1,234 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart';
import 'package:star_lock/tools/EasyRefreshTool.dart';
import 'package:star_lock/tools/commonItem.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class SpeechLanguageSettingsPage extends StatefulWidget {
const SpeechLanguageSettingsPage();
@override
State<SpeechLanguageSettingsPage> createState() =>
_SpeechLanguageSettingsPageState();
}
class _SpeechLanguageSettingsPageState
extends State<SpeechLanguageSettingsPage> {
final SpeechLanguageSettingsLogic logic =
Get.put(SpeechLanguageSettingsLogic());
final SpeechLanguageSettingsState state =
Get.find<SpeechLanguageSettingsLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(
barTitle: '锁语音包设置'.tr,
haveBack: true,
backgroundColor: AppColors.mainColor,
actionsList: [
TextButton(
onPressed: logic.saveSpeechLanguageSettings,
child: Text(
'下载'.tr,
style: TextStyle(
color: Colors.white,
fontSize: 24.sp,
fontWeight: FontWeight.w500,
),
),
),
],
),
body: Obx(
() => ListView(
padding: EdgeInsets.zero,
children: [
//
Container(
color: Colors.white,
child: Column(
children: List.generate(
state.soundTypeList.length,
(index) {
final isLastItem = index == state.soundTypeList.length - 1;
final soundType = state.soundTypeList.value[index];
return CommonItem(
leftTitel: soundType,
rightTitle: '',
isHaveLine: !isLastItem,
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
value: soundType,
groupValue: state.soundTypeList
.value[state.selectSoundTypeIndex.value],
activeColor: AppColors.mainColor,
onChanged: (value) {
if (value != null) {
final newIndex = state.soundTypeList.value
.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectSoundTypeIndex.value = newIndex;
}
}
},
),
action: () {
state.selectSoundTypeIndex.value = index;
},
);
},
),
),
),
SizedBox(
height: 8.h,
),
//
Container(
color: Colors.transparent,
child: Column(
children: List.generate(
state.languages.length,
(index) {
final item = state.languages[index];
return CommonItem(
leftTitel: item.langText,
rightTitle: '',
isHaveLine: true,
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget:
state.selectPassthroughListIndex.value == index
? Image(
image: const AssetImage(
'images/icon_item_checked.png'),
width: 30.w,
height: 30.w,
fit: BoxFit.contain,
)
: Container(),
action: () {
state.selectPassthroughListIndex.value = index;
},
);
},
),
),
),
],
),
),
);
}
Widget _buildBody() {
return Obx(
() => SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemCount: state.soundTypeList.length,
itemBuilder: (BuildContext context, int index) {
// itemCount - 1
final isLastItem = index == state.soundTypeList.length - 1;
// platFormSet RxList<Platform>
final platform = state.soundTypeList.value[index];
return CommonItem(
leftTitel: state.soundTypeList.value[index],
rightTitle: '',
isHaveLine: !isLastItem,
// 线
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
// Radio 使 id
value: platform,
// selectPlatFormIndex id
groupValue: state.soundTypeList
.value[state.selectSoundTypeIndex.value],
//
activeColor: AppColors.mainColor,
// Radio
onChanged: (value) {
if (value != null) {
setState(() {
// id
final newIndex = state.soundTypeList.value
.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectSoundTypeIndex.value = newIndex;
}
});
}
},
),
action: () {
setState(() {
state.selectSoundTypeIndex.value = index;
});
},
);
},
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics() //add this line,
),
Column(
children: _buildList(),
),
],
),
),
);
}
List<Widget> _buildList() {
final appLocalLanguages = state.languages;
return List.generate(
appLocalLanguages.length,
(index) => _buildItem(
appLocalLanguages[index],
index,
),
);
}
@override
void dispose() {
super.dispose();
if (EasyLoading.isShow) {
EasyLoading.dismiss(animation: true);
}
}
_buildItem(PassthroughItem item, index) {
return CommonItem(
leftTitel: item.langText,
rightTitle: '',
isHaveLine: true,
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: state.selectPassthroughListIndex.value == index
? Image(
image: const AssetImage('images/icon_item_checked.png'),
width: 30.w,
height: 30.w,
fit: BoxFit.contain,
)
: Container(),
action: () {
state.selectPassthroughListIndex.value = index;
},
);
}
}

View File

@ -0,0 +1,57 @@
import 'dart:typed_data';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/translations/app_dept.dart';
class SpeechLanguageSettingsState {
SpeechLanguageSettingsState() {
final map = Get.arguments;
lockSetInfoData.value = map['lockSetInfoData'];
}
Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
//
RxInt selectPassthroughListIndex = 0.obs;
//
RxInt selectLanguageIndex = 0.obs;
final RxList<PassthroughItem> languages = <PassthroughItem>[].obs;
RxBool otaUpdateIng = false.obs;
RxDouble otaProgress = 0.00.obs;
RxString deviceModel = '2403'.obs;
Uint8List? data;
//
int voiceSubcontractingSize = 256;
//
int voiceSubcontractingCount = 0;
//
int voiceSubcontractingIndex = 0;
// 0.0~1.0
RxDouble progress = 0.0.obs;
RxInt selectedValue = 1.obs;
// UI
final RxList<String> soundTypeList = List.of({
'男声'.tr,
'女声'.tr,
}).obs;
RxInt selectSoundTypeIndex = 0.obs;
RxString tempLangStr=''.obs;
RxString tempTimbreStr=''.obs;
}

View File

@ -0,0 +1,19 @@
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart';
import 'package:star_lock/tools/baseGetXController.dart';
class ThirdPartyPlatformLogic extends BaseGetXController {
ThirdPartyPlatformState state = ThirdPartyPlatformState();
void savePlatFormSetting() {
// showEasyLoading();
showToast('功能待开放'.tr);
// dismissEasyLoading();
}
@override
void dispose() {
dismissEasyLoading();
super.dispose();
}
}

View File

@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart';
import 'package:star_lock/tools/commonItem.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class ThirdPartyPlatformPage extends StatefulWidget {
const ThirdPartyPlatformPage();
@override
State<ThirdPartyPlatformPage> createState() => _ThirdPartyPlatformPageState();
}
class _ThirdPartyPlatformPageState extends State<ThirdPartyPlatformPage> {
final ThirdPartyPlatformLogic logic = Get.put(ThirdPartyPlatformLogic());
final ThirdPartyPlatformState state =
Get.find<ThirdPartyPlatformLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: TitleAppBar(
barTitle: '第三方平台设置'.tr,
haveBack: true,
backgroundColor: AppColors.mainColor,
actionsList: [
TextButton(
onPressed: logic.savePlatFormSetting,
child: Text(
'保存'.tr,
style: TextStyle(
color: Colors.white,
fontSize: 24.sp,
fontWeight: FontWeight.w500,
),
),
),
],
),
body: _buildBody(),
);
}
Widget _buildBody() {
return ListView.builder(
itemCount: state.platFormSet.length,
itemBuilder: (BuildContext context, int index) {
// itemCount - 1
final isLastItem = index == state.platFormSet.length - 1;
// platFormSet RxList<Platform>
final platform = state.platFormSet.value[index];
return CommonItem(
leftTitel: state.platFormSet.value[index],
rightTitle: '',
isHaveLine: !isLastItem,
// 线
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
// Radio 使 id
value: platform,
// selectPlatFormIndex id
groupValue:
state.platFormSet.value[state.selectPlatFormIndex.value],
//
activeColor: AppColors.mainColor,
// Radio
onChanged: (value) {
if (value != null) {
setState(() {
// id
final newIndex =
state.platFormSet.value.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectPlatFormIndex.value = newIndex;
}
});
}
},
),
action: () {
setState(() {
state.selectPlatFormIndex.value = index;
});
},
);
},
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
);
}
}

View File

@ -0,0 +1,24 @@
import 'dart:ui';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/translations/app_dept.dart';
class ThirdPartyPlatformState {
ThirdPartyPlatformState() {
final map = Get.arguments;
lockSetInfoData.value = map['lockSetInfoData'];
}
Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
// UI
final RxList<String> platFormSet = List.of({
'锁通通'.tr,
'涂鸦智能'.tr,
}).obs;
RxInt selectPlatFormIndex = 0.obs;
}

View File

@ -1,8 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluwx/fluwx.dart';
import 'package:get/get.dart';
import 'package:star_lock/flavors.dart';
import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart';
@ -84,8 +84,8 @@ class _PasswordKeyDetailPageState extends State<PasswordKeyDetailPage>
// showCupertinoAlertDialog(
// context, state.inputNameController);
// })),
Obx(() => lockDataListItem('姓名'.tr,
state.keyboardPwdName.value, () {
Obx(() =>
lockDataListItem('姓名'.tr, state.keyboardPwdName.value, () {
showCupertinoAlertDialog(
context, state.inputNameController);
})),
@ -436,7 +436,18 @@ class _PasswordKeyDetailPageState extends State<PasswordKeyDetailPage>
final String pwdShareStr = logic.getShareContentStr();
switch (itemIndex) {
case 0: //
NativeInteractionTool().loadNativeShare(shareText: pwdShareStr);
Fluwx fluwx = Fluwx();
fluwx.registerApi(
appId: F.wechatAppInfo.wechatAppId,
universalLink: F.wechatAppInfo.universalLink,
);
fluwx.share(
WeChatShareTextModel(
pwdShareStr,
scene: WeChatScene.session,
),
);
// NativeInteractionTool().loadNativeShare(shareText: pwdShareStr);
break;
case 1: //
case 2: //

View File

@ -3,9 +3,11 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluwx/fluwx.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/flavors.dart';
import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart';
import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_state.dart';
import 'package:star_lock/tools/commonDataManage.dart';
@ -859,7 +861,18 @@ class _PasswordKeyPerpetualPageState extends State<PasswordKeyPerpetualPage>
final String pwdShareStr = logic.getShareContentStr();
switch (itemIndex) {
case 0: //
NativeInteractionTool().loadNativeShare(shareText: pwdShareStr);
Fluwx fluwx = Fluwx();
fluwx.registerApi(
appId: F.wechatAppInfo.wechatAppId,
universalLink: F.wechatAppInfo.universalLink,
);
fluwx.share(
WeChatShareTextModel(
pwdShareStr,
scene: WeChatScene.session,
),
);
// NativeInteractionTool().loadNativeShare(shareText: pwdShareStr);
break;
case 1: //
case 2: //

View File

@ -2,8 +2,12 @@ import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_entity.dart';
import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/baseGetXController.dart';
@ -142,10 +146,45 @@ class VideoLogLogic extends BaseGetXController {
}
}
@override
onReady() {
super.onReady();
getLockPassthroughInfo() async {
showEasyLoading();
try {
var entity = await ApiRepository.to.getValidityPeriodInfo(
lockId: state.getLockId.value,
);
if (entity.errorCode!.codeIsSuccessful) {
state.validityPeriodInfo.value = entity.data!;
}
} catch (e) {
} finally {
dismissEasyLoading();
}
}
@override
void onInit() async {
await getLockPassthroughInfo();
super.onInit();
}
@override
onReady() async {
super.onReady();
getLockCloudStorageList();
}
getWebPlayUrl() async {
final AdvancedFeaturesWebEntity entity =
await ApiRepository.to.getServicePackageBuyUrl();
if (entity.errorCode!.codeIsSuccessful) {
state.cloudStorageWebViewUrl.value = entity.data!.cloudStorage!;
final uploadReportBuyRequest = await ApiRepository.to
.uploadReportBuyRequest(lockId: state.getLockId.value);
if (uploadReportBuyRequest.errorCode!.codeIsSuccessful) {
Get.toNamed(Routers.advancedFeaturesWebPage, arguments: <String, int>{
'webBuyType': XSConstantMacro.webBuyTypeCloudStorage,
});
}
}
}
}

View File

@ -26,7 +26,9 @@ class VideoLogPage extends StatefulWidget {
class _VideoLogPageState extends State<VideoLogPage> {
final VideoLogLogic logic = Get.put(VideoLogLogic());
final VideoLogState state = Get.find<VideoLogLogic>().state;
final VideoLogState state = Get
.find<VideoLogLogic>()
.state;
@override
void initState() {
@ -54,64 +56,66 @@ class _VideoLogPageState extends State<VideoLogPage> {
// title加编辑按钮
editVideoTip(),
Obx(
() => Visibility(
visible: !state.isNavLocal.value,
child: state.videoLogList.length > 0
? Expanded(
child: ListView.builder(
itemCount: state.videoLogList.length,
itemBuilder: (BuildContext c, int index) {
final CloudStorageData item =
state.videoLogList[index];
return Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(children: <Widget>[
Text(item.date ?? '',
style: TextStyle(fontSize: 20.sp)),
])),
mainListView(index, item)
],
);
},
),
)
: _buildNotData(),
),
() =>
Visibility(
visible: !state.isNavLocal.value,
child: state.videoLogList.length > 0
? Expanded(
child: ListView.builder(
itemCount: state.videoLogList.length,
itemBuilder: (BuildContext c, int index) {
final CloudStorageData item =
state.videoLogList[index];
return Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(children: <Widget>[
Text(item.date ?? '',
style: TextStyle(fontSize: 20.sp)),
])),
mainListView(index, item)
],
);
},
),
)
: _buildNotData(),
),
),
//
Obx(
() => Visibility(
visible: state.isNavLocal.value,
child: state.lockVideoList.length > 0
? Expanded(
child: ListView.builder(
itemCount: state.lockVideoList.length,
itemBuilder: (BuildContext c, int index) {
final CloudStorageData item =
state.lockVideoList[index];
return Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(
children: <Widget>[
Text(item.date ?? '',
style: TextStyle(fontSize: 20.sp)),
],
),
() =>
Visibility(
visible: state.isNavLocal.value,
child: state.lockVideoList.length > 0
? Expanded(
child: ListView.builder(
itemCount: state.lockVideoList.length,
itemBuilder: (BuildContext c, int index) {
final CloudStorageData item =
state.lockVideoList[index];
return Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(
children: <Widget>[
Text(item.date ?? '',
style: TextStyle(fontSize: 20.sp)),
],
),
lockMainListView(index, item)
],
);
},
),
)
: _buildNotData(),
),
),
lockMainListView(index, item)
],
);
},
),
)
: _buildNotData(),
),
),
],
),
@ -157,13 +161,14 @@ class _VideoLogPageState extends State<VideoLogPage> {
// logic.clearDownloads();
});
},
child: Obx(() => Text('云存'.tr,
style: state.isNavLocal.value == true
? TextStyle(
child: Obx(() =>
Text('云存'.tr,
style: state.isNavLocal.value == true
? TextStyle(
color: Colors.grey,
fontSize: 26.sp,
fontWeight: FontWeight.w600)
: TextStyle(
: TextStyle(
color: Colors.white,
fontSize: 28.sp,
fontWeight: FontWeight.w600)))),
@ -175,18 +180,19 @@ class _VideoLogPageState extends State<VideoLogPage> {
});
},
child: Obx(
() => Text(
'已下载'.tr,
style: state.isNavLocal.value == true
? TextStyle(
() =>
Text(
'已下载'.tr,
style: state.isNavLocal.value == true
? TextStyle(
color: Colors.white,
fontSize: 28.sp,
fontWeight: FontWeight.w600)
: TextStyle(
: TextStyle(
color: Colors.grey,
fontSize: 26.sp,
fontWeight: FontWeight.w600),
),
),
),
),
],
@ -197,41 +203,120 @@ class _VideoLogPageState extends State<VideoLogPage> {
//
Widget vipTip() {
return GestureDetector(
onTap: () {
Get.toNamed(Routers.valueAddedServicesHighFunctionPage);
onTap: () async {
await logic.getWebPlayUrl();
// Get.toNamed(Routers.valueAddedCloudStoragePage);
// Get.toNamed(Routers.valueAddedServicesHighFunctionPage);
},
child: Container(
// height: 150.h,
margin: EdgeInsets.all(15.w),
padding:
EdgeInsets.only(left: 20.w, top: 20.w, bottom: 20.w, right: 10.w),
EdgeInsets.only(left: 20.w, top: 20.w, bottom: 20.w, right: 10.w),
decoration: BoxDecoration(
color: const Color(0xFFF6F7F8),
borderRadius: BorderRadius.circular(20.h)),
child: Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('3天滚动储存'.tr, style: TextStyle(fontSize: 24.sp)),
SizedBox(height: 10.h),
Text("${F.navTitle}${"已为本设备免费提供3大滚动视频储存服务".tr}",
style: TextStyle(fontSize: 22.sp, color: Colors.grey)),
],
)),
SizedBox(width: 15.w),
Text('去升级'.tr, style: TextStyle(fontSize: 22.sp)),
Image(
width: 40.w,
height: 24.w,
image: const AssetImage('images/icon_right_black.png'))
],
child: Obx(
() =>
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('3天滚动储存'.tr,
style: TextStyle(fontSize: 24.sp)),
SizedBox(height: 10.h),
Text("${F
.navTitle}${"已为本设备免费提供3大滚动视频储存服务"
.tr}",
style:
TextStyle(fontSize: 22.sp, color: Colors
.grey)),
],
)),
SizedBox(width: 15.w),
Text('去升级'.tr, style: TextStyle(fontSize: 22.sp)),
Image(
width: 40.w,
height: 24.w,
image: const AssetImage(
'images/icon_right_black.png'))
],
),
SizedBox(
height: 16.h,
),
Text(
'云存服务状态:${_handlerValidityPeriodStatsText()}',
style: TextStyle(
fontSize: 24.sp,
),
),
SizedBox(
height: 8.h,
),
Visibility(
visible: state.validityPeriodInfo.value != null &&
state.validityPeriodInfo.value?.status == 1,
child: Text(
'过期时间:${state.validityPeriodInfo.value
?.validityPeriodEnd}',
style: TextStyle(
fontSize: 24.sp,
),
),
),
SizedBox(
height: 8.h,
),
Visibility(
visible: state.validityPeriodInfo.value != null &&
state.validityPeriodInfo.value?.status == 1,
child: Text(
'滚动存储天数:${state.validityPeriodInfo.value?.rollingStorageDays}',
style: TextStyle(
fontSize: 24.sp,
),
),
),
SizedBox(
height: 8.h,
),
Visibility(
visible: state.validityPeriodInfo.value != null &&
state.validityPeriodInfo.value?.status == 1,
child: Text(
'剩余天数:${state.validityPeriodInfo.value
?.remainingDays} ',
style: TextStyle(
fontSize: 24.sp,
),
),
),
],
),
),
),
);
}
_handlerValidityPeriodStatsText() {
if (state.validityPeriodInfo.value == null) {
return '';
}
if (state.validityPeriodInfo.value?.status == 1) {
return '已开通'.tr;
} else if (state.validityPeriodInfo.value?.status == 2) {
return '已过期'.tr;
} else {
return '未开通'.tr;
}
}
//
Widget localTip() {
return GestureDetector(
@ -244,7 +329,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
// height: 130.h,
margin: EdgeInsets.all(15.w),
padding:
EdgeInsets.only(left: 20.w, top: 30.w, bottom: 30.w, right: 10.w),
EdgeInsets.only(left: 20.w, top: 30.w, bottom: 30.w, right: 10.w),
decoration: BoxDecoration(
color: const Color(0xFFF6F7F8),
borderRadius: BorderRadius.circular(20.h)),
@ -252,15 +337,15 @@ class _VideoLogPageState extends State<VideoLogPage> {
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// SizedBox(height: 20.h),
Text('下载列表'.tr, style: TextStyle(fontSize: 24.sp)),
SizedBox(height: 15.h),
Text('暂无下载内容'.tr,
style: TextStyle(fontSize: 22.sp, color: Colors.grey)),
],
)),
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// SizedBox(height: 20.h),
Text('下载列表'.tr, style: TextStyle(fontSize: 24.sp)),
SizedBox(height: 15.h),
Text('暂无下载内容'.tr,
style: TextStyle(fontSize: 22.sp, color: Colors.grey)),
],
)),
SizedBox(width: 15.w),
// Text("去升级", style: TextStyle(fontSize: 24.sp)),
Image(
@ -334,7 +419,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//
//
crossAxisCount: 3,
//
mainAxisSpacing: 15.w,
@ -356,7 +441,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//
//
crossAxisCount: 3,
//
mainAxisSpacing: 15.w,
@ -384,9 +469,10 @@ class _VideoLogPageState extends State<VideoLogPage> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullScreenImagePage(
imageUrl: recordData.imagesUrl!,
),
builder: (context) =>
FullScreenImagePage(
imageUrl: recordData.imagesUrl!,
),
),
);
}

View File

@ -1,6 +1,8 @@
import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:get/get_rx/get_rx.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
class VideoLogState {
@ -17,4 +19,8 @@ class VideoLogState {
getLockId.value = map['lockId'];
}
}
//
final validityPeriodInfo = Rx<ValidityPeriod?>(null);
RxString cloudStorageWebViewUrl = ''.obs;
}

View File

@ -16,6 +16,5 @@ class VideoLogDetailState {
if (map['videoDataList'] != null) {
videoLogList.value = map['videoDataList'];
}
print('object');
}
}

View File

@ -0,0 +1,419 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
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_colors.dart';
import 'package:star_lock/blue/blue_manage.dart';
import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart';
import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart';
import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart';
import 'package:star_lock/blue/io_reply.dart';
import 'package:star_lock/blue/io_tool/io_tool.dart';
import 'package:star_lock/blue/io_tool/manager_event_bus.dart';
import 'package:star_lock/login/login/entity/LoginEntity.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart';
import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/showTipView.dart';
import 'package:star_lock/tools/storage.dart';
import 'package:http/http.dart' as http;
import 'package:star_lock/translations/app_dept.dart';
class LockVoiceSettingLogic extends BaseGetXController {
LockVoiceSettingState state = LockVoiceSettingState();
StreamSubscription<Reply>? _replySubscription;
bool _isThrottled = false;
//
Timer? _sendTimeoutTimer;
//
bool _isTimeout = false;
@override
void onInit() async {
super.onInit();
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
if (reply is VoicePackageConfigureReply) {
//
_handlerStartVoicePackageConfigure(reply);
} else if (reply is VoicePackageConfigureProcessReply) {
_handlerVoicePackageConfigureProcess(reply);
} else if (reply is VoicePackageConfigureConfirmationReply) {
handleVoiceConfigureThrottled(reply);
}
});
initList();
}
void handleVoiceConfigureThrottled(
VoicePackageConfigureConfirmationReply reply,
) {
if (_isThrottled) return;
_isThrottled = true;
//
_executeLogic(reply);
// 1
Future.delayed(Duration(seconds: 1), () {
_isThrottled = false;
});
}
Future<void> _executeLogic(
VoicePackageConfigureConfirmationReply reply) async {
final LoginEntity entity = await ApiRepository.to.settingCurrentVoiceTimbre(
data: {
'lang': state.tempLangStr.value,
'timbre': state.tempTimbreStr.value,
},
lockId: state.lockSetInfoData.value.lockId!,
);
if (entity.errorCode!.codeIsSuccessful) {
showSuccess('设置成功'.tr, something: () {
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang =
state.tempLangStr.value;
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.timbre = state.tempTimbreStr.value;
eventBus
.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value));
Get.offAllNamed(Routers.starLockMain);
});
}
dismissEasyLoading();
}
void saveSpeechLanguageSettings() async {
var language = state.languages[state.selectPassthroughListIndex.value];
if (language.lang == 'system') {
//
//
// print(CurrentLocaleTool.convertLocale(Get.deviceLocale!));
// APP层的语言
Locale? currentLocale = Get.locale; //
if (currentLocale != null) {
final indexWhere = state.languages
.indexWhere((element) => element.lang == currentLocale.toString());
state.selectPassthroughListIndex.value = indexWhere;
}
}
language = state.languages[state.selectPassthroughListIndex.value];
final value = state.selectSoundTypeIndex.value;
state.tempLangStr.value = language.lang;
language.timbres.forEach((element) async {
if (element.isFemale == value) {
await downloadFile(element.timbrePackUrl);
state.tempTimbreStr.value = element.timbre;
return;
}
});
}
//
Future<void> downloadFile(String url) async {
final http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
state.data = response.bodyBytes;
sendFileToDevice(response.bodyBytes, <int>[0, 0, 0, 0]);
}
}
sendFileToDevice(Uint8List data, List<int> token) {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? signKey =
await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList = changeStringListToIntList(signKey!);
final String uid = await Storage.getUid() ?? '';
final String md5Str = md5.convert(data).toString().toUpperCase();
BlueManage().writeCharacteristicWithResponse(
VoicePackageConfigure(
lockID: BlueManage().connectDeviceName,
userID: uid,
keyID: BlueManage().connectDeviceName,
platform: 0,
product: 0,
fwSize: data.length,
fwMD5: md5Str,
needAuthor: 1,
token: token,
signKey: signKeyDataList,
privateKey: getPrivateKeyList)
.packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
// 1
Future.delayed(const Duration(seconds: 2), () {
// +1
sendFileToDevice(data, token);
});
// showBlueConnetctToast();
}
});
}
void _handlerVoicePackageConfigureProcess(
VoicePackageConfigureProcessReply reply) {
//
_sendTimeoutTimer?.cancel();
_isTimeout = false; //
final int status = reply.data[2];
switch (status) {
case 0x00:
cancelBlueConnetctToastTimer();
state.voiceSubcontractingIndex++;
_sendNextPackage();
break;
default:
showToast('发送分包数据不成功'.tr);
break;
}
}
//
void _handlerStartVoicePackageConfigure(
VoicePackageConfigureReply reply) async {
final int status = reply.data[6];
switch (status) {
case 0x00:
//
cancelBlueConnetctToastTimer();
_startSendLanguageFile();
break;
case 0x06:
//
final List<int> token = reply.data.sublist(2, 6);
if (state.data != null) {
sendFileToDevice(state.data!, token);
}
break;
default:
showToast('获取设备型号失败'.tr);
break;
}
}
///
initList() async {
showEasyLoading();
try {
final vendor = state.lockSetInfoData.value.lockBasicInfo?.vendor;
final model = state.lockSetInfoData.value.lockBasicInfo?.model;
final PassthroughListResponse entity =
await ApiRepository.to.getPassthroughList(data: {
'vendor': vendor!,
'model': model!,
});
if (entity.errorCode!.codeIsSuccessful) {
final data = entity.data;
final locales = appDept.deptSupportedLocales;
state.languages.clear();
state.languages.add(
PassthroughItem(
lang: 'system',
timbres: [],
langText: '跟随系统'.tr,
name: '跟随系统'.tr,
),
);
data?.forEach((element) {
final lang = element.lang;
List<String> parts = lang.split('_');
final indexOf = locales.indexOf(Locale(parts[0], parts[1]));
final passthroughItem = PassthroughItem(
lang: element.lang,
timbres: element.timbres,
langText:
ExtensionLanguageType.fromLocale(locales[indexOf]).lanTitle,
name: element.name,
);
state.languages.add(passthroughItem);
});
state.languages.refresh();
final lang = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
final timbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
state.languages.value.forEach((element) {
final timbres = element.timbres;
timbres.forEach((item) {
if (lang == element.lang && item.timbre == timbre) {
state.selectSoundTypeIndex.value = item.isFemale;
}
});
});
}
} catch (e) {
debugPrint('获取语音包出现错误:$e');
} finally {
dismissEasyLoading();
}
}
//
sendGetDeviceModelBleMessage() {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(
BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
BlueManage().writeCharacteristicWithResponse(
GetDeviceModelCommand(
lockID: BlueManage().connectDeviceName,
).packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
}
},
);
}
void _startSendLanguageFile() {
if (state.data == null) return;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount =
(state.data!.length + state.voiceSubcontractingSize - 1) ~/
state.voiceSubcontractingSize;
state.progress.value = 0.0; //
_sendNextPackage();
}
void _handleSendTimeout() {
_isTimeout = true; //
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
//
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
state.progress.value = 0.0;
_isTimeout = false; //
}
void _sendNextPackage() {
//
if (_isTimeout) return;
//
_sendTimeoutTimer?.cancel();
if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) {
print('所有分包已发送完成');
state.progress.value = 1.0; //
// UI或做后续处理
return;
}
// 3
_sendTimeoutTimer = Timer(Duration(seconds: 3), () {
_handleSendTimeout(); //
});
int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize;
int end = start + state.voiceSubcontractingSize;
if (end > state.data!.length) end = state.data!.length;
Uint8List packageData = state.data!.sublist(start, end);
//
state.progress.value =
(state.voiceSubcontractingIndex + 1) / state.voiceSubcontractingCount;
EasyLoading.showProgress(state.progress.value,
status: '正在发送数据 ${(state.progress.value * 100).toStringAsFixed(0)}%');
_sendLanguageFileBleMessage(
index: state.voiceSubcontractingIndex,
data: packageData,
);
}
_sendLanguageFileBleMessage({required int index, required Uint8List data}) {
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
BlueManage().writeCharacteristicWithResponse(
VoicePackageConfigureProcess(
index: index,
size: data.length,
data: data,
).packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
// showBlueConnetctToast();
}
});
}
@override
void dispose() async {
await _replySubscription?.cancel();
_replySubscription = null;
await BlueManage().disconnect();
dismissEasyLoading();
cancelBlueConnetctToastTimer();
EasyLoading.dismiss();
//
state.progress.value = 0.0;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
super.dispose();
}
@override
void onClose() async {
await _replySubscription?.cancel();
_replySubscription = null;
await BlueManage().disconnect();
dismissEasyLoading();
cancelBlueConnetctToastTimer();
EasyLoading.dismiss();
//
state.progress.value = 0.0;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
super.onClose();
}
}

View File

@ -0,0 +1,183 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:get/get_utils/get_utils.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart';
import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart';
import 'package:star_lock/tools/EasyRefreshTool.dart';
import 'package:star_lock/tools/commonItem.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class LockVoiceSetting extends StatefulWidget {
const LockVoiceSetting();
@override
State<LockVoiceSetting> createState() => _LockVoiceSettingState();
}
class _LockVoiceSettingState extends State<LockVoiceSetting> {
final LockVoiceSettingLogic logic = Get.put(LockVoiceSettingLogic());
final LockVoiceSettingState state = Get.find<LockVoiceSettingLogic>().state;
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return false;
},
child: Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(
barTitle: '锁语音包设置'.tr,
haveBack: false,
haveOtherLeftWidget: true,
leftWidget: TextButton(
onPressed: () {
eventBus
.fire(RefreshLockListInfoDataEvent(isUnShowLoading: true));
Get.offAllNamed(Routers.starLockMain);
},
child: Text(
'跳过'.tr,
style: TextStyle(
color: Colors.white,
fontSize: 24.sp,
fontWeight: FontWeight.w500,
),
),
),
backgroundColor: AppColors.mainColor,
actionsList: [
TextButton(
onPressed: logic.saveSpeechLanguageSettings,
child: Text(
'下载'.tr,
style: TextStyle(
color: Colors.white,
fontSize: 24.sp,
fontWeight: FontWeight.w500,
),
),
),
],
),
body: _buildBody(),
),
);
}
Widget _buildBody() {
return Obx(
() => SingleChildScrollView(
child: Column(
children: [
Container(
width: 1.sw,
decoration: BoxDecoration(color: Colors.white),
child: ListView.builder(
itemCount: state.soundTypeList.length,
itemBuilder: (BuildContext context, int index) {
// itemCount - 1
final isLastItem = index == state.soundTypeList.length - 1;
// platFormSet RxList<Platform>
final platform = state.soundTypeList.value[index];
return CommonItem(
leftTitel: state.soundTypeList.value[index],
rightTitle: '',
isHaveLine: !isLastItem,
// 线
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
// Radio 使 id
value: platform,
// selectPlatFormIndex id
groupValue: state.soundTypeList
.value[state.selectSoundTypeIndex.value],
//
activeColor: AppColors.mainColor,
// Radio
onChanged: (value) {
if (value != null) {
setState(() {
// id
final newIndex = state.soundTypeList.value
.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectSoundTypeIndex.value = newIndex;
}
});
}
},
),
action: () {
setState(() {
state.selectSoundTypeIndex.value = index;
});
},
);
},
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
),
),
SizedBox(
height: 8.h,
),
Column(
children: _buildList(),
),
],
),
),
);
}
List<Widget> _buildList() {
final appLocalLanguages = state.languages;
return List.generate(
appLocalLanguages.length,
(index) => _buildItem(
appLocalLanguages[index],
index,
),
);
}
_buildItem(PassthroughItem passthroughItem, index) {
return CommonItem(
leftTitel: passthroughItem.langText,
rightTitle: '',
isHaveLine: true,
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: state.selectPassthroughListIndex.value == index
? Image(
image: const AssetImage('images/icon_item_checked.png'),
width: 30.w,
height: 30.w,
fit: BoxFit.contain,
)
: Container(),
action: () {
state.selectPassthroughListIndex.value = index;
},
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
if (EasyLoading.isShow) {
EasyLoading.dismiss(animation: true);
}
}
}

View File

@ -0,0 +1,56 @@
import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/translations/app_dept.dart';
class LockVoiceSettingState {
LockVoiceSettingState() {
final map = Get.arguments;
lockSetInfoData.value = map['lockSetInfoData'];
lockBasicInfo.value = lockSetInfoData.value.lockBasicInfo!;
}
Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
Rx<LockBasicInfo> lockBasicInfo = LockBasicInfo().obs;
//
RxInt selectPassthroughListIndex = 0.obs;
//
RxInt selectLanguageIndex = 0.obs;
final RxList<PassthroughItem> languages = <PassthroughItem>[].obs;
Map<int, String> languageSpeechDeviceTypeMapping = {0: '2403'};
RxBool otaUpdateIng = false.obs;
RxDouble otaProgress = 0.00.obs;
RxString deviceModel = '2403'.obs;
Uint8List? data;
//
int voiceSubcontractingSize = 256;
//
int voiceSubcontractingCount = 0;
//
int voiceSubcontractingIndex = 0;
// 0.0~1.0
RxDouble progress = 0.0.obs;
// UI
final RxList<String> soundTypeList = List.of({
'男声'.tr,
'女声'.tr,
}).obs;
RxInt selectSoundTypeIndex = 1.obs;
RxString tempLangStr=''.obs;
RxString tempTimbreStr=''.obs;
}

View File

@ -337,17 +337,15 @@ class NearbyLockLogic extends BaseGetXController {
// 'featureSettingValue': state.featureSettingValue,
// 'featureSettingParams': state.featureSettingParams,
// });
Get.toNamed(Routers.saveLockPage,
arguments: <String, Object?>{
'addressInfo': {},
'pwdTimestamp': state.timestampValue * 1000,
'lockInfo': state.lockInfo,
'featureValue': state.featureValue,
'featureSettingValue': state.featureSettingValue,
'featureSettingParams': state.featureSettingParams,
'isFromMap': 0,
});
Get.toNamed(Routers.saveLockPage, arguments: <String, Object?>{
'addressInfo': {},
'pwdTimestamp': state.timestampValue * 1000,
'lockInfo': state.lockInfo,
'featureValue': state.featureValue,
'featureSettingValue': state.featureSettingValue,
'featureSettingParams': state.featureSettingParams,
'isFromMap': 0,
});
break;
case 0x06:

View File

@ -486,7 +486,6 @@ class SaveLockLogic extends BaseGetXController {
// }
void backAction() async {
// BlueManage().disconnect();
//
@ -502,13 +501,19 @@ class SaveLockLogic extends BaseGetXController {
'lockSetInfoData': state.lockSetInfoData.value,
'pageName': 'saveLock'
});
} else if (state.lockSetInfoData.value.lockFeature?.languageSpeech == 1) {
Get.toNamed(Routers.lockVoiceSettingPage, arguments: {
'lockSetInfoData': state.lockSetInfoData.value,
'pageName': 'saveLock'
});
} else {
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
eventBus.fire(RefreshLockListInfoDataEvent(
clearScanDevices: true, isUnShowLoading: true));
Future<void>.delayed(const Duration(seconds: 1), () {
// Get.close(state.isFromMap == 1
// ? (CommonDataManage().seletLockType == 0 ? 4 : 5)
// : (CommonDataManage().seletLockType == 0 ? 5 : 6));
Get.until((route) => route.isFirst);
Get.until((route) => route.isFirst);
});
// 2
Future<void>.delayed(const Duration(milliseconds: 200), () {
@ -520,7 +525,8 @@ class SaveLockLogic extends BaseGetXController {
});
}
} else {
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
eventBus.fire(RefreshLockListInfoDataEvent(
clearScanDevices: true, isUnShowLoading: true));
Future<void>.delayed(const Duration(seconds: 1), () {
// Get.close(state.isFromMap == 1
// ? (CommonDataManage().seletLockType == 0 ? 4 : 5)

View File

@ -84,17 +84,17 @@ class _SelectLockTypePageState extends State<SelectLockTypePage>
arguments: <String, int>{'getLockType': 1});
}),
// if (!F.isLite)
lockTypeItem('images/lockType/lockType_NFCLock.png', 'NFC无源锁'.tr, () {
CommonDataManage().seletLockType = 2;
// Navigator.pushNamed(context, Routers.addLockPage);
logic.getNearByLimits();
}),
lockTypeItem('images/lockType/lockType_NFCLock.png', 'NFC无源锁'.tr, () {
CommonDataManage().seletLockType = 2;
// Navigator.pushNamed(context, Routers.addLockPage);
logic.getNearByLimits();
}),
// if (!F.isLite)
lockTypeItem('images/lockType/lockType_padlock.png', '挂锁'.tr, () {
CommonDataManage().seletLockType = 3;
// Navigator.pushNamed(context, Routers.addLockPage);
logic.getNearByLimits();
}),
lockTypeItem('images/lockType/lockType_padlock.png', '挂锁'.tr, () {
CommonDataManage().seletLockType = 3;
// Navigator.pushNamed(context, Routers.addLockPage);
logic.getNearByLimits();
}),
lockTypeItem('images/lockType/lockType_safeLock.png', '保险箱锁'.tr, () {
CommonDataManage().seletLockType = 4;
Navigator.pushNamed(context, Routers.addLockPage,
@ -223,9 +223,16 @@ class _SelectLockTypePageState extends State<SelectLockTypePage>
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(lockTypeTitle,
style: TextStyle(
fontSize: 22.sp, color: AppColors.blackColor)),
Text(
lockTypeTitle,
maxLines: 2, //
overflow: TextOverflow.ellipsis, //
softWrap: true, //
style: TextStyle(
fontSize: 22.sp,
color: AppColors.blackColor,
),
),
],
),
),

View File

@ -25,6 +25,7 @@ class SelectGatewayListLogic extends BaseGetXController {
//
late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() {
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
@ -35,7 +36,6 @@ class SelectGatewayListLogic extends BaseGetXController {
});
}
// WIFI配网结果
Future<void> _replyGatewayGetStatusReply(Reply reply) async {
final int status = reply.data[2];
@ -99,7 +99,7 @@ class SelectGatewayListLogic extends BaseGetXController {
void startScanBlueList() {
state.devices.clear();
BlueManage().startScan(2000, DeviceType.gateway, (List<ScanResult> list) {
AppLog.log('ScanResultList:$list');
// AppLog.log('ScanResultList:$list');
for (int i = 0; i < list.length; i++) {
final ScanResult device = list[i];
// if ((device.advertisementData.serviceUuids.isNotEmpty
@ -211,7 +211,12 @@ class SelectGatewayListLogic extends BaseGetXController {
@override
void dispose() {
super.dispose();
_replySubscription.cancel();
super.dispose();
}
@override
void onClose() {
_replySubscription.cancel();
super.onClose();
}
}

View File

@ -32,12 +32,16 @@ class Data {
String? vipBuyUrl;
String? cloudauthBuyUrl;
String? shopList;
String? cloudStorage;
String? valueAddServiceLimitFree;
Data(
{this.smsBuyUrl,
this.emailBuyUrl,
this.vipBuyUrl,
this.cloudauthBuyUrl,
this.cloudStorage,
this.valueAddServiceLimitFree,
this.shopList});
Data.fromJson(Map<String, dynamic> json) {
@ -46,6 +50,8 @@ class Data {
vipBuyUrl = json['vip_buy_url'];
cloudauthBuyUrl = json['cloudauth_buy_url'];
shopList = json['shopList'];
cloudStorage = json['cloud_storage'];
valueAddServiceLimitFree = json['value_add_service_limit_free'];
}
Map<String, dynamic> toJson() {
@ -55,6 +61,8 @@ class Data {
data['vip_buy_url'] = vipBuyUrl;
data['cloudauth_buy_url'] = cloudauthBuyUrl;
data['shopList'] = shopList;
data['cloud_storage'] = cloudStorage;
data['value_add_service_limit_free'] = valueAddServiceLimitFree;
return data;
}
}

View File

@ -40,6 +40,9 @@ class AdvancedFeaturesWebLogic extends BaseGetXController {
} else if (state.webBuyType.value == XSConstantMacro.webBuyTypeShop) {
state.webBuyUrl.value = entity.data!.shopList!;
state.webBuyTitle.value = '商城购买'.tr;
}else if (state.webBuyType.value == XSConstantMacro.webBuyTypeCloudStorage) {
state.webBuyUrl.value = entity.data!.cloudStorage!;
state.webBuyTitle.value = '云存购买'.tr;
}
state.webBuyView.setNavigationDelegate(

View File

@ -19,6 +19,8 @@ class AdvancedFeaturesWebState {
webBuyTitle.value = '邮件购买'.tr;
} else if (webBuyType.value == XSConstantMacro.webBuyTypeShop) {
webBuyTitle.value = '商城购买'.tr;
}else if (webBuyType.value == XSConstantMacro.webBuyTypeCloudStorage) {
webBuyTitle.value = '云存购买'.tr;
}
}
}

View File

@ -0,0 +1,6 @@
import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart';
import 'package:star_lock/tools/baseGetXController.dart';
class CloudStorageLogic extends BaseGetXController {
CloudStorageState state = CloudStorageState();
}

View File

@ -0,0 +1,150 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_logic.dart';
import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class CloudStoragePage extends StatefulWidget {
const CloudStoragePage();
@override
State<CloudStoragePage> createState() => _CloudStoragePageState();
}
class _CloudStoragePageState extends State<CloudStoragePage> {
final CloudStorageLogic logic = Get.put(CloudStorageLogic());
final CloudStorageState state = Get.find<CloudStorageLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: TitleAppBar(
barTitle: '云存储购买'.tr,
haveBack: true,
iconColor: Colors.black,
titleColor: Colors.black,
backgroundColor: Colors.white,
),
body: SafeArea(
child: _buildBody(),
),
);
}
Widget _buildBody() {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.center,
colors: [Color(0xFFC5F0E7), Color(0xFFF7F7F7)],
),
),
child: Column(
children: [
//
_buildPurchasePackage()
],
),
);
}
Widget _buildPurchasePackage() {
return Container(
width: 1.sw,
margin: EdgeInsets.symmetric(
vertical: 12.h,
horizontal: 14.w,
),
decoration: BoxDecoration(
color: const Color(0xFFF7F7F7),
borderRadius: BorderRadiusDirectional.all(
Radius.circular(16.r),
),
),
child: Column(
children: [
_buildTabs(),
_buildTabContent(),
],
),
);
}
Widget _buildTabs() {
return Obx(
() => Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: List.generate(
state.tabs.length,
(int index) => _buildTabItem(index),
),
),
);
}
Widget _buildTabItem(int index) {
return Expanded(
child: GestureDetector(
onTap: () {
state.selectedIndex.value = index;
},
child: Container(
height: 68.h,
decoration: BoxDecoration(
color: _isSelectTabBgColor(index),
borderRadius: BorderRadiusDirectional.only(
topStart: Radius.circular(16.r),
topEnd: Radius.circular(16.r),
),
),
child: Center(
child: Text(
state.tabs[index],
style: _isSelectTabTitle(index),
),
),
),
),
);
}
TextStyle _isSelectTabTitle(int index) {
if (state.selectedIndex.value == index) {
return TextStyle(
color: const Color(0xFF040404),
fontWeight: FontWeight.w600,
fontSize: 28.sp,
);
}
return TextStyle(
color: const Color(0xFF8F8F8F),
fontSize: 28.sp,
);
}
Color _isSelectTabBgColor(int index) {
if (state.selectedIndex.value == index) {
return Colors.white;
}
return const Color(0xFFF7F7F7);
}
Widget _buildTabContent() {
return Container(
width: 1.sw,
padding: EdgeInsets.symmetric(
vertical: 12.h,
horizontal: 14.w,
),
decoration: BoxDecoration(
color: Colors.white,
),
child: Text('asd'),
);
}
}

View File

@ -0,0 +1,13 @@
import 'package:get/get.dart';
class CloudStorageState {
//
RxInt selectedIndex = 0.obs;
//
final List<String> tabs = ['7天滚动存储', '30天滚动存储'];
final List<Map<String, dynamic>> tabContent = [
{'title': '连续包月', 'price': '1', 'price2': '188', 'discount': '立省188元'},
{'title': '连续包月', 'price': '1', 'price2': '188', 'discount': '立省188元'}
];
}

View File

@ -265,6 +265,8 @@ abstract class Api {
final String getServiceUserPackageURL =
'/v2/service/getUserPackage'; //
final String getValidityPeriodInfoURL = '/passthrough';
//
final String getlockCloudStorageListURL = '/lockCloudStorage/list'; //
final String deleteLockCloudStorageURL = '/lockCloudStorage/delete'; //
@ -298,4 +300,9 @@ abstract class Api {
'/SL-A-1.0/peer/nslookup'; // --
final String bindUserStarchartURL =
'/userStarchart/bindUserStarchart'; //
final String getPassthroughListURL = '/passthrough'; //
final String updateCurrentVoiceTimbre =
'/lockSetting/updateLockSetting'; //
final String reportBuyRequestURL =
'/service/reportBuyRequest'; //
}

View File

@ -2400,6 +2400,22 @@ class ApiProvider extends BaseProvider {
'searchStr': searchStr
}));
//
Future<Response> getValidityPeriodInfo(
int lockId, {
String request_method = 'POST',
String request_uri = '/api/v1/cloudStorage/getStorageServiceInfo',
required Map<String, dynamic> post_args,
}) =>
post(
getValidityPeriodInfoURL.toUrl,
jsonEncode({
'lockId': lockId,
'request_method': request_method,
'request_uri': request_uri,
'post_args': post_args,
}));
//
Future<Response> getLockCloudStorageList(int lockId) =>
post(getlockCloudStorageListURL.toUrl, jsonEncode({'lockId': lockId}));
@ -2773,6 +2789,55 @@ class ApiProvider extends BaseProvider {
isShowNetworkErrorMsg: false,
isShowErrMsg: false,
isUnShowLoading: true);
///
Future<Response> getPassthroughList(
String requestMethod,
String requestUri,
Map<String, String> data,
) =>
post(
getPassthroughListURL.toUrl,
jsonEncode({
'request_method': requestMethod,
'request_uri': requestUri,
'post_args': data,
}),
isShowNetworkErrorMsg: false,
isShowErrMsg: false,
isUnShowLoading: true);
///
Future<Response> settingCurrentVoiceTimbre(
int lockId,
Map<String, String> data,
) =>
post(
updateCurrentVoiceTimbre.toUrl,
jsonEncode({
'lockId': lockId,
'currentVoiceTimbre': data,
}),
isShowNetworkErrorMsg: false,
isShowErrMsg: false,
isUnShowLoading: true);
///
Future<Response> reportBuyRequest(
int lockId,
String type,
) =>
post(
reportBuyRequestURL.toUrl,
jsonEncode({
'lockId': lockId,
'type': type,
}),
isShowNetworkErrorMsg: false,
isShowErrMsg: false,
isUnShowLoading: true);
}
extension ExtensionString on String {

View File

@ -13,6 +13,7 @@ import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/se
import 'package:star_lock/main/lockDetail/face/addFace/addFace_entity.dart';
import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprint_entity.dart';
import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/basicInformation/basicInformation/KeyDetailEntity.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockEscalation/updateLockInfo_entity.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockEscalation/version_entity.dart';
@ -2435,6 +2436,30 @@ class ApiRepository {
return CoerceFingerprintListEntity.fromJson(res.body);
}
//
Future<ValidityPeriodResponse> getValidityPeriodInfo({
required int lockId,
}) async {
Map<String, dynamic> post_args = Map.of({'lockId': lockId});
final res = await apiProvider.getValidityPeriodInfo(
lockId,
post_args: post_args,
);
return ValidityPeriodResponse.fromJson(res.body);
}
//
Future<LoginEntity> uploadReportBuyRequest({
required int lockId,
String type = 'cloud_storage',
}) async {
final res = await apiProvider.reportBuyRequest(
lockId,
type,
);
return LoginEntity.fromJson(res.body);
}
//
Future<VideoLogEntity> getLockCloudStorageList({required int lockId}) async {
final res = await apiProvider.getLockCloudStorageList(lockId);
@ -2770,4 +2795,30 @@ class ApiRepository {
);
return DeviceNetwork.fromJson(res.body);
}
//
Future<PassthroughListResponse> getPassthroughList({
String requestMethod = 'POST',
String requestUri = '/api/v1/voice/packs',
required Map<String, String> data,
}) async {
final res = await apiProvider.getPassthroughList(
requestMethod,
requestUri,
data,
);
return PassthroughListResponse.fromJson(res.body);
}
//
Future<LoginEntity> settingCurrentVoiceTimbre({
required int lockId,
required Map<String, String> data,
}) async {
final res = await apiProvider.settingCurrentVoiceTimbre(
lockId,
data,
);
return LoginEntity.fromJson(res.body);
}
}

View File

@ -277,7 +277,6 @@ class MessageCommand {
int? SpTotal,
int? SpIndex,
}) {
final payload = talkData.writeToBuffer();
ScpMessage message = ScpMessage(
ProtocolFlag: ProtocolFlagConstant.scp01,

View File

@ -630,6 +630,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
//
StartChartManage().reSetDefaultTalkExpect();
StartChartManage().stopTalkExpectMessageTimer();
VideoDecodePlugin.releaseDecoder();
//

View File

@ -40,6 +40,7 @@ const String lockNetWorkInfo = 'lockNetWorkInfo'; //锁板配网信息
const String appVersionHistoryUrl = 'appVersionHistoryUrl'; //
const String voipToken = 'voipToken'; //
const String deviceModel = 'deviceModel'; //
class Storage {
factory Storage() => _instance;