Skip to content

Commit

Permalink
Release v2024.10.18
Browse files Browse the repository at this point in the history
  • Loading branch information
KNOOP committed Oct 18, 2024
0 parents commit 1aaf426
Show file tree
Hide file tree
Showing 13 changed files with 1,408 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
235 changes: 235 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@

# 智谱清言 AI Home Assistant 🏡
![GitHub Version](https://img.shields.io/github/v/release/knoop7/zhipuai) ![GitHub Issues](https://img.shields.io/github/issues/knoop7/zhipuai) ![GitHub Forks](https://img.shields.io/github/forks/knoop7/zhipuai?style=social) ![GitHub Stars](https://img.shields.io/github/stars/knoop7/zhipuai?style=social)

<img src="https://github.com/user-attachments/assets/f8ff7a6c-4449-496a-889a-d205469a84df" alt="image" width="700" height="400">

---
## 通知:本项目未经允许严禁商用,你可以隐晦但不能作为盈利手段,未经允许禁止发布到小红书、BilBil,若有发现一律停止更新。

### 📦 安装步骤

#### 1. HACS 添加自定义存储库
在 Home Assistant 的 HACS 中,点击右上角的三个点,选择“自定义存储库”,并添加以下 URL:
```
https://github.com/knoop7/zhipuai
```

#### 2. 添加智谱清言集成
进入 Home Assistant 的“集成”页面,搜索并添加“智谱清言”。

#### 3. 配置 Key 🔑
在配置页面中,你可以通过手机号登录获取 Key。获取后,直接填写 Key 使用,不需要进行额外验证。
**注意**:建议你新建一个 Key,避免使用系统默认的 Key。

#### 4. 免费模型使用 💡
智谱清言默认选择了免费模型,完全免费,不用担心收费。如果你有兴趣,还可以选择其他付费模型来体验更丰富的功能。

#### 5. 版本兼容性 📅
请确保 Home Assistant 的版本不低于 8.0,因为智谱清言主要针对最新版本开发。如果遇到无法识别的实体问题,建议重启系统或更新至最新版本。

---

### 🛠 模型指令使用示例
为了保证大家能使用舒畅,并且不出任何bug可以使用我的模版指令进行尝试

````
作为 Home Assistant 的智能家居管理者,你的名字叫“自定义”,我将为您提供智能家居信息和问题的解答。请查看以下可用设备、状态及操作示例。
### 可用设备展示
# 注意如果实体超过1000以上
# 直接删掉这句话
# ```csv
# entity_id,name,state
# {% for entity in states -%}
# {{ entity.entity_id }},{{ entity.name }},
# {{ entity.state }},
# {% endfor -%}
#```
### 逻辑修复和执行约束
1. **状态检查**:确保设备状态有变化时才执行命令,避免重复操作。
2. **过滤不必要的命令**:`HassTurnOff`、`HassTurnOn`等冗余命令不再生成,直接使用 `execute_services` 函数。
3. **简化用户操作**:在响应中只返回必要信息,减少多余内容。
### 检查避免重复执行
在执行服务时先检查当前状态,确保设备在目标状态时不会重复执行。例如:
```jinja
{% if states('light.living_room') != 'on' %}
{
"domain": "light",
"service": "turn_on",
"service_data": {
"entity_id": "light.living_room"
}
}
{% endif %}
```
### 今日油价:
```yaml
{% set sensor = 油价实体 %}
Sensor: {{ sensor.name }}
State: {{ sensor.state }}
Attributes:
{% for attribute, value in sensor.attributes.items() %}
{{ attribute }}: {{ value }}
{% endfor %}
```
### 电费余额信息:
```yaml
{% set balance_sensor = 电费实体 %}
{% if balance_sensor %}
当前余额: {{ balance_sensor.state }} {{ balance_sensor.attributes.unit_of_measurement }}
{% endif %}
```
### Tasmota能源消耗:
```yaml
{% set today_sensor = states.sensor.tasmota_energy_today %}
{% set yesterday_sensor = states.sensor.tasmota_energy_yesterday %}
{% if today_sensor is not none and yesterday_sensor is not none %}
今日消耗: {{ today_sensor.state }} {{ today_sensor.attributes.unit_of_measurement }}
昨日消耗: {{ yesterday_sensor.state }} {{ yesterday_sensor.attributes.unit_of_measurement }}
{% endif %}
```
### 此时天气:
```json
{% set entity_id = '天气实体' %}
{% set entity = states[entity_id] %}
{
"state": "{{ entity.state }}",
"attributes": {
{% for attr in entity.attributes %}
{% if attr not in ['hourly_temperature', 'hourly_skycon', 'hourly_cloudrate', 'hourly_precipitation'] %}
"{{ attr }}": "{{ entity.attributes[attr] }}"{% if not loop.last %},{% endif %}
{% endif %}
{% endfor %}
}
}
````

或者这个模版指令
````
### 可用设备展示
```csv
entity_id,name,state,category
{%- for entity in states if 'automation.' not in entity.entity_id and entity.state not in ['unknown'] and not ('device_tracker.' in entity.entity_id and ('huawei' in entity.entity_id or 'Samsung' in entity.entity_id)) and 'iphone' not in entity.entity_id and 'daily_english' not in entity.entity_id and 'lenovo' not in entity.entity_id and 'time' not in entity.entity_id and 'zone' not in entity.entity_id and 'n1' not in entity.entity_id and 'z470' not in entity.entity_id and 'lao_huang' not in entity.entity_id and 'lao_huang_li' not in entity.entity_id and 'input_text' not in entity.entity_id and 'conversation' not in entity.entity_id and 'camera' not in entity.entity_id and 'update' not in entity.entity_id and 'IPhone' not in entity.entity_id and 'mac' not in entity.entity_id and 'macmini' not in entity.entity_id and 'macbook' not in entity.entity_id and 'ups' not in entity.entity_id and 'OPENWRT' not in entity.entity_id and 'OPENWRT' not in entity.entity_id%}
{%- set category = '其他' %}
{%- if 'light.' in entity.entity_id %}{% set category = '灯' %}
{%- elif 'sensor.' in entity.entity_id and 'battery' in entity.entity_id %}
{% set category = '电池' %}
{%- elif 'sensor.' in entity.entity_id and 'sun' in entity.entity_id %}
{% set category = '太阳' %}
{%- elif 'sensor.' in entity.entity_id and ('motion' in entity.entity_id or 'presence' in entity.entity_id) %}
{% set category = '人体存在' %}
{%- elif 'sensor.' in entity.entity_id and ('motion' in entity.entity_id or 'presence' in entity.entity_id) %}
{% set category = '人体存在' %}
{%- elif 'climate.' in entity.entity_id %}{% set category = '空调' %}
{%- elif 'media_player.' in entity.entity_id %}{% set category = '媒体播放器' %}
{%- elif 'cover.' in entity.entity_id %}{% set category = '门窗' %}
{%- elif 'lock.' in entity.entity_id %}{% set category = '门锁' %}
{%- elif 'switch.' in entity.entity_id %}{% set category = '开关' %}
{%- elif 'sensor.' in entity.entity_id %}{% set category = '传感器' %}
{%- elif 'watering.' in entity.entity_id %}{% set category = '浇花器' %}
{%- elif 'fan.' in entity.entity_id %}{% set category = '风扇' %}
{%- elif 'air_quality.' in entity.entity_id %}{% set category = '空气质量' %}
{%- elif 'vacuum.' in entity.entity_id %}{% set category = '扫地机器人' %}
{%- elif 'person.' in entity.entity_id %}{% set category = '人员' %}
{%- elif 'binary_sensor.' in entity.entity_id and ('door' in entity.entity_id or 'window' in entity.entity_id) %}{% set category = '门窗' %}
{%- elif 'gas.' in entity.entity_id %}{% set category = '天然气' %}
{%- elif 'energy.' in entity.entity_id %}{% set category = '用电量' %}
{%- elif 'script.' in entity.entity_id %}{% set category = '脚本' %}
{%- elif 'scene.' in entity.entity_id %}{% set category = '场景' %}
{%- endif %}
{{- entity.entity_id }},{{ entity.name }},{{ entity.state }},{{ category }}
{%- endfor %}
````

---

### 使用内置 API 公开实体 🌐
你可以使用智谱清言内置的 API 来公开实体,并为其设置别名。通过重新命名实体,你可以避免使用系统默认名称造成的混乱,提升管理效率。

---

### 🚀 使用指南

1. **访问界面**
打开 Home Assistant 仪表板,找到“智谱清言”集成卡片或对应的集成页面。

2. **输入指令**
在集成页面或对话框中,输入自然语言指令,或使用语音助手下达命令。

3. **查看响应**
系统会根据你的指令执行任务,设备状态变化将实时显示并反馈。

4. **探索功能**
你可以尝试不同的指令来控制家中的智能设备,或查询相关状态。

---

### 📑 常用指令示例

- "打开客厅灯"
- "将卧室温度调到 22 度"
- "播放音乐"
- "明早 7 点提醒我备忘"
- "检查门锁状态"
- "看看全屋温度湿度“

---

### 🛠 Bug 处理
如果你在使用过程中遇到持续的 Python 错误,建议重启对话框并重新加载环境。这样可以解决一些潜在的代码问题。

---

### 🗂 处理不被 Home Assistant 认可的实体
如果 Home Assistant 中存在不被认可的实体,你可以将这些实体剔除出自动化控制的范围。通过在指令中添加 Jinja2 模板,可以有效避免 Python 的错误提示,杜绝潜在问题。

---

### 额外提示

- **系统版本要求**:智谱清言需要 Home Assistant 至少 8.0 版本支持。
- **建议**:如果遇到兼容性问题,建议重启或更新系统。通常这能解决大多数问题。
- **相关项目** 如果需要语音转文字可以使用免费在线AI模型集成,个人二次深度修改 ````https://github.com/knoop7/groqcloud_whisper````


---

### 📊 实时状态

#### 当前时间:16:09:23,今日日期:2024-10-12。

#### 油价信息 ⛽
- 92号汽油:7元/升
- 95号汽油:7元/升
- 98号汽油:8元/升
预计下次油价调整时间为10月23日24时,油价可能继续上涨。

#### 电费余额 ⚡
- 当前余额:27.5元

#### 今日能源消耗 💡
- 今日消耗:4033.0 Wh
- 昨日消耗:7.558 kWh

#### 今日新闻摘要 📰
1. 民政部发布全国老年人口数据。
Binary file added custom_components/.DS_Store
Binary file not shown.
76 changes: 76 additions & 0 deletions custom_components/zhipuai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from __future__ import annotations
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import DOMAIN, LOGGER
from .service_caller import get_service_caller

PLATFORMS: list[Platform] = [Platform.CONVERSATION]

class ZhipuAIConfigEntry:
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry):
self.hass = hass
self.config_entry = config_entry
self.api_key = config_entry.data[CONF_API_KEY]
self.options = config_entry.options
self._unsub_options_update_listener = None
self._cleanup_callbacks = []
self.service_caller = get_service_caller(hass)

