Commit 499e4a42bb09bbd9e63a16e718ee038a46a5f339

Authored by “wangming”
1 parent 557c9c0e

Enhance Bluetooth functionality and localization support

- Added support for displaying paired Bluetooth devices in the UI.
- Improved Bluetooth scanning logic to include classic Bluetooth devices.
- Updated localization files for English and Chinese to include new strings related to Bluetooth devices.
- Refined error handling and user feedback during Bluetooth operations.
- Enhanced built-in printer connection logic to probe multiple ports for better reliability.
美国版/Food Labeling Management App UniApp/src/locales/en.ts
... ... @@ -53,6 +53,11 @@ export default {
53 53 connectFail: 'Connection failed',
54 54 bleNotAvailable: 'Bluetooth not available',
55 55 noDevices: 'No devices found',
  56 + pairedDevices: 'Paired Devices',
  57 + noPairedDevices: 'No paired Bluetooth devices',
  58 + classic: 'Classic',
  59 + ble: 'BLE',
  60 + dual: 'Dual',
56 61 printer1: { name: 'Kitchen Printer #1', location: 'Main Kitchen' },
57 62 printer2: { name: 'Kitchen Printer #2', location: 'Main Kitchen' },
58 63 printer3: { name: 'Prep Area Printer', location: 'Prep Station' },
... ...
美国版/Food Labeling Management App UniApp/src/locales/zh.ts
... ... @@ -53,6 +53,11 @@ export default {
53 53 connectFail: '连接失败',
54 54 bleNotAvailable: '蓝牙未开启或不可用',
55 55 noDevices: '未发现设备',
  56 + pairedDevices: '已配对设备',
  57 + noPairedDevices: '没有已配对的蓝牙设备',
  58 + classic: '经典',
  59 + ble: '低功耗',
  60 + dual: '双模',
56 61 printer1: { name: '厨房打印机 #1', location: '主厨房' },
57 62 printer2: { name: '厨房打印机 #2', location: '主厨房' },
58 63 printer3: { name: '准备区打印机', location: '准备站' },
... ...
美国版/Food Labeling Management App UniApp/src/pages/labels/bluetooth.vue
... ... @@ -234,7 +234,7 @@ const initBluetooth = (): Promise<void> => {
234 234 })
235 235 }
236 236  
237   -const startDiscovery = () => {
  237 +const startBleScan = () => {
238 238 uni.startBluetoothDevicesDiscovery({
239 239 allowDuplicatesKey: false,
240 240 success: () => {
... ... @@ -242,29 +242,9 @@ const startDiscovery = () => {
242 242 errorMsg.value = ''
243 243 },
244 244 fail: (err: any) => {
245   - isScanning.value = false
246   - errorMsg.value = 'Scan failed: ' + (err.errMsg || 'Unknown error')
  245 + console.error('BLE startBluetoothDevicesDiscovery fail:', err)
247 246 },
248 247 })
249   - // 同时启动经典蓝牙扫描(发现 d320fax_295c 等未配对设备,不过滤任何设备)
250   - // #ifdef APP-PLUS
251   - const classic = getClassicBluetooth()
252   - if (classic && classic.startClassicDiscovery) {
253   - classic.startClassicDiscovery(
254   - (dev: { name: string; deviceId: string; type: string }) => {
255   - if (discoveredIds.has(dev.deviceId)) return
256   - discoveredIds.add(dev.deviceId)
257   - devices.value.push({
258   - deviceId: dev.deviceId,
259   - name: dev.name || 'Unknown',
260   - type: (dev.type as BtDevice['type']) || 'classic',
261   - })
262   - devices.value.sort((a, b) => (b.RSSI || -100) - (a.RSSI || -100))
263   - },
264   - () => { /* 经典蓝牙扫描完成 */ },
265   - )
266   - }
267   - // #endif
268 248 }
269 249  
270 250 const stopDiscovery = () => {
... ... @@ -383,15 +363,41 @@ const handleScan = async () => {
383 363 errorMsg.value = ''
384 364 devices.value = []
385 365 discoveredIds.clear()
  366 +
  367 + addPairedDevices()
  368 +
  369 + // #ifdef APP-PLUS
  370 + const classic = getClassicBluetooth()
  371 + if (classic && classic.startClassicDiscovery) {
  372 + try {
  373 + classic.startClassicDiscovery(
  374 + (dev: { name: string; deviceId: string; type: string }) => {
  375 + if (discoveredIds.has(dev.deviceId)) return
  376 + discoveredIds.add(dev.deviceId)
  377 + devices.value.push({
  378 + deviceId: dev.deviceId,
  379 + name: dev.name || 'Unknown',
  380 + type: (dev.type as BtDevice['type']) || 'classic',
  381 + })
  382 + },
  383 + () => {},
  384 + )
  385 + isScanning.value = true
  386 + } catch (e) {
  387 + console.error('Classic discovery failed', e)
  388 + }
  389 + }
  390 + // #endif
  391 +
  392 + if (devices.value.length > 0) {
  393 + uni.showToast({ title: `Found ${devices.value.length} device(s)`, icon: 'none' })
  394 + }
  395 +
386 396 try {
387 397 if (!btAdapterReady.value) {
388 398 await initBluetooth()
389 399 }
390   - addPairedDevices()
391 400 mergeCachedBleDevices()
392   - if (devices.value.length > 0) {
393   - uni.showToast({ title: `Found ${devices.value.length} device(s)`, icon: 'none' })
394   - }
395 401 await new Promise<void>((resolve) => {
396 402 uni.getLocation({
397 403 type: 'wgs84',
... ... @@ -399,13 +405,15 @@ const handleScan = async () =&gt; {
399 405 fail: () => resolve(),
400 406 })
401 407 })
402   - startDiscovery()
  408 + startBleScan()
403 409 uni.showToast({ title: 'Scanning...', icon: 'none' })
404 410 setTimeout(() => {
405 411 if (isScanning.value) stopDiscovery()
406 412 }, 20000)
407 413 } catch (_) {
408   - // error set in initBluetooth
  414 + if (!isScanning.value && devices.value.length === 0) {
  415 + errorMsg.value = 'Bluetooth scan failed. Check if Bluetooth is enabled.'
  416 + }
409 417 }
410 418 }
411 419  
... ... @@ -563,7 +571,17 @@ onMounted(() =&gt; {
563 571  
564 572 onUnmounted(() => {
565 573 if (isScanning.value) stopDiscovery()
566   - uni.offBluetoothDeviceFound()
  574 + try {
  575 + if (typeof uni.offBluetoothDeviceFound === 'function') {
  576 + uni.offBluetoothDeviceFound()
  577 + }
  578 + } catch (_) {}
  579 + try {
  580 + if (typeof uni.offBluetoothAdapterStateChange === 'function') {
  581 + uni.offBluetoothAdapterStateChange()
  582 + }
  583 + } catch (_) {}
  584 + uni.closeBluetoothAdapter({ complete: () => {} })
567 585 })
568 586 </script>
569 587  
... ...
美国版/Food Labeling Management App UniApp/src/pages/labels/preview.vue
... ... @@ -265,8 +265,8 @@ const handlePrint = async () =&gt; {
265 265 const msg = (e && e.message) ? e.message : 'Print failed'
266 266 if (msg === 'BUILTIN_PLUGIN_NOT_FOUND' || (msg && msg.indexOf('Built-in printer') !== -1)) {
267 267 uni.showModal({
268   - title: 'Use Bluetooth Mode',
269   - content: 'For GP-D320FAX, go to Printer settings, switch to Bluetooth mode and tap Scan to connect (e.g. d320fax_295c or Virtual BT Printer). Built-in mode needs custom app packaging.',
  268 + title: 'Built-in Print Not Available',
  269 + content: 'This device does not support TCP built-in printing. Please switch to Bluetooth mode: go to Printer Settings, tap Scan, and connect to your printer (look for a device name like "Virtual BT Printer" or your printer model). You may need to pair it first in Android Bluetooth settings.',
270 270 confirmText: 'Printer Settings',
271 271 cancelText: 'Cancel',
272 272 success: (res) => {
... ...
美国版/Food Labeling Management App UniApp/src/pages/more/printers.vue
... ... @@ -45,6 +45,29 @@
45 45 <button class="btn-connect">{{ t('printers.connect') }}</button>
46 46 </view>
47 47  
  48 + <!-- Paired Devices -->
  49 + <!-- #ifdef APP-PLUS -->
  50 + <view class="section-header">
  51 + <text class="section-title">{{ t('printers.pairedDevices') }}</text>
  52 + </view>
  53 +
  54 + <view v-for="d in pairedDevices" :key="'paired-' + d.deviceId" class="printer-card device-item" @click="connectBt(d)">
  55 + <view class="printer-icon"><AppIcon name="bluetooth" size="md" color="blue" /></view>
  56 + <view class="printer-info">
  57 + <text class="printer-name">{{ d.name || 'Unknown Device' }}</text>
  58 + <text class="printer-loc">{{ d.deviceId }}</text>
  59 + </view>
  60 + <view class="device-meta">
  61 + <text class="device-type-tag" :class="'tag-' + (d.type || 'ble')">{{ getTypeLabel(d.type) }}</text>
  62 + <button class="btn-connect" :disabled="isConnecting">{{ t('printers.connect') }}</button>
  63 + </view>
  64 + </view>
  65 +
  66 + <view v-if="pairedDevices.length === 0" class="empty-state">
  67 + <text class="empty-text">{{ t('printers.noPairedDevices') }}</text>
  68 + </view>
  69 + <!-- #endif -->
  70 +
48 71 <!-- Bluetooth Scanning Area -->
49 72 <view class="section-header">
50 73 <text class="section-title">{{ t('printers.nearby') }}</text>
... ... @@ -62,7 +85,10 @@
62 85 <text class="printer-name">{{ d.name || 'Unknown Device' }}</text>
63 86 <text class="printer-loc">{{ d.deviceId }}</text>
64 87 </view>
65   - <button class="btn-connect" :disabled="isConnecting">{{ t('printers.connect') }}</button>
  88 + <view class="device-meta">
  89 + <text v-if="d.type && d.type !== 'unknown'" class="device-type-tag" :class="'tag-' + d.type">{{ getTypeLabel(d.type) }}</text>
  90 + <button class="btn-connect" :disabled="isConnecting">{{ t('printers.connect') }}</button>
  91 + </view>
66 92 </view>
67 93  
68 94 <view v-if="devices.length === 0 && !isScanning" class="empty-state">
... ... @@ -90,51 +116,101 @@ import {
90 116 } from '../../utils/print/printerConnection'
91 117 import { buildTestTscLabel } from '../../utils/print/tscLabelBuilder'
92 118  
  119 +// #ifdef APP-PLUS
  120 +const classicBluetooth = (require('../../utils/print/bluetoothTool.js') as any).default
  121 +// #endif
  122 +
93 123 const { t } = useI18n()
94 124 const isMenuOpen = ref(false)
95 125  
96   -// 状态管理
97 126 const currentType = ref(getPrinterType())
98 127 const currentBt = ref(getBluetoothConnection())
99 128 const isScanning = ref(false)
100 129 const devices = ref<any[]>([])
  130 +const pairedDevices = ref<any[]>([])
101 131 const isConnecting = ref(false)
  132 +let bleListenerRegistered = false
102 133  
103   -// Refresh current state
104 134 const refreshStatus = () => {
105 135 currentType.value = getPrinterType()
106 136 currentBt.value = getBluetoothConnection()
107 137 }
108 138  
109   -// 蓝牙搜索
  139 +const getTypeLabel = (type?: string) => {
  140 + switch (type) {
  141 + case 'classic': return t('printers.classic')
  142 + case 'ble': return t('printers.ble')
  143 + case 'dual': return t('printers.dual')
  144 + default: return t('printers.ble')
  145 + }
  146 +}
  147 +
  148 +const addDeviceDedup = (device: any) => {
  149 + const existing = devices.value.find(d => d.deviceId === device.deviceId)
  150 + if (!existing) {
  151 + devices.value.push(device)
  152 + }
  153 +}
  154 +
  155 +// #ifdef APP-PLUS
  156 +const loadPairedDevices = () => {
  157 + try {
  158 + const list = classicBluetooth.getPairedDevices()
  159 + pairedDevices.value = list || []
  160 + } catch (e) {
  161 + console.error('Failed to load paired devices', e)
  162 + pairedDevices.value = []
  163 + }
  164 +}
  165 +// #endif
  166 +
110 167 const startScan = () => {
111 168 if (isScanning.value) return
112   -
  169 +
113 170 devices.value = []
114 171 isScanning.value = true
115   -
  172 +
  173 + // #ifdef APP-PLUS
  174 + loadPairedDevices()
  175 + try {
  176 + classicBluetooth.startClassicDiscovery(
  177 + (device: any) => {
  178 + if (device.name) {
  179 + addDeviceDedup(device)
  180 + }
  181 + },
  182 + () => {}
  183 + )
  184 + } catch (e) {
  185 + console.error('Classic discovery failed', e)
  186 + }
  187 + // #endif
  188 +
116 189 uni.openBluetoothAdapter({
117 190 success: () => {
  191 + if (!bleListenerRegistered) {
  192 + bleListenerRegistered = true
  193 + uni.onBluetoothDeviceFound((res) => {
  194 + res.devices.forEach(device => {
  195 + if (device.name) {
  196 + addDeviceDedup({ ...device, type: 'ble' })
  197 + }
  198 + })
  199 + })
  200 + }
118 201 uni.startBluetoothDevicesDiscovery({
119 202 allowDuplicatesKey: false,
120   - success: () => {
121   - uni.onBluetoothDeviceFound((res) => {
122   - res.devices.forEach(device => {
123   - if (device.name && !devices.value.find(d => d.deviceId === device.deviceId)) {
124   - devices.value.push(device)
125   - }
126   - })
127   - })
128   - },
  203 + success: () => {},
129 204 fail: (err) => {
130   - isScanning.value = false
131   - uni.showToast({ title: t('printers.bleNotAvailable'), icon: 'none' })
  205 + console.error('BLE startBluetoothDevicesDiscovery fail:', err)
132 206 }
133 207 })
134 208 },
135 209 fail: (err) => {
136   - isScanning.value = false
137   - uni.showToast({ title: t('printers.bleNotAvailable'), icon: 'none' })
  210 + console.error('openBluetoothAdapter fail:', err)
  211 + if (devices.value.length === 0 && pairedDevices.value.length === 0) {
  212 + uni.showToast({ title: t('printers.bleNotAvailable'), icon: 'none' })
  213 + }
138 214 }
139 215 })
140 216 }
... ... @@ -142,37 +218,73 @@ const startScan = () =&gt; {
142 218 const stopScan = () => {
143 219 isScanning.value = false
144 220 uni.stopBluetoothDevicesDiscovery({
145   - success: () => console.log('Stop scan success'),
146   - fail: (err) => console.error('Stop scan fail', err)
  221 + success: () => console.log('Stop BLE scan success'),
  222 + fail: (err) => console.error('Stop BLE scan fail', err)
147 223 })
  224 + // #ifdef APP-PLUS
  225 + try {
  226 + classicBluetooth.cancelClassicDiscovery()
  227 + } catch (e) {
  228 + console.error('Cancel classic discovery failed', e)
  229 + }
  230 + // #endif
148 231 }
149 232  
150   -// 连接蓝牙设备
151 233 const connectBt = (device: any) => {
152 234 if (isConnecting.value) return
153 235 isConnecting.value = true
154 236 stopScan()
155   -
  237 +
156 238 uni.showLoading({ title: t('printers.connecting') })
157   -
  239 +
  240 + const deviceType = device.type || 'ble'
  241 +
  242 + if (deviceType === 'classic' || deviceType === 'dual') {
  243 + // #ifdef APP-PLUS
  244 + classicBluetooth.connDevice(device.deviceId, (success: boolean) => {
  245 + isConnecting.value = false
  246 + uni.hideLoading()
  247 + if (success) {
  248 + setBluetoothConnection({
  249 + deviceId: device.deviceId,
  250 + deviceName: device.name || 'Bluetooth Printer',
  251 + deviceType: 'classic'
  252 + })
  253 + currentType.value = 'bluetooth'
  254 + currentBt.value = getBluetoothConnection()
  255 + uni.showToast({ title: t('printers.connectSuccess') })
  256 + } else {
  257 + uni.showToast({ title: t('printers.connectFail'), icon: 'none' })
  258 + }
  259 + })
  260 + // #endif
  261 + // #ifndef APP-PLUS
  262 + isConnecting.value = false
  263 + uni.hideLoading()
  264 + uni.showToast({ title: t('printers.connectFail'), icon: 'none' })
  265 + // #endif
  266 + } else {
  267 + connectBle(device)
  268 + }
  269 +}
  270 +
  271 +const connectBle = (device: any) => {
158 272 uni.createBLEConnection({
159 273 deviceId: device.deviceId,
160 274 success: () => {
161 275 uni.getBLEDeviceServices({
162 276 deviceId: device.deviceId,
163 277 success: (res) => {
164   - // 这里简化处理:寻找第一个包含写权限的特征值
165   - // 实际项目中可能需要根据特定 UUID 匹配,官方示例中是遍历寻找
166 278 findWriteCharacteristic(device.deviceId, res.services, device.name)
167 279 },
168   - fail: (err) => {
  280 + fail: () => {
169 281 isConnecting.value = false
170 282 uni.hideLoading()
171 283 uni.showToast({ title: t('printers.connectFail'), icon: 'none' })
172 284 }
173 285 })
174 286 },
175   - fail: (err) => {
  287 + fail: () => {
176 288 isConnecting.value = false
177 289 uni.hideLoading()
178 290 uni.showToast({ title: t('printers.connectFail'), icon: 'none' })
... ... @@ -183,7 +295,7 @@ const connectBt = (device: any) =&gt; {
183 295 const findWriteCharacteristic = (deviceId: string, services: any[], deviceName: string) => {
184 296 let found = false
185 297 let serviceIdx = 0
186   -
  298 +
187 299 const nextService = () => {
188 300 if (serviceIdx >= services.length || found) {
189 301 if (!found) {
... ... @@ -193,7 +305,7 @@ const findWriteCharacteristic = (deviceId: string, services: any[], deviceName:
193 305 }
194 306 return
195 307 }
196   -
  308 +
197 309 const service = services[serviceIdx++]
198 310 uni.getBLEDeviceCharacteristics({
199 311 deviceId,
... ... @@ -221,26 +333,32 @@ const findWriteCharacteristic = (deviceId: string, services: any[], deviceName:
221 333 fail: () => nextService()
222 334 })
223 335 }
224   -
  336 +
225 337 nextService()
226 338 }
227 339  
228   -// 连接内置打印机
229 340 const connectBuiltin = () => {
230 341 setBuiltinPrinter()
231 342 currentType.value = 'builtin'
232 343 uni.showToast({ title: t('printers.connectSuccess') })
233 344 }
234 345  
235   -// 断开连接
236 346 const disconnect = () => {
  347 + // #ifdef APP-PLUS
  348 + if (currentBt.value?.deviceType === 'classic') {
  349 + try {
  350 + classicBluetooth.disConnDevice()
  351 + } catch (e) {
  352 + console.error('Disconnect classic bluetooth failed', e)
  353 + }
  354 + }
  355 + // #endif
237 356 clearPrinter()
238 357 currentType.value = ''
239 358 currentBt.value = null
240 359 uni.showToast({ title: t('printers.disconnected') })
241 360 }
242 361  
243   -// 测试打印
244 362 const doTestPrint = async () => {
245 363 try {
246 364 const data = buildTestTscLabel()
... ... @@ -250,7 +368,17 @@ const doTestPrint = async () =&gt; {
250 368 uni.showToast({ title: t('printers.testPrintSuccess') })
251 369 } catch (e: any) {
252 370 uni.hideLoading()
253   - uni.showToast({ title: t('printers.testPrintFail') + ': ' + e.message, icon: 'none' })
  371 + const msg = (e && e.message) ? e.message : 'Print failed'
  372 + if (msg.indexOf('Built-in printer') !== -1 || msg === 'BUILTIN_PLUGIN_NOT_FOUND') {
  373 + uni.showModal({
  374 + title: 'Print Failed',
  375 + content: 'Built-in TCP printing is not available on this device. Please switch to Bluetooth mode and scan for your printer. Check Android Bluetooth settings to pair with "Virtual BT Printer" or your printer model first.',
  376 + confirmText: 'OK',
  377 + showCancel: false,
  378 + })
  379 + } else {
  380 + uni.showToast({ title: t('printers.testPrintFail') + ': ' + msg, icon: 'none' })
  381 + }
254 382 }
255 383 }
256 384  
... ... @@ -265,10 +393,22 @@ const goBack = () =&gt; {
265 393  
266 394 onMounted(() => {
267 395 refreshStatus()
  396 + // #ifdef APP-PLUS
  397 + loadPairedDevices()
  398 + // #endif
268 399 })
269 400  
270 401 onUnmounted(() => {
271 402 if (isScanning.value) stopScan()
  403 + if (bleListenerRegistered) {
  404 + bleListenerRegistered = false
  405 + try {
  406 + if (typeof uni.offBluetoothDeviceFound === 'function') {
  407 + uni.offBluetoothDeviceFound()
  408 + }
  409 + } catch (_) {}
  410 + }
  411 + uni.closeBluetoothAdapter({ complete: () => {} })
272 412 })
273 413 </script>
274 414  
... ... @@ -316,4 +456,10 @@ onUnmounted(() =&gt; {
316 456  
317 457 .empty-state { padding: 80rpx 0; text-align: center; }
318 458 .empty-text { font-size: 28rpx; color: #9ca3af; }
  459 +
  460 +.device-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 12rpx; flex-shrink: 0; }
  461 +.device-type-tag { display: inline-block; padding: 4rpx 16rpx; font-size: 20rpx; border-radius: 8rpx; font-weight: 500; }
  462 +.tag-ble { background: #eff6ff; color: #3b82f6; }
  463 +.tag-classic { background: #fef3c7; color: #d97706; }
  464 +.tag-dual { background: #ecfdf5; color: #059669; }
319 465 </style>
... ...
美国版/Food Labeling Management App UniApp/src/utils/print/printerConnection.ts
... ... @@ -9,6 +9,9 @@ const STORAGE_BT_SERVICE_ID = &#39;btServiceId&#39;
9 9 const STORAGE_BT_CHARACTERISTIC_ID = 'btCharacteristicId'
10 10 const STORAGE_BT_DEVICE_TYPE = 'btDeviceType' // 'ble' | 'classic'
11 11 const STORAGE_BLE_MTU = 'bleMTU'
  12 +const STORAGE_BUILTIN_PORT = 'builtinPort'
  13 +
  14 +const BUILTIN_PROBE_PORTS = [9100, 4000, 9000, 6000]
12 15  
13 16 export type PrinterType = 'bluetooth' | 'builtin'
14 17 export type BtDeviceType = 'ble' | 'classic'
... ... @@ -56,6 +59,7 @@ export function clearPrinter () {
56 59 uni.removeStorageSync(STORAGE_BT_CHARACTERISTIC_ID)
57 60 uni.removeStorageSync(STORAGE_BT_DEVICE_TYPE)
58 61 uni.removeStorageSync(STORAGE_BLE_MTU)
  62 + uni.removeStorageSync(STORAGE_BUILTIN_PORT)
59 63 }
60 64  
61 65 const BLE_MTU_DEFAULT = 20
... ... @@ -219,24 +223,46 @@ function sendViaBuiltin (data: number[]): Promise&lt;void&gt; {
219 223 const hexStr = Array.from(uint8)
220 224 .map(b => ('0' + (b & 0xff).toString(16)).slice(-2))
221 225 .join('')
222   - return new Promise((resolve, reject) => {
223   - moeTcp.connect({ ip: '127.0.0.1', port: 9100 }, (res: string) => {
224   - try {
225   - const r = typeof res === 'string' ? JSON.parse(res) : res
226   - if (r.code !== 1) {
227   - reject(new Error(r.msg || 'Built-in printer connection failed'))
228   - return
229   - }
230   - moeTcp.sendHexStr({ message: hexStr })
231   - setTimeout(() => {
  226 +
  227 + const savedPort = parseInt(uni.getStorageSync(STORAGE_BUILTIN_PORT)) || 0
  228 + const ports = savedPort > 0
  229 + ? [savedPort, ...BUILTIN_PROBE_PORTS.filter(p => p !== savedPort)]
  230 + : [...BUILTIN_PROBE_PORTS]
  231 +
  232 + function tryPort (idx: number): Promise<void> {
  233 + if (idx >= ports.length) {
  234 + return Promise.reject(new Error(
  235 + 'Built-in printer: all ports failed (tried ' + BUILTIN_PROBE_PORTS.join(', ') +
  236 + '). Check if the printer service is running on this device.'
  237 + ))
  238 + }
  239 + const port = ports[idx]
  240 + return new Promise((resolve, reject) => {
  241 + console.log('[builtin] trying 127.0.0.1:' + port)
  242 + moeTcp.connect({ ip: '127.0.0.1', port }, (res: string) => {
  243 + try {
  244 + const r = typeof res === 'string' ? JSON.parse(res) : res
  245 + if (r.code !== 1) {
  246 + console.log('[builtin] port ' + port + ' failed: ' + (r.msg || ''))
  247 + try { moeTcp.disconnect() } catch (_) {}
  248 + tryPort(idx + 1).then(resolve).catch(reject)
  249 + return
  250 + }
  251 + console.log('[builtin] connected on port ' + port)
  252 + uni.setStorageSync(STORAGE_BUILTIN_PORT, String(port))
  253 + moeTcp.sendHexStr({ message: hexStr })
  254 + setTimeout(() => {
  255 + try { moeTcp.disconnect() } catch (_) {}
  256 + resolve()
  257 + }, 300)
  258 + } catch (e) {
232 259 try { moeTcp.disconnect() } catch (_) {}
233   - resolve()
234   - }, 300)
235   - } catch (e) {
236   - reject(e)
237   - }
  260 + tryPort(idx + 1).then(resolve).catch(reject)
  261 + }
  262 + })
238 263 })
239   - })
  264 + }
  265 + return tryPort(0)
240 266 } catch (e) {
241 267 return Promise.reject(e)
242 268 }
... ...