添加灯光管理、自动化和脚本功能,更新依赖项,完善文档
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
|
||||
.env
|
||||
!env*example
|
||||
2
.npmrc
Normal file
2
.npmrc
Normal file
@@ -0,0 +1,2 @@
|
||||
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
|
||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||
13
package.json
13
package.json
@@ -1,21 +1,28 @@
|
||||
{
|
||||
"name": "ha-api",
|
||||
"name": "@kevisual/ha-api",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"keywords": [],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||
"license": "MIT",
|
||||
"packageManager": "pnpm@10.24.0",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.3.3",
|
||||
"dotenv": "^17.2.3",
|
||||
"@types/node": "^24.10.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^17.2.3"
|
||||
"fuse.js": "^7.1.0"
|
||||
}
|
||||
}
|
||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
||||
dotenv:
|
||||
specifier: ^17.2.3
|
||||
version: 17.2.3
|
||||
fuse.js:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
devDependencies:
|
||||
'@types/bun':
|
||||
specifier: ^1.3.3
|
||||
@@ -34,6 +37,10 @@ packages:
|
||||
resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
fuse.js@7.1.0:
|
||||
resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
undici-types@7.16.0:
|
||||
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||
|
||||
@@ -53,4 +60,6 @@ snapshots:
|
||||
|
||||
dotenv@17.2.3: {}
|
||||
|
||||
fuse.js@7.1.0: {}
|
||||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
27
readme.md
Normal file
27
readme.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 灯光管理
|
||||
|
||||
该模块提供对Home Assistant中灯光设备的管理功能,包括获取灯光列表、搜索特定灯光设备以及控制灯光的开关状态。
|
||||
|
||||
```ts
|
||||
import { haLight } from '@kevisual/ha-api';
|
||||
|
||||
const light = new haLight({
|
||||
host: 'http://your-home-assistant:8123',
|
||||
token: 'your-long-lived-access-token',
|
||||
});
|
||||
// 获取所有灯光设备
|
||||
const lights = await light.getLights();
|
||||
console.log(lights);
|
||||
|
||||
const searchResult = await light.searchLight('living room');
|
||||
console.log(searchResult);
|
||||
|
||||
if(searchResult.hasMore) {
|
||||
console.log('多个灯光设备匹配该关键词,请进一步筛选。');
|
||||
} else if(searchResult.id) {
|
||||
console.log(`唯一匹配的灯光设备ID为: ${searchResult.id}`);
|
||||
light.toggleLight({ entity_id: searchResult.id, service: 'turn_on' });
|
||||
} else {
|
||||
console.log('没有找到匹配的灯光设备。');
|
||||
}
|
||||
```
|
||||
13
src/auto.ts
Normal file
13
src/auto.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import Fuse from "fuse.js";
|
||||
import { HACore, HACoreOptions } from "./core";
|
||||
|
||||
export class AutoHA extends HACore {
|
||||
constructor(options: HACoreOptions) {
|
||||
super(options);
|
||||
}
|
||||
getAutos() {
|
||||
const auto = this.getEntities((entity: any) => entity.entity_id.startsWith('automation.'));
|
||||
return auto;
|
||||
}
|
||||
|
||||
}
|
||||
68
src/core.ts
68
src/core.ts
@@ -1,11 +1,10 @@
|
||||
const homeassistantURL = 'http://home.mz.zxj.im:8123';
|
||||
|
||||
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmMzk3ZDUwMWU3ODE0MTA4Yjk4ZjYwNDFjMzI3NzVkZSIsImlhdCI6MTc2NDg2NDUyMywiZXhwIjoyMDgwMjI0NTIzfQ.S2zO3DNzeVYgd1c_N9IkRc13zmtj2HGVq-n6IUmttRQ'
|
||||
|
||||
type HACoreOptions = {
|
||||
export type HACoreOptions = {
|
||||
token: string;
|
||||
homeassistantURL?: string;
|
||||
}
|
||||
/**
|
||||
* https://developers.home-assistant.io/docs/api/rest/
|
||||
*/
|
||||
export class HACore {
|
||||
token: string;
|
||||
homeassistantURL?: string;
|
||||
@@ -47,15 +46,56 @@ export class HACore {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
async getEntities(filter?: (entity: any) => boolean): Promise<any[]> {
|
||||
const entities = await this.get({ url: '/api/states' });
|
||||
if (filter) {
|
||||
return entities.filter(filter);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
async getState(entity_id?: string): Promise<any> {
|
||||
return this.get({ url: `/api/states/${entity_id}` });
|
||||
}
|
||||
async getEntityTypes(): Promise<any[]> {
|
||||
const entities = await this.getEntities();
|
||||
const types = new Set<string>();
|
||||
entities.forEach((entity: any) => {
|
||||
const [type] = entity.entity_id.split('.');
|
||||
types.add(type);
|
||||
});
|
||||
return Array.from(types);
|
||||
}
|
||||
}
|
||||
|
||||
export const getEntities = async (): Promise<any[]> => {
|
||||
const hacore = new HACore({ token, homeassistantURL });
|
||||
return hacore.get({ url: '/api/states' });
|
||||
}
|
||||
|
||||
export const getLights = async (): Promise<any[]> => {
|
||||
const hacore = new HACore({ token, homeassistantURL });
|
||||
const entities = await hacore.get({ url: '/api/states' });
|
||||
return entities.filter((entity: any) => entity.entity_id.startsWith('light.'));
|
||||
}
|
||||
|
||||
export const entitiesTypes = [
|
||||
{ "type": "conversation", "desc": "处理自然语言对话指令,如语音助手" },
|
||||
{ "type": "event", "desc": "系统或设备触发的事件,用于自动化监听" },
|
||||
{ "type": "sensor", "desc": "测量并报告数值型数据,如温度、湿度、电量" },
|
||||
{ "type": "zone", "desc": "定义地理区域,用于判断人或设备是否在范围内" },
|
||||
{ "type": "person", "desc": "代表家庭成员,关联位置与状态(在家/离家)" },
|
||||
{ "type": "scene", "desc": "预设一组设备状态,一键切换场景" },
|
||||
{ "type": "sun", "desc": "提供日出、日落等天文信息,用于时间触发" },
|
||||
{ "type": "script", "desc": "可调用的自动化脚本,执行一系列操作步骤" },
|
||||
{ "type": "binary_sensor", "desc": "报告二进制状态(开/关),如门磁、运动传感器" },
|
||||
{ "type": "device_tracker", "desc": "追踪设备(如手机)的位置信息" },
|
||||
{ "type": "media_player", "desc": "控制媒体播放设备,如音响、电视" },
|
||||
{ "type": "todo", "desc": "管理待办事项列表,如购物清单或任务" },
|
||||
{ "type": "update", "desc": "监控系统或设备的软件更新状态" },
|
||||
{ "type": "tts", "desc": "文本转语音服务,用于语音播报" },
|
||||
{ "type": "ai_task", "desc": "自定义AI任务(非官方标准,可能来自第三方AI集成)" },
|
||||
{ "type": "automation", "desc": "定义自动化规则,触发条件与动作的组合" },
|
||||
{ "type": "weather", "desc": "提供天气预报信息,如温度、降水、风速" },
|
||||
{ "type": "remote", "desc": "发送红外或射频遥控信号,控制电视、空调等" },
|
||||
{ "type": "switch", "desc": "控制开关类设备,如智能插座、继电器" },
|
||||
{ "type": "button", "desc": "触发一次性操作,按下即执行(无状态)" },
|
||||
{ "type": "text", "desc": "可编辑的文本字段,用于输入或显示文本信息" },
|
||||
{ "type": "select", "desc": "从预定义选项中选择一个值,如模式、音源" },
|
||||
{ "type": "climate", "desc": "控制温控设备,如空调、恒温器" },
|
||||
{ "type": "cover", "desc": "控制遮蔽设备,如窗帘、百叶窗、车库门" },
|
||||
{ "type": "fan", "desc": "控制风扇设备,支持风速、摇头等" },
|
||||
{ "type": "light", "desc": "控制照明设备,支持开关、亮度、颜色、色温" },
|
||||
{ "type": "notify", "desc": "发送通知,如推送、邮件、语音播报" },
|
||||
{ "type": "number", "desc": "可调整的数值控件,有上下限,如温度设定、定时器" }
|
||||
]
|
||||
9
src/event.ts
Normal file
9
src/event.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import Fuse from "fuse.js";
|
||||
import { HACore, HACoreOptions } from "./core";
|
||||
|
||||
export class EventHA extends HACore {
|
||||
getEvents() {
|
||||
const events = this.getEntities((entity: any) => entity.entity_id.startsWith('event.'));
|
||||
return events;
|
||||
}
|
||||
}
|
||||
8
src/index.ts
Normal file
8
src/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export * from './light.ts'
|
||||
export * from './core.ts'
|
||||
|
||||
export * from './auto.ts'
|
||||
|
||||
export * from './event.ts'
|
||||
|
||||
export * from './script.ts'
|
||||
85
src/light.ts
Normal file
85
src/light.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import Fuse from "fuse.js";
|
||||
import { HACore, HACoreOptions } from "./core";
|
||||
|
||||
export class LightHA extends HACore {
|
||||
constructor(options: HACoreOptions) {
|
||||
super(options);
|
||||
}
|
||||
async getLights(): Promise<any[]> {
|
||||
return this.getEntities((entity: any) => entity.entity_id.startsWith('light.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换灯的状态,若未指定 service,则根据当前状态切换
|
||||
* @param opts
|
||||
* @returns
|
||||
*/
|
||||
async toggleLight(opts: { entity_id?: string, name?: string, service?: string, data?: Record<string, any> }): Promise<any> {
|
||||
// e.g., service: 'turn_on', 'turn_off', 'toggle'
|
||||
let { entity_id, service = '', data } = opts;
|
||||
if (!entity_id && opts.name) {
|
||||
const entities = await this.getLights();
|
||||
const target = entities.find((entity: any) => entity.attributes?.friendly_name.includes(opts.name || ''));
|
||||
if (target) {
|
||||
entity_id = target.entity_id;
|
||||
} else {
|
||||
throw new Error(`Light with name including "${opts.name}" not found.`);
|
||||
}
|
||||
} else if (!entity_id) {
|
||||
throw new Error('实体 ID 或 名称 必须提供其一。');
|
||||
}
|
||||
if (!service) {
|
||||
const state = await this.getState(entity_id!);
|
||||
service = state.state === 'on' ? 'turn_off' : 'turn_on';
|
||||
}
|
||||
return this.post({
|
||||
url: `/api/services/light/${service}`,
|
||||
body: {
|
||||
entity_id,
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
async getInfoList(): Promise<LightItem[]> {
|
||||
const lights = await this.getLights();
|
||||
const infoList = lights.map((light: any) => {
|
||||
return {
|
||||
entity_id: light.entity_id,
|
||||
name: light.attributes?.friendly_name || '',
|
||||
state: light.state,
|
||||
};
|
||||
});
|
||||
return infoList;
|
||||
}
|
||||
async searchLight(keyword: string): Promise<{ result: LightItem[], lights: LightItem[], id?: string, hasMore?: boolean }> {
|
||||
const devices = await this.getInfoList();
|
||||
const fuse = new Fuse(devices, {
|
||||
keys: ['name'], // 搜索字段
|
||||
threshold: 0.4, // 匹配宽松度:0~1,越小越严格
|
||||
includeScore: true,
|
||||
minMatchCharLength: 1, // 允许单字匹配
|
||||
});
|
||||
const result = fuse.search(keyword);
|
||||
const resultItems = result.map(r => r.item);
|
||||
let id = ''
|
||||
if (resultItems.length === 1) {
|
||||
id = resultItems[0].entity_id;
|
||||
}
|
||||
const hasMore = resultItems.length > 1;
|
||||
return { result: resultItems, lights: devices, id, hasMore };
|
||||
}
|
||||
async closeAllLights(): Promise<void> {
|
||||
const lights = await this.getLights();
|
||||
for (const light of lights) {
|
||||
if (light.state === 'on') {
|
||||
this.toggleLight({ entity_id: light.entity_id, service: 'turn_off' });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type LightItem = {
|
||||
entity_id: string;
|
||||
name: string;
|
||||
state: string;
|
||||
}
|
||||
19
src/script.ts
Normal file
19
src/script.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { HACore, HACoreOptions } from "./core";
|
||||
|
||||
export class ScriptHA extends HACore {
|
||||
static serviceName = 'script';
|
||||
getScripts() {
|
||||
const scripts = this.getEntities((entity: any) => entity.entity_id.startsWith('script.'));
|
||||
return scripts;
|
||||
}
|
||||
runScript(entity_id: string, data?: Record<string, any>) {
|
||||
const serviceName = ScriptHA.serviceName;
|
||||
return this.post({
|
||||
url: `/api/services/${serviceName}/turn_on`,
|
||||
body: {
|
||||
entity_id,
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
5
test/auto.ts
Normal file
5
test/auto.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { auto, showMore } from './common.ts'
|
||||
|
||||
const autos = await auto.getAutos();
|
||||
|
||||
console.log(showMore(autos));
|
||||
212
test/common.ts
212
test/common.ts
@@ -1,113 +1,127 @@
|
||||
import { HACore } from "../src/core";
|
||||
import { LightHA, AutoHA, EventHA, ScriptHA } from "../src/index.ts";
|
||||
|
||||
import util from 'node:util';
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
export const showMore = (obj: any) => {
|
||||
return util.inspect(obj, { depth: null, colors: true });
|
||||
}
|
||||
|
||||
export const hacore = new LightHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
|
||||
const hacore = new HACore({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
const enti = await hacore.get({ url: '/api/states' });
|
||||
// console.log(util.inspect(enti, { depth: null }));
|
||||
export const auto = new AutoHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
export const event = new EventHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
export const script = new ScriptHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
|
||||
// const enti = await hacore.getLights();
|
||||
// console.log(showMore(enti), enti.length);
|
||||
|
||||
// const lightEntities = enti.filter((entity: any) => {
|
||||
// const hasLight = entity.entity_id.startsWith('light.');
|
||||
// const name = entity.attributes?.friendly_name || '';
|
||||
|
||||
// return hasLight && name.includes('次卧');
|
||||
// // return hasLight && name.includes('次卧');
|
||||
// return hasLight;
|
||||
// });
|
||||
// console.log(util.inspect(lightEntities, { depth: null }));
|
||||
|
||||
const lights = [
|
||||
{
|
||||
entity_id: 'light.lemesh_wy0c14_f18d_light',
|
||||
state: 'off',
|
||||
attributes: {
|
||||
min_color_temp_kelvin: 2700,
|
||||
max_color_temp_kelvin: 6500,
|
||||
min_mireds: 153,
|
||||
max_mireds: 370,
|
||||
effect_list: [
|
||||
'WY', 'Day',
|
||||
'Night', 'Warmth',
|
||||
'Tv', 'Reading',
|
||||
'Computer', 'Hospitality',
|
||||
'Entertainment', 'Wakeup',
|
||||
'Dusk', 'Sleep'
|
||||
],
|
||||
supported_color_modes: ['color_temp'],
|
||||
effect: null,
|
||||
color_mode: null,
|
||||
brightness: null,
|
||||
color_temp_kelvin: null,
|
||||
color_temp: null,
|
||||
hs_color: null,
|
||||
rgb_color: null,
|
||||
xy_color: null,
|
||||
'light.mode': 0,
|
||||
'light.on': false,
|
||||
'light.color_temperature': 6500,
|
||||
'light.brightness': 1,
|
||||
friendly_name: '次卧灯 灯光',
|
||||
supported_features: 4
|
||||
},
|
||||
last_changed: '2025-12-02T16:35:00.229216+00:00',
|
||||
last_reported: '2025-12-02T16:36:00.314622+00:00',
|
||||
last_updated: '2025-12-02T16:35:00.229216+00:00',
|
||||
context: {
|
||||
id: '01KBFYNN05ZYWZHTGC1W7N66Z5',
|
||||
parent_id: null,
|
||||
user_id: null
|
||||
}
|
||||
},
|
||||
{
|
||||
entity_id: 'light.lemesh_cn_1099991426_wy0c14_s_2_light',
|
||||
state: 'off',
|
||||
attributes: {
|
||||
min_color_temp_kelvin: 2700,
|
||||
max_color_temp_kelvin: 6500,
|
||||
min_mireds: 153,
|
||||
max_mireds: 370,
|
||||
effect_list: [
|
||||
'色温模式',
|
||||
'日光',
|
||||
'月光(夜间)模式',
|
||||
'温馨',
|
||||
'电视模式(影院模式)',
|
||||
'阅读模式',
|
||||
'电脑模式',
|
||||
'会客模式',
|
||||
'娱乐模式',
|
||||
'清晨唤醒',
|
||||
'黄昏明亮',
|
||||
'夜晚助眠'
|
||||
],
|
||||
supported_color_modes: ['color_temp'],
|
||||
effect: null,
|
||||
color_mode: null,
|
||||
brightness: null,
|
||||
color_temp_kelvin: null,
|
||||
color_temp: null,
|
||||
hs_color: null,
|
||||
rgb_color: null,
|
||||
xy_color: null,
|
||||
friendly_name: '次卧灯 灯光',
|
||||
supported_features: 4
|
||||
},
|
||||
last_changed: '2025-12-04T13:28:05.284635+00:00',
|
||||
last_reported: '2025-12-04T13:28:09.331178+00:00',
|
||||
last_updated: '2025-12-04T13:28:05.284635+00:00',
|
||||
context: {
|
||||
id: '01KBMRRTX4ZE10MGHTVVNC1K7Y',
|
||||
parent_id: null,
|
||||
user_id: null
|
||||
}
|
||||
}
|
||||
]
|
||||
// console.log(showMore(lightEntities));
|
||||
|
||||
const res = await hacore.post({
|
||||
url: '/api/services/light/turn_off',
|
||||
body: {
|
||||
entity_id: 'light.lemesh_cn_1099991426_wy0c14_s_2_light' // 或第二个次卧灯的ID
|
||||
}
|
||||
});
|
||||
console.log(util.inspect(res, { depth: null }));
|
||||
// const infoList = await hacore.getInfoList();
|
||||
// console.log(showMore(infoList));
|
||||
|
||||
// const lights = [
|
||||
// {
|
||||
// entity_id: 'light.lemesh_wy0c14_f18d_light',
|
||||
// state: 'off',
|
||||
// attributes: {
|
||||
// min_color_temp_kelvin: 2700,
|
||||
// max_color_temp_kelvin: 6500,
|
||||
// min_mireds: 153,
|
||||
// max_mireds: 370,
|
||||
// effect_list: [
|
||||
// 'WY', 'Day',
|
||||
// 'Night', 'Warmth',
|
||||
// 'Tv', 'Reading',
|
||||
// 'Computer', 'Hospitality',
|
||||
// 'Entertainment', 'Wakeup',
|
||||
// 'Dusk', 'Sleep'
|
||||
// ],
|
||||
// supported_color_modes: ['color_temp'],
|
||||
// effect: null,
|
||||
// color_mode: null,
|
||||
// brightness: null,
|
||||
// color_temp_kelvin: null,
|
||||
// color_temp: null,
|
||||
// hs_color: null,
|
||||
// rgb_color: null,
|
||||
// xy_color: null,
|
||||
// 'light.mode': 0,
|
||||
// 'light.on': false,
|
||||
// 'light.color_temperature': 6500,
|
||||
// 'light.brightness': 1,
|
||||
// friendly_name: '次卧灯 灯光',
|
||||
// supported_features: 4
|
||||
// },
|
||||
// last_changed: '2025-12-02T16:35:00.229216+00:00',
|
||||
// last_reported: '2025-12-02T16:36:00.314622+00:00',
|
||||
// last_updated: '2025-12-02T16:35:00.229216+00:00',
|
||||
// context: {
|
||||
// id: '01KBFYNN05ZYWZHTGC1W7N66Z5',
|
||||
// parent_id: null,
|
||||
// user_id: null
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// entity_id: 'light.lemesh_cn_1099991426_wy0c14_s_2_light',
|
||||
// state: 'off',
|
||||
// attributes: {
|
||||
// min_color_temp_kelvin: 2700,
|
||||
// max_color_temp_kelvin: 6500,
|
||||
// min_mireds: 153,
|
||||
// max_mireds: 370,
|
||||
// effect_list: [
|
||||
// '色温模式',
|
||||
// '日光',
|
||||
// '月光(夜间)模式',
|
||||
// '温馨',
|
||||
// '电视模式(影院模式)',
|
||||
// '阅读模式',
|
||||
// '电脑模式',
|
||||
// '会客模式',
|
||||
// '娱乐模式',
|
||||
// '清晨唤醒',
|
||||
// '黄昏明亮',
|
||||
// '夜晚助眠'
|
||||
// ],
|
||||
// supported_color_modes: ['color_temp'],
|
||||
// effect: null,
|
||||
// color_mode: null,
|
||||
// brightness: null,
|
||||
// color_temp_kelvin: null,
|
||||
// color_temp: null,
|
||||
// hs_color: null,
|
||||
// rgb_color: null,
|
||||
// xy_color: null,
|
||||
// friendly_name: '次卧灯 灯光',
|
||||
// supported_features: 4
|
||||
// },
|
||||
// last_changed: '2025-12-04T13:28:05.284635+00:00',
|
||||
// last_reported: '2025-12-04T13:28:09.331178+00:00',
|
||||
// last_updated: '2025-12-04T13:28:05.284635+00:00',
|
||||
// context: {
|
||||
// id: '01KBMRRTX4ZE10MGHTVVNC1K7Y',
|
||||
// parent_id: null,
|
||||
// user_id: null
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
|
||||
// const res = await hacore.toggleLight({
|
||||
// // name: '次卧灯',
|
||||
// // service: 'turn_off'
|
||||
// name: '阳台灯'
|
||||
// });
|
||||
// console.log(util.inspect(res, { depth: null }));
|
||||
|
||||
// const entityType = await hacore.getEntityTypes();
|
||||
// console.log(showMore(entityType));
|
||||
19
test/light.ts
Normal file
19
test/light.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { hacore, showMore } from "./common.ts";
|
||||
import Fuse from 'fuse.js';
|
||||
|
||||
const devices = await hacore.getInfoList();
|
||||
const fuse = new Fuse(devices, {
|
||||
keys: ['name'], // 搜索字段
|
||||
threshold: 0.4, // 匹配宽松度:0~1,越小越严格
|
||||
includeScore: true,
|
||||
minMatchCharLength: 1, // 允许单字匹配
|
||||
});
|
||||
// const searchKeyword = '次卧灯';
|
||||
// const searchKeyword = '阳台 灯';
|
||||
// const searchKeyword = '晾衣机的 灯';
|
||||
const searchKeyword = ' 阳台 灯';
|
||||
const result = fuse.search(searchKeyword);
|
||||
|
||||
// 输出搜索结果
|
||||
console.log(`搜索关键词: "${searchKeyword}"`);
|
||||
console.log(showMore(result.map(r => r.item)));
|
||||
16
test/script.ts
Normal file
16
test/script.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { script, showMore } from './common.ts';
|
||||
|
||||
const scripts = await script.getScripts();
|
||||
|
||||
const values = scripts.map(e => {
|
||||
return {
|
||||
entity_id: e.entity_id,
|
||||
state: e.state,
|
||||
attributes: e.attributes,
|
||||
last_changed: e.last_changed,
|
||||
last_updated: e.last_updated,
|
||||
};
|
||||
});
|
||||
console.log(showMore(values));
|
||||
|
||||
console.log(`实体数量: ${scripts.length}`);
|
||||
Reference in New Issue
Block a user