From cf153b31ab331fe4845cd32d2d0d7d2fd2cb6a58 Mon Sep 17 00:00:00 2001 From: woan <798680981@qq.com> Date: Thu, 25 Jun 2026 11:58:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=B0=83=E8=AF=95=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E8=84=9A=E6=9C=AC(probe-*.ts=20+=20tmp=5Fhub.ts)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- scripts/probe-airpurifier.ts | 48 ------------------------- scripts/probe-cbshot.ts | 18 ---------- scripts/probe-colortemp.ts | 37 ------------------- scripts/probe-ct-nodes.ts | 41 --------------------- scripts/probe-current.ts | 16 --------- scripts/probe-del2.ts | 10 ------ scripts/probe-delpc.ts | 16 --------- scripts/probe-fields.ts | 9 ----- scripts/probe-home-scan.ts | 8 ----- scripts/probe-hub3-connect.ts | 24 ------------- scripts/probe-keypad.ts | 10 ------ scripts/probe-light-popup.ts | 67 ----------------------------------- scripts/probe-lights.ts | 20 ----------- scripts/probe-pair.ts | 20 ----------- scripts/probe-passcode.ts | 14 -------- scripts/probe-pc2.ts | 17 --------- scripts/probe-pc3.ts | 11 ------ scripts/probe-pc4.ts | 10 ------ scripts/probe-pc5.ts | 10 ------ scripts/probe-pc6.ts | 11 ------ scripts/probe-pc7.ts | 8 ----- scripts/probe-s10-finish.ts | 13 ------- scripts/probe-s1p-finish.ts | 17 --------- scripts/probe-s1p-next.ts | 7 ---- scripts/probe-s1p-wifi.ts | 9 ----- scripts/probe-s1p.ts | 27 -------------- scripts/probe-select.ts | 15 -------- scripts/probe-skip.ts | 16 --------- scripts/probe-slider.ts | 55 ---------------------------- scripts/probe-tap.ts | 8 ----- scripts/probe-tap2.ts | 12 ------- tmp_hub.ts | 17 --------- 32 files changed, 621 deletions(-) delete mode 100644 scripts/probe-airpurifier.ts delete mode 100644 scripts/probe-cbshot.ts delete mode 100644 scripts/probe-colortemp.ts delete mode 100644 scripts/probe-ct-nodes.ts delete mode 100644 scripts/probe-current.ts delete mode 100644 scripts/probe-del2.ts delete mode 100644 scripts/probe-delpc.ts delete mode 100644 scripts/probe-fields.ts delete mode 100644 scripts/probe-home-scan.ts delete mode 100644 scripts/probe-hub3-connect.ts delete mode 100644 scripts/probe-keypad.ts delete mode 100644 scripts/probe-light-popup.ts delete mode 100644 scripts/probe-lights.ts delete mode 100644 scripts/probe-pair.ts delete mode 100644 scripts/probe-passcode.ts delete mode 100644 scripts/probe-pc2.ts delete mode 100644 scripts/probe-pc3.ts delete mode 100644 scripts/probe-pc4.ts delete mode 100644 scripts/probe-pc5.ts delete mode 100644 scripts/probe-pc6.ts delete mode 100644 scripts/probe-pc7.ts delete mode 100644 scripts/probe-s10-finish.ts delete mode 100644 scripts/probe-s1p-finish.ts delete mode 100644 scripts/probe-s1p-next.ts delete mode 100644 scripts/probe-s1p-wifi.ts delete mode 100644 scripts/probe-s1p.ts delete mode 100644 scripts/probe-select.ts delete mode 100644 scripts/probe-skip.ts delete mode 100644 scripts/probe-slider.ts delete mode 100644 scripts/probe-tap.ts delete mode 100644 scripts/probe-tap2.ts delete mode 100644 tmp_hub.ts diff --git a/scripts/probe-airpurifier.ts b/scripts/probe-airpurifier.ts deleted file mode 100644 index 2792510..0000000 --- a/scripts/probe-airpurifier.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import * as fs from 'fs'; - -(async () => { - const driver = createDriver(); - await driver.createSession(); - const KW = process.env.AIR_PURIFIER_CARD || 'Air Purifier'; - try { - await driver.dismissPopupIfPresent(); - await driver.goBackToHomepage(); - await new Promise((r) => setTimeout(r, 1000)); - // 找卡片并点中心 - let el: string | null = null; - for (let i = 0; i < 8; i++) { - el = await driver.findElementRaw('-android uiautomator', `new UiSelector().textContains("${KW}")`).catch(() => null); - if (el) break; - await driver.swipe(540, 1400, 540, 600, 0.4).catch(() => {}); - await new Promise((r) => setTimeout(r, 900)); - } - if (!el) throw new Error('找不到卡片'); - const rect = await driver.getElementRect(el); - console.log(`卡片文本 rect=(${rect.x},${rect.y}) ${rect.width}x${rect.height}`); - await driver.tap(rect.x + rect.width / 2, rect.y + rect.height / 2); - await new Promise((r) => setTimeout(r, 2500)); - - const size = await driver.getWindowSize(); - console.log(`屏幕 ${size.width}x${size.height}`); - const src = await driver.getSource(); - const texts = Array.from(src.matchAll(/text="([^"]+)"/g)).map((m) => m[1]).filter((t) => t.trim()); - console.log('=== 浮层文本节点 ==='); - console.log(JSON.stringify([...new Set(texts)], null, 0)); - - // 把带 bounds 的可点节点也 dump 出来(找无文案电源键的可能容器) - const nodes = Array.from(src.matchAll(/<[^>]*?(?:text="([^"]*)")?[^>]*?(?:content-desc="([^"]*)")?[^>]*?clickable="true"[^>]*?bounds="(\[\d+,\d+\]\[\d+,\d+\])"[^>]*?>/g)); - console.log('=== clickable 节点(text|desc|bounds) ==='); - for (const n of nodes.slice(0, 40)) console.log(` "${n[1] || ''}" | "${n[2] || ''}" | ${n[3]}`); - - const ss = await driver.screenshot(); - fs.writeFileSync('/tmp/airpurifier_popup.png', Buffer.from(ss, 'base64')); - console.log('截图: /tmp/airpurifier_popup.png'); - } catch (e: any) { - console.error('探针失败:', e.message); - const ss = await driver.screenshot().catch(() => ''); - if (ss) fs.writeFileSync('/tmp/airpurifier_popup.png', Buffer.from(ss, 'base64')); - } finally { - await driver.destroySession(); - } -})(); diff --git a/scripts/probe-cbshot.ts b/scripts/probe-cbshot.ts deleted file mode 100644 index 5585262..0000000 --- a/scripts/probe-cbshot.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import * as fs from 'fs'; -(async () => { - const d = createDriver(); await d.createSession(); - const KW='Color Bulb 7E', W=1080,H=2400; const sleep=(m:number)=>new Promise(r=>setTimeout(r,m)); - try { - await d.dismissPopupIfPresent(); await d.goBackToHomepage(); await sleep(800); - let el=null; for(let i=0;i<10;i++){el=await d.findElementRaw('-android uiautomator',`new UiSelector().textContains("${KW}")`).catch(()=>null); if(el)break; await d.swipe(540,1500,540,700,0.4).catch(()=>{}); await sleep(800);} - const r=await d.getElementRect(el!); await d.tap(r.x+r.width/2,r.y+r.height/2); await sleep(2500); - const src=await d.getSource(); - const pw=Array.from(src.matchAll(/clickable="true"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/g)).map(m=>{const x1=+m[1],y1=+m[2],x2=+m[3],y2=+m[4];return{w:x2-x1,h:y2-y1,cx:(x1+x2)/2,cy:(y1+y2)/2};}).filter(b=>b.w>=150&&b.w<=320&&b.h>=150&&b.h<=320&&Math.abs(b.cx-W/2)H*0.4); - const st=()=>d.getSource().then(s=>{const t=Array.from(s.matchAll(/text="([^"]+)"/g)).map(m=>m[1]);const i=t.findIndex(x=>x.includes(KW));return i>=0?t[i+1]||'':'';}); - if(!/\d+\s*%/.test(await st()) && pw.length){await d.tap(Math.round(pw[0].cx),Math.round(pw[0].cy)); await sleep(3500);} - const texts=[...new Set(Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)).map(m=>m[1]).filter(t=>t.trim()))]; - console.log('TEXTS='+JSON.stringify(texts)); - const ss=await d.screenshot(); fs.writeFileSync('/tmp/cb_popup.png',Buffer.from(ss,'base64')); console.log('OK'); - } catch(e:any){console.error(e.message);} finally{await d.destroySession();} -})(); diff --git a/scripts/probe-colortemp.ts b/scripts/probe-colortemp.ts deleted file mode 100644 index f20fb7d..0000000 --- a/scripts/probe-colortemp.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createDriver } from '../drivers/factory'; - -(async () => { - const d = createDriver(); - await d.createSession(); - const KW = process.env.LIGHT_CARD || 'Color Bulb 7E'; - const W = 1080, H = 2400; - const sleep = (m: number) => new Promise((r) => setTimeout(r, m)); - const fullSub = async (): Promise => { - const s = await d.getSource(); - const t = Array.from(s.matchAll(/text="([^"]+)"/g)).map((m) => m[1]); - const i = t.findIndex((x) => x.includes(KW)); - return i >= 0 ? `${t[i + 1] || ''} | ${t[i + 2] || ''} | ${t[i + 3] || ''}` : ''; - }; - try { - await d.dismissPopupIfPresent(); await d.goBackToHomepage(); await sleep(800); - let el: string | null = null; - for (let i = 0; i < 10; i++) { el = await d.findElementRaw('-android uiautomator', `new UiSelector().textContains("${KW}")`).catch(() => null); if (el) break; await d.swipe(540, 1500, 540, 700, 0.4).catch(() => {}); await sleep(800); } - const r = await d.getElementRect(el!); await d.tap(r.x + r.width / 2, r.y + r.height / 2); await sleep(2500); - // 开灯 - const src = await d.getSource(); - const pw = Array.from(src.matchAll(/clickable="true"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/g)) - .map((m) => { const x1 = +m[1], y1 = +m[2], x2 = +m[3], y2 = +m[4]; return { w: x2 - x1, h: y2 - y1, cx: (x1 + x2) / 2, cy: (y1 + y2) / 2 }; }) - .filter((b) => b.w >= 150 && b.w <= 320 && b.h >= 150 && b.h <= 320 && Math.abs(b.cx - W / 2) < W * 0.15 && b.cy > H * 0.4); - if (!/\d+\s*%/.test(await fullSub()) && pw.length) { await d.tap(Math.round(pw[0].cx), Math.round(pw[0].cy)); await sleep(3500); } - console.log('开灯后副标题(含后2字段)=' + JSON.stringify(await fullSub())); - - // 色温条 y1737:拖最左 / 中 / 最右,各看副标题 - const left = 58, right = 1022, y = 1737; - for (const [lbl, f] of [['左', 0.05], ['中', 0.5], ['右', 0.95]] as Array<[string, number]>) { - // 从中点起拖(色温滑块当前位置未知,先试中点抓) - await d.swipe(540, y, Math.round(left + f * (right - left)), y, 0.8); await sleep(2000); - console.log(`色温拖${lbl}(f=${f}) → 副标题=${JSON.stringify(await fullSub())}`); - } - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-ct-nodes.ts b/scripts/probe-ct-nodes.ts deleted file mode 100644 index 4de38e3..0000000 --- a/scripts/probe-ct-nodes.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { createDriver } from '../drivers/factory'; - -(async () => { - const d = createDriver(); - await d.createSession(); - const KW = process.env.LIGHT_CARD || 'Color Bulb 7E'; - const W = 1080, H = 2400; - const sleep = (m: number) => new Promise((r) => setTimeout(r, m)); - const sub = async (): Promise => { - const s = await d.getSource(); - const t = Array.from(s.matchAll(/text="([^"]+)"/g)).map((m) => m[1]); - const i = t.findIndex((x) => x.includes(KW)); - return i >= 0 ? t[i + 1] || '' : ''; - }; - // dump y1650-1825 区间所有节点(class + bounds),找会随拖动移动的子节点 - const dumpTrack = async (y1lo: number, y1hi: number): Promise => { - const s = await d.getSource(); - return Array.from(s.matchAll(/<[^>]*class="([^"]+)"[^>]*bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"[^>]*>/g)) - .map((m) => ({ cls: m[1].split('.').pop(), x1: +m[2], y1: +m[3], x2: +m[4], y2: +m[5] })) - .filter((b) => b.y1 >= y1lo && b.y2 <= y1hi) - .map((b) => `${b.cls} [${b.x1},${b.y1}][${b.x2},${b.y2}] w${b.x2 - b.x1}`); - }; - try { - await d.dismissPopupIfPresent(); await d.goBackToHomepage(); await sleep(800); - let el: string | null = null; - for (let i = 0; i < 10; i++) { el = await d.findElementRaw('-android uiautomator', `new UiSelector().textContains("${KW}")`).catch(() => null); if (el) break; await d.swipe(540, 1500, 540, 700, 0.4).catch(() => {}); await sleep(800); } - const r = await d.getElementRect(el!); await d.tap(r.x + r.width / 2, r.y + r.height / 2); await sleep(2500); - const src = await d.getSource(); - const pw = Array.from(src.matchAll(/clickable="true"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/g)) - .map((m) => { const x1 = +m[1], y1 = +m[2], x2 = +m[3], y2 = +m[4]; return { w: x2 - x1, h: y2 - y1, cx: (x1 + x2) / 2, cy: (y1 + y2) / 2 }; }) - .filter((b) => b.w >= 150 && b.w <= 320 && b.h >= 150 && b.h <= 320 && Math.abs(b.cx - W / 2) < W * 0.15 && b.cy > H * 0.4); - if (!/\d+\s*%/.test(await sub()) && pw.length) { await d.tap(Math.round(pw[0].cx), Math.round(pw[0].cy)); await sleep(3500); } - - const left = 58, right = 1022, y = 1737; - await d.swipe(540, y, left, y, 0.8); await sleep(1800); - console.log('色温拖最左, track节点=' + JSON.stringify(await dumpTrack(1620, 1860))); - await d.swipe(left, y, right, y, 0.8); await sleep(1800); - console.log('色温拖最右, track节点=' + JSON.stringify(await dumpTrack(1620, 1860))); - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-current.ts b/scripts/probe-current.ts deleted file mode 100644 index 123e4f3..0000000 --- a/scripts/probe-current.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createDriver } from '../drivers/factory'; - -(async () => { - const d = createDriver(); - await d.createSession(); - try { - const src = await d.getSource(); - const texts = [...new Set(Array.from(src.matchAll(/text="([^"]+)"/g)).map((m) => m[1]).filter((t) => t.trim()))]; - console.log('当前页文案=' + JSON.stringify(texts)); - // clickable 节点的 text/desc - const clk = Array.from(src.matchAll(/<[^>]*?(?:text="([^"]*)")?[^>]*?(?:content-desc="([^"]*)")?[^>]*?clickable="true"[^>]*?>/g)) - .map((m) => `${m[1] || ''}|${m[2] || ''}`).filter((s) => s !== '|'); - console.log('可点按钮=' + JSON.stringify([...new Set(clk)].slice(0, 25))); - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-del2.ts b/scripts/probe-del2.ts deleted file mode 100644 index 9fb3a60..0000000 --- a/scripts/probe-del2.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - const del=await d.findElementRaw('-android uiautomator','new UiSelector().text("Delete")').catch(()=>null); - if(del){await d.tapElement(del);await sleep(2000);console.log('点Delete后: '+JSON.stringify(await dump(d))); - // 确认框 - for(const t of ['Delete','Confirm','OK','确定','Yes']){const b=await d.findElementRaw('-android uiautomator',`new UiSelector().text("${t}")`).catch(()=>null);if(b){await d.tapElement(b);await sleep(2500);console.log(`确认(${t})后: `+JSON.stringify(await dump(d)));break;}} - } else console.log('无Delete, 当前: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-delpc.ts b/scripts/probe-delpc.ts deleted file mode 100644 index 22df97b..0000000 --- a/scripts/probe-delpc.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - await d.dismissPopupIfPresent();await d.goBackToHomepage();await sleep(1000); - let el=null;for(let i=0;i<8;i++){el=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Keypad Vision")').catch(()=>null);if(el)break;await d.swipe(540,1500,540,700,0.4).catch(()=>{});await sleep(700);} - const r=await d.getElementRect(el!);await d.tap(r.x+100,r.y-20);await sleep(5000);await d.dismissPopupIfPresent();await sleep(1500); - // Passcode tab - const pc=await d.findElementRaw('-android uiautomator','new UiSelector().text("Passcode")').catch(()=>null); - if(pc){const pr=await d.getElementRect(pc);await d.tap(Math.round(pr.x+pr.width/2),Math.round(pr.y+pr.height/2));await sleep(2000);} - console.log('Passcode tab: '+JSON.stringify(await dump(d))); - // 点密码项 "Permanent Passcode 1" - const item=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Permanent Passcode")').catch(()=>null); - if(item){await d.tapElement(item);await sleep(2500);console.log('点密码项后: '+JSON.stringify(await dump(d)));} - else console.log('无密码项'); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-fields.ts b/scripts/probe-fields.ts deleted file mode 100644 index 7a8ef36..0000000 --- a/scripts/probe-fields.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))].slice(0,25) as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - console.log('当前页文案: '+JSON.stringify(await dump(d))); - const src=await d.getSource(); - // EditText 节点 + bounds + 旁边的提示文字 - const eds=Array.from(src.matchAll(/<[^>]*class="android\.widget\.EditText"[^>]*bounds="(\[\d+,\d+\]\[\d+,\d+\])"[^>]*>/g)).map((m:any)=>m[1]); - console.log('EditText 数='+eds.length+' bounds='+JSON.stringify(eds)); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-home-scan.ts b/scripts/probe-home-scan.ts deleted file mode 100644 index b10ebe3..0000000 --- a/scripts/probe-home-scan.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -(async()=>{const d=createDriver();await d.createSession();try{ - await d.dismissPopupIfPresent();await d.goBackToHomepage();await sleep(1000); - const names=new Set(); - for(let i=0;i<8;i++){const s=await d.getSource();for(const m of s.matchAll(/text="([^"]+)"/g)){const t=m[1];if(/S10|Robot|Floor|Vacuum|扫地/i.test(t))names.add(t);} await d.swipe(540,1500,540,700,0.4).catch(()=>{});await sleep(700);} - console.log('ROBOT_CARDS='+JSON.stringify([...names])); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-hub3-connect.ts b/scripts/probe-hub3-connect.ts deleted file mode 100644 index 7e14ed4..0000000 --- a/scripts/probe-hub3-connect.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import { enterPairingMode } from '../utils/common/relay.helper'; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); -const dump = async (d: any): Promise => [...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map((m) => m[1]).filter((t: string) => t.trim()))] as string[]; -(async () => { - const d = createDriver(); - await d.createSession(); - try { - await enterPairingMode('hub3').catch((e) => console.log('relay 失败:', e.message)); - console.log('已按 ch9+10 3s'); - await sleep(2000); - for (const t of ['Connect device', 'Connect Device', 'Connect Devices']) { - const b = await d.findElementRaw('-android uiautomator', `new UiSelector().text("${t}")`).catch(() => null); - if (b) { await d.tapElement(b); console.log(`已点 ${t}`); break; } - } - for (let i = 0; i < 12; i++) { - await sleep(5000); - const texts = await dump(d); - console.log(`+${(i + 1) * 5}s: ${JSON.stringify(texts)}`); - if (/Configure Wi-?Fi|SSID|Select Device|Pick a room|added successfully/i.test(texts.join(' '))) { console.log('==关键页=='); break; } - } - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-keypad.ts b/scripts/probe-keypad.ts deleted file mode 100644 index 131c088..0000000 --- a/scripts/probe-keypad.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - await d.dismissPopupIfPresent();await d.goBackToHomepage();await sleep(1000); - let el=null;for(let i=0;i<8;i++){el=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Keypad Vision")').catch(()=>null);if(el)break;await d.swipe(540,1500,540,700,0.4).catch(()=>{});await sleep(700);} - if(!el){console.log('找不到Keypad卡片');return;} - const r=await d.getElementRect(el);await d.tap(r.x+100,r.y-20);await sleep(5000);await d.dismissPopupIfPresent();await sleep(1500); - console.log('功能页: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-light-popup.ts b/scripts/probe-light-popup.ts deleted file mode 100644 index b62266a..0000000 --- a/scripts/probe-light-popup.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import * as fs from 'fs'; - -(async () => { - const d = createDriver(); - await d.createSession(); - const KW = process.env.LIGHT_CARD || 'Permanent Outdoor Lights'; - try { - await d.dismissPopupIfPresent(); await d.goBackToHomepage(); - await new Promise((r) => setTimeout(r, 1000)); - let el: string | null = null; - for (let i = 0; i < 10; i++) { - el = await d.findElementRaw('-android uiautomator', `new UiSelector().textContains("${KW}")`).catch(() => null); - if (el) break; - await d.swipe(540, 1500, 540, 700, 0.4).catch(() => {}); - await new Promise((r) => setTimeout(r, 800)); - } - if (!el) throw new Error('找不到灯卡片'); - const rect = await d.getElementRect(el); - console.log(`卡片文本 rect=(${rect.x},${rect.y}) ${rect.width}x${rect.height}`); - await d.tap(rect.x + rect.width / 2, rect.y + rect.height / 2); - await new Promise((r) => setTimeout(r, 2500)); - - const size = await d.getWindowSize(); - console.log(`屏幕 ${size.width}x${size.height}`); - const src = await d.getSource(); - const texts = [...new Set(Array.from(src.matchAll(/text="([^"]+)"/g)).map((m) => m[1]).filter((t) => t.trim()))]; - console.log('TEXTS=' + JSON.stringify(texts)); - - // clickable 节点 - const clk = Array.from(src.matchAll(/clickable="true"[^>]*?bounds="(\[\d+,\d+\]\[\d+,\d+\])"/g)).map((m) => m[1]); - console.log('CLICKABLE=' + JSON.stringify(clk.slice(0, 30))); - // 滑条类节点(SeekBar/ProgressBar/Slider) — 找 class 含 SeekBar/Slider 或 scrollable - const sliders = Array.from(src.matchAll(/<[^>]*class="([^"]*(?:SeekBar|Slider|ProgressBar)[^"]*)"[^>]*bounds="(\[\d+,\d+\]\[\d+,\d+\])"[^>]*>/g)).map((m) => `${m[1]} ${m[2]}`); - console.log('SLIDERS=' + JSON.stringify(sliders)); - - // 浮层下半区(y>1300)所有"宽"节点(width>400):RN 自绘滑条候选 - const wide: string[] = []; - for (const m of src.matchAll(/<[^>]*class="([^"]+)"[^>]*bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"[^>]*>/g)) { - const [cls, x1, y1, x2, y2] = [m[1], +m[2], +m[3], +m[4], +m[5]]; - const w = x2 - x1, h = y2 - y1; - if (y1 > 1300 && w > 400 && h < 300) wide.push(`${cls.split('.').pop()} [${x1},${y1}][${x2},${y2}] w${w}h${h}`); - } - console.log('WIDE_NODES=' + JSON.stringify(wide.slice(0, 20))); - - // 开灯后再看滑条填充条:点电源 → dump 滑条 y 区间(1620-1850)内所有节点(找蓝色填充 View 的右边缘=亮度) - await d.tap(540, 1455); // 电源键 - await new Promise((r) => setTimeout(r, 3500)); - const src2 = await d.getSource(); - const inTrack: string[] = []; - for (const m of src2.matchAll(/<[^>]*class="([^"]+)"[^>]*bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"[^>]*>/g)) { - const [cls, x1, y1, x2, y2] = [m[1], +m[2], +m[3], +m[4], +m[5]]; - if (y1 >= 1600 && y2 <= 1860 && x2 - x1 > 30) inTrack.push(`${cls.split('.').pop()} [${x1},${y1}][${x2},${y2}] w${x2 - x1}`); - } - const st = [...new Set(Array.from(src2.matchAll(/text="([^"]+)"/g)).map((m) => m[1]))].slice(0, 8); - console.log('AFTER_ON_TEXTS=' + JSON.stringify(st)); - console.log('TRACK_NODES=' + JSON.stringify(inTrack.slice(0, 15))); - - const ss = await d.screenshot(); - fs.writeFileSync('/tmp/light_popup.png', Buffer.from(ss, 'base64')); - console.log('截图: /tmp/light_popup.png'); - } catch (e: any) { - console.error('探针失败:', e.message); - } finally { - await d.destroySession(); - } -})(); diff --git a/scripts/probe-lights.ts b/scripts/probe-lights.ts deleted file mode 100644 index 03fb28e..0000000 --- a/scripts/probe-lights.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createDriver } from '../drivers/factory'; -(async () => { - const d = createDriver(); - await d.createSession(); - try { - await d.dismissPopupIfPresent(); await d.goBackToHomepage(); - await new Promise(r=>setTimeout(r,1000)); - const names = new Set(); - for (let i=0;i<10;i++){ - const src = await d.getSource(); - for (const m of src.matchAll(/text="([^"]+)"/g)) { - const t=m[1]; - if (/light|lamp|bulb|neon|strip|ceiling|floor|outdoor/i.test(t)) names.add(t); - } - await d.swipe(540,1500,540,700,0.4).catch(()=>{}); - await new Promise(r=>setTimeout(r,700)); - } - console.log('LIGHTS_ON_HOME='+JSON.stringify([...names])); - } finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-pair.ts b/scripts/probe-pair.ts deleted file mode 100644 index a608de2..0000000 --- a/scripts/probe-pair.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - // 进 keypad 功能页 - await d.dismissPopupIfPresent();await d.goBackToHomepage();await sleep(1000); - let el=null;for(let i=0;i<8;i++){el=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Keypad Vision")').catch(()=>null);if(el)break;await d.swipe(540,1500,540,700,0.4).catch(()=>{});await sleep(700);} - const r=await d.getElementRect(el!);await d.tap(r.x+100,r.y-20);await sleep(5000);await d.dismissPopupIfPresent();await sleep(1500); - const cb=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Do not show again")').catch(()=>null); - if(cb){await d.tapElement(cb).catch(()=>{});for(const t of['OK','Got it','Confirm']){const b=await d.findElementRaw('-android uiautomator',`new UiSelector().text("${t}")`).catch(()=>null);if(b){await d.tapElement(b);await sleep(1500);break;}}} - const pair=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Pair to Lock")').catch(()=>null); - if(pair){await d.tapElement(pair);await sleep(3000);} - console.log('选锁页: '+JSON.stringify(await dump(d))); - // 点 Lock 6D 行 - const lk=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Lock 6D")').catch(()=>null); - if(lk){await d.tapElement(lk);await sleep(2500);console.log('点Lock 6D后: '+JSON.stringify(await dump(d)));} - // 再点 Pair - const pb=await d.findElementRaw('-android uiautomator','new UiSelector().text("Pair")').catch(()=>null); - if(pb){await d.tapElement(pb);await sleep(6000);console.log('点Pair后: '+JSON.stringify(await dump(d)));} -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-passcode.ts b/scripts/probe-passcode.ts deleted file mode 100644 index c7ea491..0000000 --- a/scripts/probe-passcode.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - await d.dismissPopupIfPresent();await d.goBackToHomepage();await sleep(1000); - let el=null;for(let i=0;i<8;i++){el=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Keypad Vision")').catch(()=>null);if(el)break;await d.swipe(540,1500,540,700,0.4).catch(()=>{});await sleep(700);} - const r=await d.getElementRect(el!);await d.tap(r.x+100,r.y-20);await sleep(5000);await d.dismissPopupIfPresent();await sleep(1500); - // 精确点 Passcode(避开 Passcode user guide) - let p=await d.findElementRaw('-android uiautomator','new UiSelector().text("Passcode")').catch(()=>null); - if(p){await d.tapElement(p);await sleep(2500);console.log('点Passcode后: '+JSON.stringify(await dump(d)));} - else console.log('精确Passcode未找到, 当前: '+JSON.stringify(await dump(d))); - // 点 Add - for(const t of ['Add','Create','+','Add Passcode']){const b=await d.findElementRaw('-android uiautomator',`new UiSelector().text("${t}")`).catch(()=>null);if(b){await d.tapElement(b);await sleep(2500);console.log(`点${t}后: `+JSON.stringify(await dump(d)));break;}} -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-pc2.ts b/scripts/probe-pc2.ts deleted file mode 100644 index 089af3c..0000000 --- a/scripts/probe-pc2.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - await d.dismissPopupIfPresent();await d.goBackToHomepage();await sleep(1000); - let el=null;for(let i=0;i<8;i++){el=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Keypad Vision")').catch(()=>null);if(el)break;await d.swipe(540,1500,540,700,0.4).catch(()=>{});await sleep(700);} - const r=await d.getElementRect(el!);await d.tap(r.x+100,r.y-20);await sleep(5000);await d.dismissPopupIfPresent();await sleep(1500); - // Passcode 文字 rect - const pc=await d.findElementRaw('-android uiautomator','new UiSelector().text("Passcode")').catch(()=>null); - if(pc){const pr=await d.getElementRect(pc);console.log(`Passcode rect=(${pr.x},${pr.y}) ${pr.width}x${pr.height}`); - // 点整行中部(往右挪,避开图标) - await d.tap(540, pr.y+pr.height/2);await sleep(2500);console.log('点行中部后: '+JSON.stringify(await dump(d)));} - // dump clickable 节点 bounds - const src=await d.getSource(); - const clk=Array.from(src.matchAll(/clickable="true"[^>]*?bounds="(\[\d+,\d+\]\[\d+,\d+\])"/g)).map(m=>m[1]); - console.log('clickable: '+JSON.stringify(clk.slice(0,15))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-pc3.ts b/scripts/probe-pc3.ts deleted file mode 100644 index 4f1630b..0000000 --- a/scripts/probe-pc3.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))] as string[]; -const clkOf=async(d:any):Promise=>Array.from((await d.getSource()).matchAll(/clickable="true"[^>]*?bounds="(\[\d+,\d+\]\[\d+,\d+\])"/g)).map((m:any)=>m[1]); -(async()=>{const d=createDriver();await d.createSession();try{ - console.log('当前页: '+JSON.stringify(await dump(d))); - // 点 Passcode 图标(左列 ~195,909) - await d.tap(195,909);await sleep(2500); - console.log('点Passcode图标后: '+JSON.stringify(await dump(d))); - console.log('该页clickable: '+JSON.stringify((await clkOf(d)).slice(0,15))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-pc4.ts b/scripts/probe-pc4.ts deleted file mode 100644 index d46458a..0000000 --- a/scripts/probe-pc4.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - // 确保在 Passcode tab(点左列图标) - await d.tap(195,909);await sleep(1500); - // 点底部无文案 Add (540,2211) - await d.tap(540,2211);await sleep(2500); - console.log('点底部Add后: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-pc5.ts b/scripts/probe-pc5.ts deleted file mode 100644 index 0f4739e..0000000 --- a/scripts/probe-pc5.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - const p=await d.findElementRaw('-android uiautomator','new UiSelector().text("Permanent")').catch(()=>null); - if(p){await d.tapElement(p);await sleep(2500);console.log('点Permanent后: '+JSON.stringify(await dump(d))); - const eds=await d.findElementsRaw('-android uiautomator','new UiSelector().className("android.widget.EditText")'); - console.log('EditText数='+eds.length); - } else console.log('无Permanent, 当前: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-pc6.ts b/scripts/probe-pc6.ts deleted file mode 100644 index 0b1a999..0000000 --- a/scripts/probe-pc6.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - const eds=await d.findElementsRaw('-android uiautomator','new UiSelector().className("android.widget.EditText")'); - if(eds.length){await d.typeText(eds[0],'123456');await sleep(1000);console.log('输码后: '+JSON.stringify(await dump(d)));} - try{await d.goBack();}catch{} - const n=await d.findElementRaw('-android uiautomator','new UiSelector().text("Next")').catch(()=>null); - if(n){await d.tapElement(n);await sleep(2500);console.log('点Next后: '+JSON.stringify(await dump(d))); - const e2=await d.findElementsRaw('-android uiautomator','new UiSelector().className("android.widget.EditText")');console.log('Next页EditText数='+e2.length);} -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-pc7.ts b/scripts/probe-pc7.ts deleted file mode 100644 index d4caa43..0000000 --- a/scripts/probe-pc7.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - const s=await d.findElementRaw('-android uiautomator','new UiSelector().text("Save")').catch(()=>null); - if(s){await d.tapElement(s);await sleep(4000);await d.dismissPopupIfPresent();await sleep(1500);console.log('点Save后: '+JSON.stringify(await dump(d)));} - else console.log('无Save, 当前: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-s10-finish.ts b/scripts/probe-s10-finish.ts deleted file mode 100644 index c54de9d..0000000 --- a/scripts/probe-s10-finish.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import { configureHubWifi } from '../utils/common/hub.helper'; -import { getWifiCredentials } from '../config/wifi.config'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))].slice(0,20) as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - console.log('起始: '+JSON.stringify(await dump(d))); - await configureHubWifi(d, getWifiCredentials()); - await sleep(3000); - await d.goBackToHomepage().catch(()=>{}); await sleep(2000); - const home=await dump(d); - console.log('首页含S10/Robot: '+JSON.stringify(home.filter(t=>/S10|Robot|Floor Cleaning|扫地/i.test(t)))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-s1p-finish.ts b/scripts/probe-s1p-finish.ts deleted file mode 100644 index 75b073b..0000000 --- a/scripts/probe-s1p-finish.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import { configureHubWifi } from '../utils/common/hub.helper'; -import { getWifiCredentials } from '../config/wifi.config'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))].slice(0,20) as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - console.log('起始页: '+JSON.stringify(await dump(d))); - const cn=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Configure network")').catch(()=>null); - if(cn){await d.tapElement(cn);console.log('点了 Configure network');await sleep(3000);} - await configureHubWifi(d, getWifiCredentials()); - await sleep(3000); - console.log('配网后: '+JSON.stringify(await dump(d))); - // 回首页看真实卡名 - await d.goBackToHomepage().catch(()=>{}); await sleep(2000); - const home=await dump(d); - console.log('首页含S1/Plus: '+JSON.stringify(home.filter(t=>/S1|Plus|Robot|Vacuum/i.test(t)))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-s1p-next.ts b/scripts/probe-s1p-next.ts deleted file mode 100644 index b5c4646..0000000 --- a/scripts/probe-s1p-next.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))].slice(0,18) as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - for(const t of ['Configure network','Configure Network','Next','Configure']){const b=await d.findElementRaw('-android uiautomator',`new UiSelector().text("${t}")`).catch(()=>null);if(b){await d.tapElement(b);console.log('点了 '+t);break;}} - await sleep(3500);console.log('下一页: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-s1p-wifi.ts b/scripts/probe-s1p-wifi.ts deleted file mode 100644 index 1af7a2e..0000000 --- a/scripts/probe-s1p-wifi.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))].slice(0,20) as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - const n=await d.findElementRaw('-android uiautomator','new UiSelector().text("Next")').catch(()=>null); - if(n){await d.tapElement(n);console.log('点了 Next');} - await sleep(3000); - console.log('点Next后: '+JSON.stringify(await dump(d))); -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-s1p.ts b/scripts/probe-s1p.ts deleted file mode 100644 index ddf5929..0000000 --- a/scripts/probe-s1p.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { createDriver } from '../drivers/factory'; -import { enterPairingMode } from '../utils/common/relay.helper'; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); -const dump = async (d: any): Promise => [...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map((m) => m[1]).filter((t: string) => t.trim() && t.length < 30))].slice(0, 18) as string[]; -(async () => { - const d = createDriver(); - await d.createSession(); - try { - console.log('当前页: ' + JSON.stringify(await dump(d))); - await enterPairingMode('robot_s1p').catch((e) => console.log('relay 失败:', e.message)); // ch11+12 5s - console.log('已按 ch11+12 5s'); - await sleep(2000); - // 点 Next 进搜索 - for (const t of ['Next', 'Connect device', 'Connect Device']) { - const b = await d.findElementRaw('-android uiautomator', `new UiSelector().text("${t}")`).catch(() => null); - if (b) { await d.tapElement(b); console.log('点了 ' + t); break; } - } - // 轮询搜索结果 - for (let i = 0; i < 14; i++) { - await sleep(5000); - const t = await dump(d); - console.log(`+${(i + 1) * 5}s: ${JSON.stringify(t)}`); - if (/Configure Wi-?Fi|SSID|Select Device|Pick a room|added successfully|S1 Plus/i.test(t.join(' ')) && !/Search for a device/i.test(t.join(' '))) { console.log('==发现/进配网=='); break; } - } - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-select.ts b/scripts/probe-select.ts deleted file mode 100644 index dc7311a..0000000 --- a/scripts/probe-select.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); -(async () => { - const d = createDriver(); - await d.createSession(); - try { - const dev = await d.findElementRaw('-android uiautomator', 'new UiSelector().textMatches("(?i)Relay Switch 1.*")').catch(() => null); - if (dev) { await d.tapElement(dev); console.log('已选设备'); await sleep(1500); } else console.log('未找到设备项'); - const n = await d.findElementRaw('-android uiautomator', 'new UiSelector().text("Next")').catch(() => null); - if (n) { await d.tapElement(n); console.log('已点 Next'); await sleep(3000); } else console.log('未找到 Next'); - const texts = [...new Set(Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)).map((m) => m[1]).filter((t) => t.trim()))]; - console.log('下一页文案=' + JSON.stringify(texts)); - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-skip.ts b/scripts/probe-skip.ts deleted file mode 100644 index 5112489..0000000 --- a/scripts/probe-skip.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); -(async () => { - const d = createDriver(); - await d.createSession(); - try { - // 点 "Skip this guide" 跳过接线引导 - const skip = await d.findElementRaw('-android uiautomator', 'new UiSelector().textContains("Skip this guide")').catch(() => null); - if (skip) { await d.tapElement(skip); console.log('已点 Skip this guide'); await sleep(2500); } - else console.log('未找到 Skip this guide'); - const src = await d.getSource(); - const texts = [...new Set(Array.from(src.matchAll(/text="([^"]+)"/g)).map((m) => m[1]).filter((t) => t.trim()))]; - console.log('跳过后页面文案=' + JSON.stringify(texts)); - } catch (e: any) { console.error('FAIL:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-slider.ts b/scripts/probe-slider.ts deleted file mode 100644 index a37c505..0000000 --- a/scripts/probe-slider.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { createDriver } from '../drivers/factory'; - -(async () => { - const d = createDriver(); - await d.createSession(); - const KW = process.env.LIGHT_CARD || 'Strip Light 4E'; - const W = 1080, H = 2400; - const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); - const status = async () => { - const src = await d.getSource(); - const texts = Array.from(src.matchAll(/text="([^"]+)"/g)).map((m) => m[1]); - const i = texts.findIndex((t) => t.includes(KW)); - return i >= 0 ? texts[i + 1] || '' : ''; - }; - const bri = async () => { const m = (await status()).match(/(\d+)\s*%/); return m ? +m[1] : -1; }; - try { - await d.dismissPopupIfPresent(); await d.goBackToHomepage(); await sleep(800); - let el: string | null = null; - for (let i = 0; i < 10; i++) { el = await d.findElementRaw('-android uiautomator', `new UiSelector().textContains("${KW}")`).catch(() => null); if (el) break; await d.swipe(540, 1500, 540, 700, 0.4).catch(() => {}); await sleep(800); } - if (!el) throw new Error('找不到卡片'); - const r = await d.getElementRect(el); - await d.tap(r.x + r.width / 2, r.y + r.height / 2); await sleep(2500); - - // 开灯(动态电源键) - const src0 = await d.getSource(); - const pw = Array.from(src0.matchAll(/clickable="true"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/g)) - .map((m) => ({ w: +m[3] - +m[1], h: +m[4] - +m[2], cx: (+m[1] + +m[3]) / 2, cy: (+m[2] + +m[4]) / 2 })) - .filter((b) => b.w >= 150 && b.w <= 320 && b.h >= 150 && b.h <= 320 && Math.abs(b.cx - W / 2) < W * 0.15 && b.cy > H * 0.4); - if (await bri() < 0 && pw.length) { await d.tap(Math.round(pw[0].cx), Math.round(pw[0].cy)); await sleep(3500); } - console.log('开灯后状态=' + JSON.stringify(await status())); - - // 列出所有滑条 track - const src = await d.getSource(); - const tracks = Array.from(src.matchAll(/class="android\.view\.View"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/g)) - .map((m) => ({ x1: +m[1], y1: +m[2], x2: +m[3], y2: +m[4] })) - .filter((b) => b.x2 - b.x1 > W * 0.8 && b.y2 - b.y1 > 40 && b.y2 - b.y1 < 280 && b.y1 > H * 0.4) - .map((b) => ({ left: b.x1 + 10, right: b.x2 - 10, y: Math.round((b.y1 + b.y2) / 2) })) - .sort((a, b) => a.y - b.y); - console.log('滑条数=' + tracks.length + ' y=' + JSON.stringify(tracks.map((t) => t.y))); - - // 逐条:从中点拖到低(0.25)读%,再拖到高(0.75)读% — 找亮度条+方向 - for (const t of tracks) { - const mid = Math.round((t.left + t.right) / 2); - const loX = Math.round(t.left + 0.25 * (t.right - t.left)); - const hiX = Math.round(t.left + 0.75 * (t.right - t.left)); - // 起点尝试:先按当前亮度反算滑块位置(若读得到),否则用中点 - const cur = await bri(); const span = t.right - t.left; - const startX = cur >= 0 ? Math.round(t.left + cur / 100 * span) : mid; - await d.swipe(startX, t.y, loX, t.y, 0.7); await sleep(2000); const aLo = await bri(); - await d.swipe(loX, t.y, hiX, t.y, 0.7); await sleep(2000); const aHi = await bri(); - console.log(`track y=${t.y}: 拖低→${aLo}% 拖高→${aHi}% ${aHi > aLo && aHi > 0 ? '★亮度条(正向)' : ''}`); - } - } catch (e: any) { console.error('探针失败:', e.message); } - finally { await d.destroySession(); } -})(); diff --git a/scripts/probe-tap.ts b/scripts/probe-tap.ts deleted file mode 100644 index c7dcb7e..0000000 --- a/scripts/probe-tap.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<40))].slice(0,20) as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - const T=process.env.TAP||'Connect Device'; - for(const t of [T,'Connect device']){const b=await d.findElementRaw('-android uiautomator',`new UiSelector().text("${t}")`).catch(()=>null);if(b){await d.tapElement(b);console.log('点了 '+t);break;}} - for(let i=0;i<8;i++){await sleep(4000);const tx=await dump(d);console.log(`+${(i+1)*4}s: ${JSON.stringify(tx)}`);if(/Configure Wi-?Fi|Enter Wi-?Fi|SSID|Connecting to your router|found|Configure network/i.test(tx.join(' '))){console.log('==到配网/发现==');break;}} -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/scripts/probe-tap2.ts b/scripts/probe-tap2.ts deleted file mode 100644 index 70aba23..0000000 --- a/scripts/probe-tap2.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createDriver } from '../drivers/factory'; -const sleep=(ms:number)=>new Promise(r=>setTimeout(r,ms)); -const dump=async(d:any):Promise=>[...new Set((Array.from((await d.getSource()).matchAll(/text="([^"]+)"/g)) as any[]).map(m=>m[1]).filter((t:string)=>t.trim()&&t.length<30))] as string[]; -(async()=>{const d=createDriver();await d.createSession();try{ - // 先关弹框(勾Do not show again再关) - const cb=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Do not show again")').catch(()=>null); - if(cb){await d.tapElement(cb).catch(()=>{});await sleep(500);} - for(const t of ['OK','Got it','Confirm','I Know','Close']){const b=await d.findElementRaw('-android uiautomator',`new UiSelector().text("${t}")`).catch(()=>null);if(b){await d.tapElement(b);await sleep(1500);break;}} - console.log('关弹框后: '+JSON.stringify(await dump(d))); - const pair=await d.findElementRaw('-android uiautomator','new UiSelector().textContains("Pair to Lock")').catch(()=>null); - if(pair){await d.tapElement(pair);await sleep(3000);console.log('点Pair to Lock后: '+JSON.stringify(await dump(d)));} -}catch(e:any){console.error('FAIL:',e.message);}finally{await d.destroySession();}})(); diff --git a/tmp_hub.ts b/tmp_hub.ts deleted file mode 100644 index 44b7d44..0000000 --- a/tmp_hub.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createDriver } from './drivers/factory'; -const sleep = (ms: number) => new Promise(r => setTimeout(r, ms)); -(async () => { - process.env.PLATFORM = 'ios'; - const d = createDriver(); await d.createSession(); - try { - await d.goBackToHomepage(); await sleep(1200); - const seen = new Set(); - for (let i = 0; i < 16; i++) { - const src = await d.getSource(); - // iOS 卡名在 name/label;抓含 Hub 的 - for (const m of src.matchAll(/(?:name|label|value)="([^"]*Hub[^"]*)"/g)) seen.add(m[1]); - await d.scrollDown(500); await sleep(500); - } - console.log('含 Hub 的元素:', JSON.stringify(Array.from(seen))); - } finally { await d.destroySession(); } -})();