diff --git a/docs/修改记录_2026-09-02_母乳杯蓝牙改造.md b/docs/修改记录_2026-09-02_母乳杯蓝牙改造.md index dea101c..e663e2a 100644 --- a/docs/修改记录_2026-09-02_母乳杯蓝牙改造.md +++ b/docs/修改记录_2026-09-02_母乳杯蓝牙改造.md @@ -75,3 +75,18 @@ version/sysinfo/bankinfo 显示、temp/fan(待固件)、本地 bin OTA 后 bankinfo 确认切 bank。 - OTA 大数据量发送走 Write Without Response + 扇区级 ack 流控,若实测丢包导致 status=2 重同步频繁,可在 OtaManager 扇区内加小窗口节流。 + +## 后续调整(同日) + +- **uts 编译修复**:`match()` 结果元素可空需先判空;uts 函数不能直接当 lambda 传递 + (改为箭头函数包装);uvue 页面内函数需"定义在前、使用在后";`setTimeout` 不接受 + async 回调(改 then 链);`java.io` 交互处需显式 `Int` 类型。 +- **UI 全面英文化**:pages.json 导航/ tab(Device/Status/OTA/my/CLI Terminal)、 + home/sysStatus/ota/my/CLI 终端全部文案与 toast、OtaManager 升级日志消息、 + manifest 应用名 `smartAssister`、iOS 蓝牙用途英文描述。 +- **扫描不过滤**:设备页去掉 `CAIIC-MCM` 名称前缀过滤,扫到的设备全部列出; + `BluetoothManager.startScan` 的 `showEmptyName` 改为 1(无广播名设备也返回, + 列表中匿名设备显示 N/A)。 +- **APP 图标**:新增 `static/appIcon.png`(1024×1024,蓝色渐变底 + 白色母乳杯 + + 蓝牙徽标,脚本生成),manifest 的 Android 四档与 iOS appstore 图标均指向它; + 图标与应用名需重打自定义基座并重装后生效。 diff --git a/manifest.json b/manifest.json index a4865e1..9310805 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "name": "smartassister", + "name": "smartAssister", "appid": "__UNI__884AC41", "description": "", "versionName": "1.0.1", @@ -46,10 +46,10 @@ "distribute": { "modules": {}, "icons": { - "hdpi": "/static/androidApp.png", - "xhdpi": "/static/androidApp.png", - "xxhdpi": "/static/androidApp.png", - "xxxhdpi": "/static/androidApp.png" + "hdpi": "/static/appIcon.png", + "xhdpi": "/static/appIcon.png", + "xxhdpi": "/static/appIcon.png", + "xxxhdpi": "/static/appIcon.png" }, "splashScreens": { "default": {} @@ -69,12 +69,12 @@ "uni-barcode-scanning": {} }, "icons": { - "appstore": "/static/androidApp.png" + "appstore": "/static/appIcon.png" }, "splashScreens": {}, "privacyDescription": { - "NSBluetoothPeripheralUsageDescription": "请允许使用蓝牙功能。该功能用于:连接母乳杯设备,显示温度、风扇转速等运行参数,查询设备系统状态,并通过蓝牙为设备升级固件。", - "NSBluetoothAlwaysUsageDescription": "请允许使用蓝牙功能。该功能用于:连接母乳杯设备,显示温度、风扇转速等运行参数,查询设备系统状态,并通过蓝牙为设备升级固件。", + "NSBluetoothPeripheralUsageDescription": "Please allow Bluetooth access. It is used to connect to the mother cup device: displaying runtime parameters such as temperature and fan speed, querying device system status, and upgrading the device firmware over Bluetooth.", + "NSBluetoothAlwaysUsageDescription": "Please allow Bluetooth access. It is used to connect to the mother cup device: displaying runtime parameters such as temperature and fan speed, querying device system status, and upgrading the device firmware over Bluetooth.", "NSLocationWhenInUseUsageDescription": "Please allow the use of location services to identify the position of charging stations. This app promises that this function will not be used for any other purposes.", "NSLocalNetworkUsageDescription": "Please allow the use of network connectivity for communication between the app and the cloud service backend to enable charging-related features. This app promises that it will only be used to complete charging-related services with the cloud backend and will not be utilized for any other purposes.", "NSCameraUsageDescription": "Please allow the use of the camera function. This function is solely used for scanning the QR codes on charging piles to obtain information corresponding to the QR codes. This app promises that the function will not be used for any other purposes." @@ -94,4 +94,4 @@ "mode": "" } } -} \ No newline at end of file +} diff --git a/pages.json b/pages.json index 71eb819..0471059 100644 --- a/pages.json +++ b/pages.json @@ -3,7 +3,7 @@ { "path": "pages/tabbar/home", "style": { - "navigationBarTitleText": "母乳杯设备", + "navigationBarTitleText": "Device", "navigationBarBackgroundColor": "#3A6FA1", "enablePullDownRefresh": true } @@ -11,7 +11,7 @@ { "path": "pages/tabbar/sysStatus", "style": { - "navigationBarTitleText": "系统状态", + "navigationBarTitleText": "System Status", "navigationBarBackgroundColor": "#3A6FA1", "enablePullDownRefresh": true } @@ -19,7 +19,7 @@ { "path": "pages/tabbar/ota", "style": { - "navigationBarTitleText": "固件升级", + "navigationBarTitleText": "Firmware Upgrade", "navigationBarBackgroundColor": "#3A6FA1" } }, @@ -63,7 +63,7 @@ { "path": "pages/bleTest/bluetoothOperation/bluetoothOperation", "style": { - "navigationBarTitleText": "CLI 调试终端" + "navigationBarTitleText": "CLI Terminal" } } ], @@ -75,19 +75,19 @@ "list": [ { "pagePath": "pages/tabbar/home", - "text": "设备", + "text": "Device", "iconPath": "/static/tabbar/homeDefault.png", "selectedIconPath": "/static/tabbar/homeActive.png" }, { "pagePath": "pages/tabbar/sysStatus", - "text": "状态", + "text": "Status", "iconPath": "/static/tabbar/mapDefault.png", "selectedIconPath": "/static/tabbar/mapActive.png" }, { "pagePath": "pages/tabbar/ota", - "text": "升级", + "text": "OTA", "iconPath": "/static/tabbar/chargeDefault.png", "selectedIconPath": "/static/tabbar/chargeActive.png" }, diff --git a/pages/bleTest/bluetoothOperation/bluetoothOperation.uvue b/pages/bleTest/bluetoothOperation/bluetoothOperation.uvue index 42f11ee..b904814 100644 --- a/pages/bleTest/bluetoothOperation/bluetoothOperation.uvue +++ b/pages/bleTest/bluetoothOperation/bluetoothOperation.uvue @@ -17,7 +17,7 @@ - + @@ -147,9 +147,9 @@ async function onSendCmd() { if (r.status == 0) { pushMsg("rx", r.text.length > 0 ? r.text : "(ok)") } else if (r.status == 1) { - pushMsg("message", "未知命令或行超长") + pushMsg("message", "Unknown command or line too long") } else { - pushMsg("message", "命令失败 status=" + r.status + (r.text.length > 0 ? (", 已收: " + r.text) : "")) + pushMsg("message", "Command failed, status=" + r.status + (r.text.length > 0 ? (", received: " + r.text) : "")) } } diff --git a/pages/tabbar/home.uvue b/pages/tabbar/home.uvue index 81aeca1..de3c5b3 100644 --- a/pages/tabbar/home.uvue +++ b/pages/tabbar/home.uvue @@ -8,23 +8,23 @@ - {{ connected ? '已连接' : (connecting ? '连接中...' : '未连接') }} + {{ connected ? 'Connected' : (connecting ? 'Connecting...' : 'Disconnected') }} {{ deviceName }} ({{ deviceMac }}) - - + + - 温度 + Temperature {{ temperature }} ℃ - 风扇转速 + Fan Speed {{ fanSpeed }} RPM @@ -32,11 +32,11 @@ - 固件版本 + Firmware {{ fwVersion }} - 运行 Bank + Bank {{ bankInfo }} @@ -49,13 +49,13 @@ - {{ item.device.name }} + {{ item.device.name ?? 'N/A' }} {{ item.device.address }} - 未发现 CAIIC-MCM 设备,点击"扫描设备"重试 + No device found. Tap "Scan" to retry @@ -166,7 +166,7 @@ function onBleStatueListener(state: number) { } else if (state == 10000) { // 连接失败 connecting.value = false connected.value = false - uni.showToast({ title: '连接失败', icon: 'error' }) + uni.showToast({ title: 'Connection failed', icon: 'error' }) } else if (state == 10001) { // 已断开 onDisConnectUi() } @@ -188,17 +188,15 @@ function onBleStarScan() { Ble.startScan(scanMs, function(res: MyApiResult) { if (res.type == 0) { const scan = res.data as BleScanResult - const name = scan.device.name ?? "" - if (name.indexOf(DEVICE_NAME_FILTER) < 0) return // 只显示母乳杯设备 // 去重 for (let i = 0; i < scanArray.value.length; i++) { if (scanArray.value[i].device.address == scan.device.address) return } scanArray.value.push(scan) } else if (res.type == 10003) { - uni.showToast({ title: '无蓝牙权限', icon: 'none' }) + uni.showToast({ title: 'No Bluetooth permission', icon: 'none' }) } else if (res.type == 10002) { - uni.showToast({ title: '蓝牙未开启', icon: 'none' }) + uni.showToast({ title: 'Bluetooth is not turned on', icon: 'none' }) } }) setTimeout(() => { diff --git a/pages/tabbar/my.uvue b/pages/tabbar/my.uvue index 57584a0..b7a8fda 100644 --- a/pages/tabbar/my.uvue +++ b/pages/tabbar/my.uvue @@ -17,7 +17,7 @@ - 后台服务器 + Server {{currentServerName}} @@ -31,7 +31,7 @@ - CLI 调试终端 + CLI Terminal @@ -80,7 +80,7 @@ function onServerTap() { setBaseUrl(SERVER_LIST[idx].url) currentServerName.value = SERVER_LIST[idx].name uni.showToast({ - title: '已切换到: ' + SERVER_LIST[idx].name, + title: 'Switched to: ' + SERVER_LIST[idx].name, icon: 'none', duration: 2000 }) diff --git a/pages/tabbar/ota.uvue b/pages/tabbar/ota.uvue index b72b984..6ef9fea 100644 --- a/pages/tabbar/ota.uvue +++ b/pages/tabbar/ota.uvue @@ -5,42 +5,42 @@ - 设备未连接,请先在"设备"页连接 CAIIC-MCM + Not connected. Please connect a CAIIC-MCM device on the Device tab first @@ -141,19 +141,19 @@ function onLoadFile() { const bytes = readFileBytes(filePath.value.trim()) if (bytes == null) { fileLoaded.value = false - uni.showToast({ title: '文件读取失败,请检查路径', icon: 'error' }) + uni.showToast({ title: 'Failed to read file, check the path', icon: 'error' }) return } if (bytes.length > 0x38000) { fileLoaded.value = false - uni.showToast({ title: '文件超过 224KB 上限', icon: 'error' }) + uni.showToast({ title: 'File exceeds the 224KB limit', icon: 'error' }) return } imageBytes = bytes fileSize.value = bytes.length fileCrcHex.value = crc32Ieee(bytes).toString(16) fileLoaded.value = true - addLog("已加载文件: " + bytes.length + " 字节, CRC32=0x" + fileCrcHex.value) + addLog("File loaded: " + bytes.length + " bytes, CRC32=0x" + fileCrcHex.value) } // ================= 版本号解析 "1.00.02" -> 0x010002 ================= @@ -174,17 +174,17 @@ function parseVersion(v: string): number | null { async function onStartOta() { const version = parseVersion(versionText.value) if (version == null) { - uni.showToast({ title: '版本号格式错误(如 1.00.02)', icon: 'error' }) + uni.showToast({ title: 'Invalid version format (e.g. 1.00.02)', icon: 'error' }) return } if (!Ble.isConnected()) { - uni.showToast({ title: '设备未连接', icon: 'error' }) + uni.showToast({ title: 'Device not connected', icon: 'error' }) return } upgrading.value = true progress.value = 0 logs.value = [] - addLog("开始升级,目标版本 " + versionText.value) + addLog("Upgrade started, target version " + versionText.value) const cbs: OtaCallbacks = { onProgress: (percent: number) => { progress.value = percent @@ -196,15 +196,15 @@ async function onStartOta() { const ok = await Ota.start(imageBytes, version, cbs) upgrading.value = false if (ok) { - uni.showToast({ title: '升级成功,设备将自动复位', icon: 'success' }) + uni.showToast({ title: 'Upgrade succeeded, device will reboot', icon: 'success' }) } else { - uni.showToast({ title: '升级失败', icon: 'error' }) + uni.showToast({ title: 'Upgrade failed', icon: 'error' }) } } function onAbortOta() { Ota.abort() - addLog("用户请求中止 ...") + addLog("Abort requested...") } // ================= 设备信息 ================= @@ -224,7 +224,7 @@ function onBleStatueListener(state: number) { if (state == 10000 || state == 10001) { connected.value = false if (upgrading.value) { - addLog("连接断开,升级中止") + addLog("Disconnected, upgrade aborted") upgrading.value = false } } diff --git a/pages/tabbar/sysStatus.uvue b/pages/tabbar/sysStatus.uvue index 5c1b53a..3ade3f1 100644 --- a/pages/tabbar/sysStatus.uvue +++ b/pages/tabbar/sysStatus.uvue @@ -5,30 +5,30 @@ - 设备未连接,请先在"设备"页连接 CAIIC-MCM + Not connected. Please connect a CAIIC-MCM device on the Device tab first diff --git a/src/BluetoothManager.uts b/src/BluetoothManager.uts index 2f722ac..16d4a59 100644 --- a/src/BluetoothManager.uts +++ b/src/BluetoothManager.uts @@ -21,7 +21,7 @@ export function startScan(timeoutMs: number, cb: (res: MyApiResult) => void) { // ble().startScanBleDevice(timeoutMs, cb) // 旧版本 ble().onStartScanBle({ scantime:timeoutMs, // 超时时间 ms - showEmptyName:0, // 0表示 不返回空的名称 1 表示可返回空名称蓝牙 + showEmptyName:1, // 0表示 不返回空的名称 1 表示可返回空名称蓝牙 btNameFilter:"", // showEmptyName 为0有效 代表过滤相关的名字 为空表示不过滤 onScanResult:(cb) } as ScanPara) diff --git a/src/mcm/OtaManager.uts b/src/mcm/OtaManager.uts index 7c33280..8af972d 100644 --- a/src/mcm/OtaManager.uts +++ b/src/mcm/OtaManager.uts @@ -99,18 +99,18 @@ async function run(image: number[], version: number, cb: OtaCallbacks): Promise< pushU32LE(pb, total) pushU32LE(pb, crc) pushU32LE(pb, version) - cb.onState("发送 OTA_BEGIN(" + total + " 字节)...") + cb.onState("Sending OTA_BEGIN (" + total + " bytes)...") if (!await sendFrame(TYPE_OTA_BEGIN, pb)) { - cb.onState("OTA_BEGIN 发送失败") + cb.onState("Failed to send OTA_BEGIN") return false } let ack = await waitRsp(TYPE_OTA_BEGIN, 5000) if (!ack.received) { - cb.onState(ack.status == -2 ? "升级已中止" : "等待 OTA_BEGIN 应答超时") + cb.onState(ack.status == -2 ? "Upgrade aborted" : "Timeout waiting for OTA_BEGIN ack") return false } if (ack.status != 0) { - cb.onState("设备拒绝升级: " + statusText(ack.status)) + cb.onState("Device rejected upgrade: " + statusText(ack.status)) return false } @@ -118,7 +118,7 @@ async function run(image: number[], version: number, cb: OtaCallbacks): Promise< let offset = 0 while (offset < total) { if (aborted) { - cb.onState("升级已中止") + cb.onState("Upgrade aborted") return false } const sectorEnd = Math.min(offset + SECTOR_SIZE, total) @@ -131,7 +131,7 @@ async function run(image: number[], version: number, cb: OtaCallbacks): Promise< payload.push(image[pos + i]) } if (!await sendFrame(TYPE_OTA_DATA, payload)) { - cb.onState("OTA_DATA 写入失败 offset=" + pos) + cb.onState("Failed to write OTA_DATA, offset=" + pos) return false } pos += n @@ -141,17 +141,17 @@ async function run(image: number[], version: number, cb: OtaCallbacks): Promise< // 满扇区:设备擦写完成后回 OTA_RSP(0x11)(擦写期间关中断数十 ms,超时给足) ack = await waitRsp(TYPE_OTA_DATA, 8000) if (!ack.received) { - cb.onState(ack.status == -2 ? "升级已中止" : "等待扇区应答超时 offset=" + offset) + cb.onState(ack.status == -2 ? "Upgrade aborted" : "Timeout waiting for sector ack, offset=" + offset) return false } if (ack.status == 2) { // offset 乱序:从设备期望的 offset 重发重同步 offset = ack.offset - cb.onState("重同步至 offset=" + offset) + cb.onState("Resync to offset=" + offset) continue } if (ack.status != 0) { - cb.onState("设备写入错误: " + statusText(ack.status)) + cb.onState("Device write error: " + statusText(ack.status)) return false } } @@ -161,22 +161,22 @@ async function run(image: number[], version: number, cb: OtaCallbacks): Promise< // 3. OTA_END:设备 flush 尾部并整镜像回读校验 CRC32 const pe = [] as number[] pushU32LE(pe, crc) - cb.onState("发送 OTA_END,设备校验镜像 ...") + cb.onState("Sending OTA_END, verifying image on device...") if (!await sendFrame(TYPE_OTA_END, pe)) { - cb.onState("OTA_END 发送失败") + cb.onState("Failed to send OTA_END") return false } ack = await waitRsp(TYPE_OTA_END, 15000) if (!ack.received) { - cb.onState(ack.status == -2 ? "升级已中止" : "等待 OTA_END 应答超时") + cb.onState(ack.status == -2 ? "Upgrade aborted" : "Timeout waiting for OTA_END ack") return false } if (ack.status != 0) { - cb.onState("镜像校验失败: " + statusText(ack.status)) + cb.onState("Image verification failed: " + statusText(ack.status)) return false } cb.onProgress(100) - cb.onState("升级成功,设备约 200ms 后自动复位运行新固件,请重新连接") + cb.onState("Upgrade succeeded. Device will reboot into the new firmware in ~200ms, please reconnect.") return true } @@ -187,11 +187,11 @@ async function run(image: number[], version: number, cb: OtaCallbacks): Promise< */ export async function start(image: number[], version: number, cb: OtaCallbacks): Promise { if (running) { - cb.onState("已有升级任务进行中") + cb.onState("Upgrade already in progress") return false } if (image.length < 4 || image.length > BANK_MAX) { - cb.onState("镜像大小非法(4 ~ " + BANK_MAX + " 字节)") + cb.onState("Invalid image size (4 ~ " + BANK_MAX + " bytes)") return false } running = true diff --git a/static/appIcon.png b/static/appIcon.png new file mode 100644 index 0000000..7f4a13a Binary files /dev/null and b/static/appIcon.png differ