@property
def entry_id(self):
return self.config_entry.entry_id

@property
def title(self):
return self.config_entry.title

async def async_setup(self) -> None:
self._unsub_options_update_listener = self.config_entry.add_update_listener(
self.async_options_updated
)

async def async_unload(self) -> None:
if self._unsub_options_update_listener is not None:
self._unsub_options_update_listener()
self._unsub_options_update_listener = None
for cleanup_callback in self._cleanup_callbacks:
cleanup_callback()
self._cleanup_callbacks.clear()

def async_on_unload(self, func):
self._cleanup_callbacks.append(func)

@callback
async def async_options_updated(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
self.options = entry.options
async_dispatcher_send(hass, f"{DOMAIN}_options_updated", entry)

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {})
try:
zhipuai_entry = ZhipuAIConfigEntry(hass, entry)
await zhipuai_entry.async_setup()
hass.data[DOMAIN][entry.entry_id] = zhipuai_entry
LOGGER.info("成功设置, 条目 ID: %s", entry.entry_id)
except Exception as ex:
LOGGER.error("设置 AI 时出错: %s", ex)
raise ConfigEntryNotReady from ex

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
zhipuai_entry = hass.data[DOMAIN].get(entry.entry_id)
if zhipuai_entry is None:
return True

if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
await zhipuai_entry.async_unload()
hass.data[DOMAIN].pop(entry.entry_id, None)
LOGGER.info("已卸载 AI 条目,ID: %s", entry.entry_id)

return unload_ok
23 changes: 23 additions & 0 deletions custom_components/zhipuai/ai_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import aiohttp
from aiohttp import TCPConnector
from homeassistant.exceptions import HomeAssistantError
from .const import LOGGER, ZHIPUAI_URL

async def send_ai_request(api_key: str, payload: dict) -> dict:
try:
connector = TCPConnector(ssl=False)
async with aiohttp.ClientSession(connector=connector) as session:
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}

async with session.post(ZHIPUAI_URL, json=payload, headers=headers) as response:
if response.status != 200:
raise HomeAssistantError(f"AI 返回状态 {response.status}")
result = await response.json()
return result

except Exception as err:
LOGGER.error(f"与 AI 通信时出错: {err}")
raise HomeAssistantError(f"与 AI 通信时出错: {err}")
Loading

0 comments on commit 1aaf426

Please sign in to comment.