删除调试临时脚本(probe-*.ts + tmp_hub.ts)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ae336e300f
commit
cf153b31ab
|
|
@ -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();
|
||||
}
|
||||
})();
|
||||
|
|
@ -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)<W*0.15&&b.cy>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();}
|
||||
})();
|
||||
|
|
@ -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<string> => {
|
||||
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(); }
|
||||
})();
|
||||
|
|
@ -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<string> => {
|
||||
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<string[]> => {
|
||||
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(); }
|
||||
})();
|
||||
|
|
@ -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(); }
|
||||
})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
import { createDriver } from '../drivers/factory';
|
||||
const dump=async(d:any):Promise<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string>();
|
||||
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();}})();
|
||||
|
|
@ -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<string[]> => [...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(); }
|
||||
})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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();
|
||||
}
|
||||
})();
|
||||
|
|
@ -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<string>();
|
||||
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(); }
|
||||
})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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<string[]>=>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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]> => [...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(); }
|
||||
})();
|
||||
|
|
@ -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(); }
|
||||
})();
|
||||
|
|
@ -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(); }
|
||||
})();
|
||||
|
|
@ -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(); }
|
||||
})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
|
|
@ -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<string[]>=>[...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();}})();
|
||||
17
tmp_hub.ts
17
tmp_hub.ts
|
|
@ -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<string>();
|
||||
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(); }
|
||||
})();
|
||||
Loading…
Reference in New Issue