diff --git a/.gitignore b/.gitignore index b263584..d281830 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ node_modules .env -!env*example \ No newline at end of file +!env*example + +dist \ No newline at end of file diff --git a/agent/app.ts b/agent/app.ts new file mode 100644 index 0000000..bb8f469 --- /dev/null +++ b/agent/app.ts @@ -0,0 +1,9 @@ +import { App } from '@kevisual/router' +import { useContextKey } from '@kevisual/context'; +import { useConfig } from "@kevisual/use-config"; + +export const config = useConfig<{ HAAS_TOKEN: string, HAAS_URL: string, HAAS_MI_ENTITY_ID: string }>(); + +export const app = useContextKey('app', () => { + return new App(); +}); \ No newline at end of file diff --git a/agent/index.ts b/agent/index.ts new file mode 100644 index 0000000..2f6a0bd --- /dev/null +++ b/agent/index.ts @@ -0,0 +1,3 @@ +export * from './app.ts'; + +import './routes/index.ts'; \ No newline at end of file diff --git a/agent/routes/call.ts b/agent/routes/call.ts new file mode 100644 index 0000000..83622c3 --- /dev/null +++ b/agent/routes/call.ts @@ -0,0 +1,74 @@ +import { LightHA } from "../../src/index.ts"; +import { config } from "../app.ts"; +import { app } from "../app.ts"; +import dayjs from 'dayjs'; +export const lightHA = new LightHA({ token: config.HAAS_TOKEN || '', homeassistantURL: config.HAAS_URL }); + +const mi = config.HAAS_MI_ENTITY_ID || 'text.xiaomi_lx06_9e08_execute_text_directive'; + +type CallHaReult = { + entity_id?: string; + runTime?: number; + message?: string; +} +export const callText = async (text: string): Promise => { + const command = text?.trim().slice(0, 20); + type ParseCommand = { + type?: '打开' | '关闭', + appName?: string, + command?: string, + } + let obj: ParseCommand = {}; + if (command.startsWith('打开')) { + obj.appName = command.replace('打开', '').trim(); + obj.type = '打开'; + } else if (command.startsWith('关闭')) { + obj.appName = command.replace('关闭', '').trim(); + obj.type = '关闭'; + } + let endTime = Date.now(); + let result: CallHaReult = {}; + if (obj.type) { + try { + const search = await lightHA.searchLight(obj.appName || ''); + console.log('searchTime', Date.now() - endTime); + if (search.id) { + result.entity_id = search.id; + await lightHA.runService({ entity_id: search.id, service: obj.type === '打开' ? 'turn_on' : 'turn_off' }); + } else if (search.hasMore) { + const [first] = search.result; + await lightHA.runService({ entity_id: first.entity_id, service: obj.type === '打开' ? 'turn_on' : 'turn_off' }); + result.entity_id = first.entity_id; + } else { + if (mi) { + result.message = '使用小爱音箱控制'; + await lightHA.text.executeTextDirective(mi, text); + } else { + console.log('未找到对应设备:', obj.appName); + result.message = `未找到对应设备: ${obj.appName}`; + } + } + console.log('解析到控制指令', obj); + } catch (e) { + console.error('控制失败', e); + } + } else { + result.message = '无法解析控制指令,必须以 "打开 xxx" 或 "关闭 xxx" 开头'; + } + result.runTime = Date.now() - endTime; + return result; +} + +app.route({ + path: 'ha', + key: 'ha-call', + description: 'Home Assistant 控制指令', + +}).define(async (ctx) => { + const text = ctx.query?.text || '' + if (!text) { + ctx.throw(400, '缺少 text 参数'); + } + const res = await callText(text); + ctx.body = { content: '指令已发送', result: res, timestamp: dayjs().format() }; +}).addTo(app) \ No newline at end of file diff --git a/agent/routes/index.ts b/agent/routes/index.ts new file mode 100644 index 0000000..689e4a1 --- /dev/null +++ b/agent/routes/index.ts @@ -0,0 +1 @@ +import './call.ts' \ No newline at end of file diff --git a/bun.config.ts b/bun.config.ts new file mode 100644 index 0000000..c4b766e --- /dev/null +++ b/bun.config.ts @@ -0,0 +1,22 @@ +import { resolvePath } from '@kevisual/use-config'; +import { execSync } from 'node:child_process'; + +const buildFn = async (opts: { entry?: string, naming?: string, external?: string[] }) => { + const entry = opts.entry || 'index.ts'; + const naming = opts.naming || 'app'; + const external: string[] = opts.external || ["bun", "ws"]; + await Bun.build({ + target: 'node', + format: 'esm', + entrypoints: [resolvePath(entry, { meta: import.meta })], + outdir: resolvePath('./dist', { meta: import.meta }), + naming: { + entry: `${naming}.js`, + }, + external, + }); + const cmd = `dts -i ${entry} -o ${naming}.d.ts`; + execSync(cmd); +}; + +await buildFn({ naming: 'app', entry: 'agent/index.ts' }); \ No newline at end of file diff --git a/package.json b/package.json index 57f8199..4ccc339 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,18 @@ { "name": "@kevisual/ha-api", - "version": "0.0.6", + "version": "0.0.7", "description": "", "main": "src/index.ts", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build": "bun run bun.config.ts" }, "app": { - "type": "pm2-system-app", - "entry": "src/index.ts" + "type": "system-app", + "entry": "dist/app.js" }, "files": [ + "dist", + "agent", "src" ], "keywords": [], @@ -19,16 +21,24 @@ }, "author": "abearxiong (https://www.xiongxiao.me)", "license": "MIT", - "packageManager": "pnpm@10.26.2", + "packageManager": "pnpm@10.28.2", "type": "module", "devDependencies": { - "@types/bun": "^1.3.5", - "@types/node": "^25.0.3", + "@types/bun": "^1.3.8", + "@types/node": "^25.1.0", + "dayjs": "^1.11.19", + "@kevisual/context": "^0.0.4", + "@kevisual/router": "^0.0.64", + "@kevisual/use-config": "^1.0.28", "dotenv": "^17.2.3" }, "dependencies": { - "@kevisual/cache": "^0.0.4", + "@kevisual/cache": "^0.0.5", "fuse.js": "^7.1.0", - "lru-cache": "^11.2.4" + "lru-cache": "^11.2.5" + }, + "exports": { + ".": "./src/index.ts", + "./routes": "./dist/app.js" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b2cc7f..8e6e4e4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,90 +9,670 @@ importers: .: dependencies: '@kevisual/cache': + specifier: ^0.0.5 + version: 0.0.5 + '@kevisual/context': specifier: ^0.0.4 version: 0.0.4 + '@kevisual/router': + specifier: ^0.0.64 + version: 0.0.64(typescript@5.9.3) + '@kevisual/use-config': + specifier: ^1.0.28 + version: 1.0.28(dotenv@17.2.3) fuse.js: specifier: ^7.1.0 version: 7.1.0 lru-cache: - specifier: ^11.2.4 - version: 11.2.4 + specifier: ^11.2.5 + version: 11.2.5 devDependencies: '@types/bun': - specifier: ^1.3.5 - version: 1.3.5 + specifier: ^1.3.8 + version: 1.3.8 '@types/node': - specifier: ^25.0.3 - version: 25.0.3 + specifier: ^25.1.0 + version: 25.1.0 + dayjs: + specifier: ^1.11.19 + version: 1.11.19 dotenv: specifier: ^17.2.3 version: 17.2.3 packages: - '@kevisual/cache@0.0.4': - resolution: {integrity: sha512-NlyriJ9fC27TgQhWYbEH9hG84R2k0lIofOxo/+nVHN6a6LJSLnVbpDIysRcnH8MI52n/XHfWwLSjeDDL3D1/cQ==} + '@babel/code-frame@7.28.6': + resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + engines: {node: '>=6.9.0'} - '@types/bun@1.3.5': - resolution: {integrity: sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} - '@types/node@25.0.3': - resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - bun-types@1.3.5: - resolution: {integrity: sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw==} + '@kevisual/cache@0.0.5': + resolution: {integrity: sha512-fgtUYGUUq/DY0KFV4CkWszNqvQUaA8XvMTUjoR9ZXRpau5IIDolD/Wen2TFsZ7G3Rfy+lef5dnaiZVDkZwdVKg==} + + '@kevisual/context@0.0.4': + resolution: {integrity: sha512-HJeLeZQLU+7tCluSfOyvkgKLs0HjCZrdJlZgEgKRSa8XTwZfMAUt6J7qZTbrZAHBlPtX68EPu/PI8JMCeu3WAQ==} + + '@kevisual/dts@0.0.3': + resolution: {integrity: sha512-4T/m2LqhtwWEW+lWmg7jLxKFW7VtIAftsWFDDZvh10bZunqFf8iXxChHcVSQWikghJb4cq1IkWzPkvc2l+Asdw==} + hasBin: true + + '@kevisual/load@0.0.6': + resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==} + + '@kevisual/router@0.0.64': + resolution: {integrity: sha512-EYz1MZxrltgySUL0Y+/MtZf2FEmqC5U8GmFAqvHNjgtS5FJdHpxRjo6zab4+0wSUlVyCxCpZXFY5vHB/g+nQBw==} + + '@kevisual/use-config@1.0.28': + resolution: {integrity: sha512-ngF+LDbjxpXWrZNmnShIKF/jPpAa+ezV+DcgoZIIzHlRnIjE+rr9sLkN/B7WJbiH9C/j1tQXOILY8ujBqILrow==} + peerDependencies: + dotenv: ^17 + + '@rollup/plugin-commonjs@28.0.9': + resolution: {integrity: sha512-PIR4/OHZ79romx0BVVll/PkwWpJ7e5lsqFa3gFfcrFPWwLXLV39JVUzQV9RKjWerE7B845Hqjj9VYlQeieZ2dA==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.3': + resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-typescript@12.3.0': + resolution: {integrity: sha512-7DP0/p7y3t67+NabT9f8oTBFE6gGkto4SA6Np2oudYmZE/m1dt8RB0SjL1msMxFpLo631qjRCcBlAbq1ml/Big==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.57.1': + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.57.1': + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.57.1': + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.57.1': + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.57.1': + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.57.1': + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.57.1': + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.57.1': + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.57.1': + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.57.1': + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.57.1': + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.57.1': + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.57.1': + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.57.1': + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + cpu: [x64] + os: [win32] + + '@types/bun@1.3.8': + resolution: {integrity: sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@25.1.0': + resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + bun-types@1.3.8: + resolution: {integrity: sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q==} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} dotenv@17.2.3: resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + fuse.js@7.1.0: resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} engines: {node: '>=10'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hono@4.11.7: + resolution: {integrity: sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==} + engines: {node: '>=16.9.0'} + idb-keyval@6.2.2: resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} - lru-cache@11.2.4: - resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + lru-cache@11.2.5: + resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + nanoid@5.1.6: resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} engines: {node: ^18 || >=20} hasBin: true + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + rollup-plugin-dts@6.3.0: + resolution: {integrity: sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + + rollup@4.57.1: + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} snapshots: - '@kevisual/cache@0.0.4': + '@babel/code-frame@7.28.6': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + optional: true + + '@babel/helper-validator-identifier@7.28.5': + optional: true + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@kevisual/cache@0.0.5': dependencies: idb-keyval: 6.2.2 - lru-cache: 11.2.4 + lru-cache: 11.2.5 nanoid: 5.1.6 - '@types/bun@1.3.5': - dependencies: - bun-types: 1.3.5 + '@kevisual/context@0.0.4': {} - '@types/node@25.0.3': + '@kevisual/dts@0.0.3(typescript@5.9.3)': + dependencies: + '@rollup/plugin-commonjs': 28.0.9(rollup@4.57.1) + '@rollup/plugin-node-resolve': 16.0.3(rollup@4.57.1) + '@rollup/plugin-typescript': 12.3.0(rollup@4.57.1)(tslib@2.8.1)(typescript@5.9.3) + rollup: 4.57.1 + rollup-plugin-dts: 6.3.0(rollup@4.57.1)(typescript@5.9.3) + tslib: 2.8.1 + transitivePeerDependencies: + - typescript + + '@kevisual/load@0.0.6': + dependencies: + eventemitter3: 5.0.4 + + '@kevisual/router@0.0.64(typescript@5.9.3)': + dependencies: + '@kevisual/dts': 0.0.3(typescript@5.9.3) + hono: 4.11.7 + transitivePeerDependencies: + - typescript + + '@kevisual/use-config@1.0.28(dotenv@17.2.3)': + dependencies: + '@kevisual/load': 0.0.6 + dotenv: 17.2.3 + + '@rollup/plugin-commonjs@28.0.9(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.5.0(picomatch@4.0.3) + is-reference: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-node-resolve@16.0.3(rollup@4.57.1)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.11 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/plugin-typescript@12.3.0(rollup@4.57.1)(tslib@2.8.1)(typescript@5.9.3)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + resolve: 1.22.11 + typescript: 5.9.3 + optionalDependencies: + rollup: 4.57.1 + tslib: 2.8.1 + + '@rollup/pluginutils@5.3.0(rollup@4.57.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + + '@rollup/rollup-android-arm-eabi@4.57.1': + optional: true + + '@rollup/rollup-android-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-x64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.57.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.57.1': + optional: true + + '@rollup/rollup-openharmony-arm64@4.57.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.57.1': + optional: true + + '@types/bun@1.3.8': + dependencies: + bun-types: 1.3.8 + + '@types/estree@1.0.8': {} + + '@types/node@25.1.0': dependencies: undici-types: 7.16.0 - bun-types@1.3.5: + '@types/resolve@1.20.2': {} + + bun-types@1.3.8: dependencies: - '@types/node': 25.0.3 + '@types/node': 25.1.0 + + commondir@1.0.1: {} + + dayjs@1.11.19: {} + + deepmerge@4.3.1: {} dotenv@17.2.3: {} + estree-walker@2.0.2: {} + + eventemitter3@5.0.4: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + fuse.js@7.1.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hono@4.11.7: {} + idb-keyval@6.2.2: {} - lru-cache@11.2.4: {} + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-module@1.0.0: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.8 + + js-tokens@4.0.0: + optional: true + + lru-cache@11.2.5: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 nanoid@5.1.6: {} + path-parse@1.0.7: {} + + picocolors@1.1.1: + optional: true + + picomatch@4.0.3: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rollup-plugin-dts@6.3.0(rollup@4.57.1)(typescript@5.9.3): + dependencies: + magic-string: 0.30.21 + rollup: 4.57.1 + typescript: 5.9.3 + optionalDependencies: + '@babel/code-frame': 7.28.6 + + rollup@4.57.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.57.1 + '@rollup/rollup-android-arm64': 4.57.1 + '@rollup/rollup-darwin-arm64': 4.57.1 + '@rollup/rollup-darwin-x64': 4.57.1 + '@rollup/rollup-freebsd-arm64': 4.57.1 + '@rollup/rollup-freebsd-x64': 4.57.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 + '@rollup/rollup-linux-arm-musleabihf': 4.57.1 + '@rollup/rollup-linux-arm64-gnu': 4.57.1 + '@rollup/rollup-linux-arm64-musl': 4.57.1 + '@rollup/rollup-linux-loong64-gnu': 4.57.1 + '@rollup/rollup-linux-loong64-musl': 4.57.1 + '@rollup/rollup-linux-ppc64-gnu': 4.57.1 + '@rollup/rollup-linux-ppc64-musl': 4.57.1 + '@rollup/rollup-linux-riscv64-gnu': 4.57.1 + '@rollup/rollup-linux-riscv64-musl': 4.57.1 + '@rollup/rollup-linux-s390x-gnu': 4.57.1 + '@rollup/rollup-linux-x64-gnu': 4.57.1 + '@rollup/rollup-linux-x64-musl': 4.57.1 + '@rollup/rollup-openbsd-x64': 4.57.1 + '@rollup/rollup-openharmony-arm64': 4.57.1 + '@rollup/rollup-win32-arm64-msvc': 4.57.1 + '@rollup/rollup-win32-ia32-msvc': 4.57.1 + '@rollup/rollup-win32-x64-gnu': 4.57.1 + '@rollup/rollup-win32-x64-msvc': 4.57.1 + fsevents: 2.3.3 + + supports-preserve-symlinks-flag@1.0.0: {} + + tslib@2.8.1: {} + + typescript@5.9.3: {} + undici-types@7.16.0: {} diff --git a/src/light.ts b/src/light.ts index f7d9a9b..5a1a5c2 100644 --- a/src/light.ts +++ b/src/light.ts @@ -2,8 +2,10 @@ import Fuse from "fuse.js"; import { HACore, HACoreOptions, InfoItem, EntityItem } from "./core.ts"; export class LightHA extends HACore { static serviceName = 'light'; + text: TextHA; constructor(options: HACoreOptions) { super(options); + this.text = new TextHA(options); } async searchLight(keyword: string): Promise<{ result: InfoItem[], lights: InfoItem[], id?: string, hasMore?: boolean }> { const devices = await this.getInfoList(); diff --git a/test/speaker.ts b/test/speaker.ts index b25f959..59e13ab 100644 --- a/test/speaker.ts +++ b/test/speaker.ts @@ -20,8 +20,8 @@ console.log(`实体数量: ${entities.length}`); // console.log(showMore(res)); -const res2 = await text.executeTextDirective('text.xiaomi_lx06_9e08_execute_text_directive', '关闭阳台灯'); +const res2 = await text.executeTextDirective('text.xiaomi_lx06_9e08_execute_text_directive', '打开阳台灯'); console.log(showMore(res2)); -const call = { "type": "call_service", "domain": "text", "service": "set_value", "target": { "entity_id": "text.xiaomi_lx06_9e08_execute_text_directive" }, "return_response": false, "service_data": { "value": "关闭阳台灯" }, "id": 101 } \ No newline at end of file +// const call = { "type": "call_service", "domain": "text", "service": "set_value", "target": { "entity_id": "text.xiaomi_lx06_9e08_execute_text_directive" }, "return_response": false, "service_data": { "value": "关闭阳台灯" }, "id": 101 } \ No newline at end of file