update
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
{
|
||||
"name": "@kevisual/ha-api",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.6",
|
||||
"description": "",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"app": {
|
||||
"type": "pm2-system-app",
|
||||
"entry": "src/index.ts"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
|
||||
21
readme.md
21
readme.md
@@ -1,4 +1,4 @@
|
||||
# 灯光管理
|
||||
## 灯光管理
|
||||
|
||||
该模块提供对Home Assistant中灯光设备的管理功能,包括获取灯光列表、搜索特定灯光设备以及控制灯光的开关状态。
|
||||
|
||||
@@ -25,3 +25,22 @@ if(searchResult.hasMore) {
|
||||
console.log('没有找到匹配的灯光设备。');
|
||||
}
|
||||
```
|
||||
|
||||
## 音箱管理
|
||||
|
||||
该模块提供对Home Assistant中音箱设备的管理功能,执行文本指令等。
|
||||
|
||||
```ts
|
||||
import { TextHA } from '@kevisual/ha-api';
|
||||
|
||||
const tts = new TextHA({
|
||||
host: 'http://your-home-assistant:8123',
|
||||
token: 'your-long-lived-access-token',
|
||||
});
|
||||
// 获取所有音箱设备
|
||||
const entities = await text.getSpeakerEntities();
|
||||
// 执行文本指令
|
||||
const res2 = await text.executeTextDirective('text.xiaomi_lx06_9e08_execute_text_directive', '关闭阳台灯');
|
||||
console.log(res2);
|
||||
```
|
||||
|
||||
|
||||
12
src/core.ts
12
src/core.ts
@@ -4,6 +4,7 @@ export type HACoreOptions = {
|
||||
token: string;
|
||||
homeassistantURL?: string;
|
||||
ttl?: number;
|
||||
ha?: HACore;
|
||||
}
|
||||
/**
|
||||
* https://developers.home-assistant.io/docs/api/rest/
|
||||
@@ -14,7 +15,10 @@ export class HACore {
|
||||
static serviceName = '';
|
||||
cache: LRUStorage;
|
||||
constructor(options: HACoreOptions) {
|
||||
this.token = options?.token;
|
||||
this.token = options?.token!;
|
||||
if (!this.token && options.ha) {
|
||||
this.token = options.ha?.token;
|
||||
}
|
||||
this.homeassistantURL = options?.homeassistantURL || 'http://localhost:8123';
|
||||
this.cache = new LRUStorage({ max: 200, ttl: options?.ttl || 1000 * 60 * 30 }); // 30分钟缓存
|
||||
}
|
||||
@@ -91,9 +95,9 @@ export class HACore {
|
||||
});
|
||||
return infoList;
|
||||
}
|
||||
async runService(opts: { entity_id?: string, name?: string, service?: string, data?: Record<string, any> }) {
|
||||
async runService(opts: { entity_id?: string, name?: string, serverName?: string, service?: string, data?: Record<string, any> }) {
|
||||
// e.g., service: 'turn_on', 'turn_off', 'toggle'
|
||||
const serviceName = (this.constructor as typeof HACore).serviceName;
|
||||
const serviceName = opts?.serverName || (this.constructor as typeof HACore).serviceName;
|
||||
let { entity_id, service = '', data } = opts;
|
||||
if (!entity_id && opts.name) {
|
||||
const entities = await this.getServiceEntities();
|
||||
@@ -156,7 +160,7 @@ export const entitiesTypes = [
|
||||
{ "type": "number", "desc": "可调整的数值控件,有上下限,如温度设定、定时器" }
|
||||
]
|
||||
|
||||
type EntityItem = {
|
||||
export type EntityItem = {
|
||||
entity_id: string;
|
||||
attributes: {
|
||||
friendly_name?: string;
|
||||
|
||||
46
src/light.ts
46
src/light.ts
@@ -1,5 +1,5 @@
|
||||
import Fuse from "fuse.js";
|
||||
import { HACore, HACoreOptions, InfoItem } from "./core.ts";
|
||||
import { HACore, HACoreOptions, InfoItem, EntityItem } from "./core.ts";
|
||||
export class LightHA extends HACore {
|
||||
static serviceName = 'light';
|
||||
constructor(options: HACoreOptions) {
|
||||
@@ -60,3 +60,47 @@ export class ButtonHA extends HACore {
|
||||
super(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class SpeakerHA extends HACore {
|
||||
static serviceName = 'notify';
|
||||
constructor(options: HACoreOptions) {
|
||||
super(options);
|
||||
}
|
||||
/**
|
||||
* 获取音箱实体列表
|
||||
* @returns
|
||||
*/
|
||||
getSpeakerEntities(): Promise<EntityItem[]> {
|
||||
return this.getEntities((entity: EntityItem) => entity.entity_id.startsWith(`notify.`) && entity.attributes?.friendly_name?.includes?.('音箱'));
|
||||
}
|
||||
}
|
||||
|
||||
export class TextHA extends HACore {
|
||||
static serviceName = 'text';
|
||||
constructor(options: HACoreOptions) {
|
||||
super(options);
|
||||
}
|
||||
/**
|
||||
* 获取音箱实体列表
|
||||
* @returns
|
||||
*/
|
||||
getSpeakerEntities(): Promise<EntityItem[]> {
|
||||
return this.getEntities((entity: EntityItem) => entity.entity_id.startsWith(`text.`) && entity.attributes?.friendly_name?.includes?.('音箱'));
|
||||
}
|
||||
/**
|
||||
* 执行文本指令
|
||||
* @param entity_id
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
executeTextDirective(entity_id: string, value: string): Promise<any> {
|
||||
return this.runService({
|
||||
entity_id,
|
||||
service: 'set_value',
|
||||
data: {
|
||||
value
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LightHA, AutoHA, EventHA, ScriptHA, ButtonHA } from "../src/index.ts";
|
||||
import { LightHA, AutoHA, EventHA, ScriptHA, ButtonHA, HACore, SpeakerHA, TextHA } from "../src/index.ts";
|
||||
|
||||
import util from 'node:util';
|
||||
import dotenv from 'dotenv';
|
||||
@@ -7,13 +7,15 @@ 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 });
|
||||
export const hacore = new HACore({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
export const light = new LightHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
|
||||
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 });
|
||||
export const button = new ButtonHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
|
||||
export const speaker = new SpeakerHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
export const text = new TextHA({ token: process.env.HAAS_TOKEN || '', homeassistantURL: process.env.HAAS_URL });
|
||||
// const enti = await hacore.getEntities((item) => item.attributes?.friendly_name?.includes?.('电视'));
|
||||
// console.log(showMore(enti), enti.length);
|
||||
|
||||
|
||||
27
test/speaker.ts
Normal file
27
test/speaker.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { speaker, showMore, text } from './common.ts';
|
||||
|
||||
// const entities = await speaker.getSpeakerEntities();
|
||||
const entities = await text.getSpeakerEntities();
|
||||
|
||||
|
||||
|
||||
console.log(showMore(entities));
|
||||
|
||||
console.log(`实体数量: ${entities.length}`);
|
||||
|
||||
// const res = await speaker.runService({
|
||||
// entity_id: 'text.xiaomi_lx06_9e08_execute_text_directive',
|
||||
// service: 'set_value',
|
||||
// serverName: 'text',
|
||||
// data: {
|
||||
// value: '关闭阳台灯'
|
||||
// }
|
||||
// });
|
||||
|
||||
// console.log(showMore(res));
|
||||
|
||||
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 }
|
||||
Reference in New Issue
Block a user