mijiaAPI 4.1.2__tar.gz → 4.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/PKG-INFO +108 -108
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/README.md +1 -1
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/__main__.py +117 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/devices.py +26 -14
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/mcp_server.py +11 -4
- mijiaapi-4.2.0/mijiaAPI/version.py +1 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/setup.cfg +4 -4
- mijiaapi-4.1.2/mijiaAPI/version.py +0 -1
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/.gitignore +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/LICENSE +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/MANIFEST.in +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/__init__.py +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/apis.py +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/errors.py +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/logger.py +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI/miutils.py +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/mijiaAPI.egg-info/SOURCES.txt +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/pyproject.toml +0 -0
- {mijiaapi-4.1.2 → mijiaapi-4.2.0}/uv.lock +0 -0
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: mijiaAPI
|
|
3
|
-
Version: 4.
|
|
4
|
-
Summary: A Python API for Xiaomi Mijia
|
|
5
|
-
Author-email: Do1e <i@do1e.cn>
|
|
6
|
-
License-Expression: GPL-3.0-or-later
|
|
7
|
-
Project-URL: Homepage, https://mijia-api.do1e.com/
|
|
8
|
-
Project-URL: Repository, https://github.com/Do1e/mijia-api
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: <4.0,>=3.10
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: fastmcp>=3.4.2
|
|
15
|
-
Requires-Dist: pillow>=11.3.0
|
|
16
|
-
Requires-Dist: pycryptodome>=3.23.0
|
|
17
|
-
Requires-Dist: qrcode>=8.2
|
|
18
|
-
Requires-Dist: requests>=2.32.5
|
|
19
|
-
Requires-Dist: tzlocal>=5.3.1
|
|
20
|
-
Dynamic: license-file
|
|
21
|
-
|
|
22
|
-
# mijiaAPI
|
|
23
|
-
|
|
24
|
-
米家 API,可以使用代码、CLI、MCP 直接控制米家设备。
|
|
25
|
-
|
|
26
|
-
> 🎉 **v4.0.0 版本已支持 MCP**,详见 [MCP 使用文档](https://mijia-api.do1e.com/usage/mcp)
|
|
27
|
-
> 🎉 **v4.1.0 版本已支持 Agent Skill**,详见 [Agent Skill 使用文档](https://mijia-api.do1e.com/usage/skill)
|
|
28
|
-
|
|
29
|
-
[](https://github.com/Do1e/mijia-api)
|
|
30
|
-
[](https://pypi.org/project/mijiaAPI/)
|
|
31
|
-
[](https://opensource.org/licenses/GPL-3.0)
|
|
32
|
-
|
|
33
|
-
📖 **完整文档请见 [mijia-api.do1e.com](https://mijia-api.do1e.com)**
|
|
34
|
-
|
|
35
|
-
[常见问题](https://mijia-api.do1e.com/faq) | [更新日志](https://mijia-api.do1e.com/changelog)
|
|
36
|
-
|
|
37
|
-
## 安装
|
|
38
|
-
|
|
39
|
-
> 要求 Python >= 3.10
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
pip install mijiaAPI
|
|
43
|
-
# Or `uv add mijiaAPI` for uv users
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
其他安装方式(源码安装、AUR)请参考[文档](https://mijia-api.do1e.com/guide/installation)。
|
|
47
|
-
|
|
48
|
-
## 快速开始
|
|
49
|
-
|
|
50
|
-
```python
|
|
51
|
-
from mijiaAPI import mijiaAPI, mijiaDevice
|
|
52
|
-
|
|
53
|
-
# 初始化并扫码登录(认证文件默认保存在 ~/.config/mijia-api/auth.json)
|
|
54
|
-
api = mijiaAPI()
|
|
55
|
-
api.login()
|
|
56
|
-
|
|
57
|
-
# 通过设备名称控制设备(推荐)
|
|
58
|
-
device = mijiaDevice(api, dev_name="我的台灯")
|
|
59
|
-
device.on = True # 打开设备
|
|
60
|
-
device.brightness = 60 # 设置亮度为 60%
|
|
61
|
-
|
|
62
|
-
# 查看设备支持的所有属性和动作
|
|
63
|
-
print(device)
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
CLI 用法:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
mijiaAPI login # 扫码登录
|
|
70
|
-
mijiaAPI -l # 列出所有设备
|
|
71
|
-
mijiaAPI set --dev_name "台灯" --prop_name "brightness" --value 60
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
MCP 用法:
|
|
75
|
-
|
|
76
|
-
执行 `uvx mijiaAPI login -p /path/to/auth.json` 登录后,在 MCP 客户端配置中添加以下内容即可接入米家:
|
|
77
|
-
|
|
78
|
-
```json
|
|
79
|
-
{
|
|
80
|
-
"mcpServers": {
|
|
81
|
-
"mijia-api": {
|
|
82
|
-
"command": "uvx",
|
|
83
|
-
"args": ["mijiaAPI", "mcp", "-p", "/path/to/auth.json"]
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
更多用法(API 基础调用、MCP Server、CLI 完整参数、最佳实践等)请查阅[完整文档](https://mijia-api.do1e.com)。
|
|
90
|
-
|
|
91
|
-
## 致谢
|
|
92
|
-
|
|
93
|
-
* [janzlan/mijia-api](https://gitee.com/janzlan/mijia-api/tree/master)
|
|
94
|
-
* [米家 APP 网络请求的抓包、加解密与构造的代码笔记](https://imkero.net/posts/mihome-app-api/)
|
|
95
|
-
* [al-one/hass-xiaomi-miot](https://github.com/al-one/hass-xiaomi-miot)
|
|
96
|
-
|
|
97
|
-
## 开源许可
|
|
98
|
-
|
|
99
|
-
本项目采用 [GPL-3.0](LICENSE) 开源许可证。
|
|
100
|
-
|
|
101
|
-
**请注意:GPL-3.0 是具有“强传染性”的开源许可证。**
|
|
102
|
-
如果您在您的项目中使用、修改或分发本项目的代码(包括作为库依赖),您的整个项目也**必须**以 GPL-3.0 或兼容许可证开源发布。
|
|
103
|
-
|
|
104
|
-
## 免责声明
|
|
105
|
-
|
|
106
|
-
* 本项目仅供学习交流使用,不得用于商业用途,如有侵权请联系删除
|
|
107
|
-
* 用户使用本项目所产生的任何后果,需自行承担风险
|
|
108
|
-
* 开发者不对使用本项目产生的任何直接或间接损失负责
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mijiaAPI
|
|
3
|
+
Version: 4.2.0
|
|
4
|
+
Summary: A Python API for Xiaomi Mijia
|
|
5
|
+
Author-email: Do1e <i@do1e.cn>
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://mijia-api.do1e.com/
|
|
8
|
+
Project-URL: Repository, https://github.com/Do1e/mijia-api
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: <4.0,>=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: fastmcp>=3.4.2
|
|
15
|
+
Requires-Dist: pillow>=11.3.0
|
|
16
|
+
Requires-Dist: pycryptodome>=3.23.0
|
|
17
|
+
Requires-Dist: qrcode>=8.2
|
|
18
|
+
Requires-Dist: requests>=2.32.5
|
|
19
|
+
Requires-Dist: tzlocal>=5.3.1
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# mijiaAPI
|
|
23
|
+
|
|
24
|
+
米家 API,可以使用代码、CLI、MCP 直接控制米家设备。
|
|
25
|
+
|
|
26
|
+
> 🎉 **v4.0.0 版本已支持 MCP**,详见 [MCP 使用文档](https://mijia-api.do1e.com/usage/mcp)
|
|
27
|
+
> 🎉 **v4.1.0 版本已支持 Agent Skill**,详见 [Agent Skill 使用文档](https://mijia-api.do1e.com/usage/skill)
|
|
28
|
+
|
|
29
|
+
[](https://github.com/Do1e/mijia-api)
|
|
30
|
+
[](https://pypi.org/project/mijiaAPI/)
|
|
31
|
+
[](https://opensource.org/licenses/GPL-3.0)
|
|
32
|
+
|
|
33
|
+
📖 **完整文档请见 [mijia-api.do1e.com](https://mijia-api.do1e.com)**
|
|
34
|
+
|
|
35
|
+
[常见问题](https://mijia-api.do1e.com/faq) | [更新日志](https://mijia-api.do1e.com/changelog)
|
|
36
|
+
|
|
37
|
+
## 安装
|
|
38
|
+
|
|
39
|
+
> 要求 Python >= 3.10
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install mijiaAPI
|
|
43
|
+
# Or `uv add mijiaAPI` for uv users
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
其他安装方式(源码安装、AUR)请参考[文档](https://mijia-api.do1e.com/guide/installation)。
|
|
47
|
+
|
|
48
|
+
## 快速开始
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from mijiaAPI import mijiaAPI, mijiaDevice
|
|
52
|
+
|
|
53
|
+
# 初始化并扫码登录(认证文件默认保存在 ~/.config/mijia-api/auth.json)
|
|
54
|
+
api = mijiaAPI()
|
|
55
|
+
api.login()
|
|
56
|
+
|
|
57
|
+
# 通过设备名称控制设备(推荐)
|
|
58
|
+
device = mijiaDevice(api, dev_name="我的台灯")
|
|
59
|
+
device.on = True # 打开设备
|
|
60
|
+
device.brightness = 60 # 设置亮度为 60%
|
|
61
|
+
|
|
62
|
+
# 查看设备支持的所有属性和动作
|
|
63
|
+
print(device)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
CLI 用法:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
mijiaAPI login # 扫码登录
|
|
70
|
+
mijiaAPI -l # 列出所有设备
|
|
71
|
+
mijiaAPI set --dev_name "台灯" --prop_name "brightness" --value 60
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
MCP 用法:
|
|
75
|
+
|
|
76
|
+
执行 `uvx mijiaAPI login -p /path/to/auth.json` 登录后,在 MCP 客户端配置中添加以下内容即可接入米家:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"mijia-api": {
|
|
82
|
+
"command": "uvx",
|
|
83
|
+
"args": ["mijiaAPI", "mcp", "-p", "/path/to/auth.json"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
更多用法(API 基础调用、MCP Server、CLI 完整参数、最佳实践等)请查阅[完整文档](https://mijia-api.do1e.com)。
|
|
90
|
+
|
|
91
|
+
## 致谢
|
|
92
|
+
|
|
93
|
+
* [janzlan/mijia-api](https://gitee.com/janzlan/mijia-api/tree/master)
|
|
94
|
+
* [米家 APP 网络请求的抓包、加解密与构造的代码笔记](https://imkero.net/posts/mihome-app-api/)
|
|
95
|
+
* [al-one/hass-xiaomi-miot](https://github.com/al-one/hass-xiaomi-miot)
|
|
96
|
+
|
|
97
|
+
## 开源许可
|
|
98
|
+
|
|
99
|
+
本项目采用 [GPL-3.0](LICENSE) 开源许可证。
|
|
100
|
+
|
|
101
|
+
**请注意:GPL-3.0 是具有“强传染性”的开源许可证。**
|
|
102
|
+
如果您在您的项目中使用、修改或分发本项目的代码(包括作为库依赖),您的整个项目也**必须**以 GPL-3.0 或兼容许可证开源发布。
|
|
103
|
+
|
|
104
|
+
## 免责声明
|
|
105
|
+
|
|
106
|
+
* 本项目仅供学习交流使用,不得用于商业用途,如有侵权请联系删除
|
|
107
|
+
* 用户使用本项目所产生的任何后果,需自行承担风险
|
|
108
|
+
* 开发者不对使用本项目产生的任何直接或间接损失负责
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
米家 API,可以使用代码、CLI、MCP 直接控制米家设备。
|
|
4
4
|
|
|
5
|
-
> 🎉 **v4.0.0 版本已支持 MCP**,详见 [MCP 使用文档](https://mijia-api.do1e.com/usage/mcp)
|
|
5
|
+
> 🎉 **v4.0.0 版本已支持 MCP**,详见 [MCP 使用文档](https://mijia-api.do1e.com/usage/mcp)
|
|
6
6
|
> 🎉 **v4.1.0 版本已支持 Agent Skill**,详见 [Agent Skill 使用文档](https://mijia-api.do1e.com/usage/skill)
|
|
7
7
|
|
|
8
8
|
[](https://github.com/Do1e/mijia-api)
|
|
@@ -19,6 +19,17 @@ if log_level_name not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']:
|
|
|
19
19
|
log_level = getattr(logging, log_level_name, logging.INFO)
|
|
20
20
|
logging.getLogger("mijiaAPI").setLevel(log_level)
|
|
21
21
|
|
|
22
|
+
|
|
23
|
+
def json_object(value: str) -> dict:
|
|
24
|
+
try:
|
|
25
|
+
result = json.loads(value)
|
|
26
|
+
except json.JSONDecodeError as e:
|
|
27
|
+
raise argparse.ArgumentTypeError(f"无效 JSON: {e.msg}") from e
|
|
28
|
+
if not isinstance(result, dict):
|
|
29
|
+
raise argparse.ArgumentTypeError("必须是 JSON 对象")
|
|
30
|
+
return result
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
def parse_args(args):
|
|
23
34
|
parser = argparse.ArgumentParser(description=f"Mijia API CLI (v{version})")
|
|
24
35
|
subparsers = parser.add_subparsers(dest='command')
|
|
@@ -190,6 +201,87 @@ def parse_args(args):
|
|
|
190
201
|
help="需要设定的属性值",
|
|
191
202
|
required=True,
|
|
192
203
|
)
|
|
204
|
+
|
|
205
|
+
action = subparsers.add_parser(
|
|
206
|
+
'action',
|
|
207
|
+
help="执行设备动作",
|
|
208
|
+
)
|
|
209
|
+
action.set_defaults(func='action')
|
|
210
|
+
action.add_argument(
|
|
211
|
+
'-p', '--auth_path',
|
|
212
|
+
type=Path,
|
|
213
|
+
default=Path.home() / ".config" / "mijia-api" / "auth.json",
|
|
214
|
+
help="认证文件保存路径,默认保存在 ~/.config/mijia-api/auth.json",
|
|
215
|
+
)
|
|
216
|
+
action_device = action.add_mutually_exclusive_group(required=True)
|
|
217
|
+
action_device.add_argument(
|
|
218
|
+
'--did',
|
|
219
|
+
type=str,
|
|
220
|
+
help="设备did",
|
|
221
|
+
)
|
|
222
|
+
action_device.add_argument(
|
|
223
|
+
'--dev_name',
|
|
224
|
+
type=str,
|
|
225
|
+
help="设备名称,指定为米家APP中设定的名称",
|
|
226
|
+
)
|
|
227
|
+
action.add_argument(
|
|
228
|
+
'--action_name',
|
|
229
|
+
type=str,
|
|
230
|
+
help="动作名称,先使用 --get_device_info 获取",
|
|
231
|
+
required=True,
|
|
232
|
+
)
|
|
233
|
+
action.add_argument(
|
|
234
|
+
'--params',
|
|
235
|
+
type=json_object,
|
|
236
|
+
help='动作参数 JSON 对象,例如 {"value":[2]}',
|
|
237
|
+
default=None,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
statistics = subparsers.add_parser(
|
|
241
|
+
'statistics',
|
|
242
|
+
help="获取设备统计数据",
|
|
243
|
+
)
|
|
244
|
+
statistics.set_defaults(func='statistics')
|
|
245
|
+
statistics.add_argument(
|
|
246
|
+
'-p', '--auth_path',
|
|
247
|
+
type=Path,
|
|
248
|
+
default=Path.home() / ".config" / "mijia-api" / "auth.json",
|
|
249
|
+
help="认证文件保存路径,默认保存在 ~/.config/mijia-api/auth.json",
|
|
250
|
+
)
|
|
251
|
+
statistics.add_argument(
|
|
252
|
+
'--did',
|
|
253
|
+
type=str,
|
|
254
|
+
help="设备did,先使用 --list_devices 获取",
|
|
255
|
+
required=True,
|
|
256
|
+
)
|
|
257
|
+
statistics.add_argument(
|
|
258
|
+
'--key',
|
|
259
|
+
type=str,
|
|
260
|
+
help='设备相关的统计键,例如 lumi.acpartner.mcn04 的 "7.1"',
|
|
261
|
+
required=True,
|
|
262
|
+
)
|
|
263
|
+
statistics.add_argument(
|
|
264
|
+
'--data_type',
|
|
265
|
+
type=str,
|
|
266
|
+
help="统计类型,例如 stat_month_v3;旧设备可能不带 _v3",
|
|
267
|
+
required=True,
|
|
268
|
+
)
|
|
269
|
+
statistics.add_argument(
|
|
270
|
+
'--limit',
|
|
271
|
+
type=int,
|
|
272
|
+
help="返回的最大条目数,默认 6",
|
|
273
|
+
default=6,
|
|
274
|
+
)
|
|
275
|
+
statistics.add_argument(
|
|
276
|
+
'--time_start',
|
|
277
|
+
type=int,
|
|
278
|
+
help="开始时间戳(秒),默认结束时间前 30 天",
|
|
279
|
+
)
|
|
280
|
+
statistics.add_argument(
|
|
281
|
+
'--time_end',
|
|
282
|
+
type=int,
|
|
283
|
+
help="结束时间戳(秒),默认为当前时间",
|
|
284
|
+
)
|
|
193
285
|
return parser.parse_args(args)
|
|
194
286
|
|
|
195
287
|
def init_api(auth_path: Path) -> mijiaAPI:
|
|
@@ -333,6 +425,27 @@ def set(args):
|
|
|
333
425
|
return
|
|
334
426
|
print(f"{device.name} ({device.did}) 的 {args.prop_name} 值已设置为 {args.value}")
|
|
335
427
|
|
|
428
|
+
|
|
429
|
+
def run_action(api: mijiaAPI, args):
|
|
430
|
+
device = mijiaDevice(api, did=args.did, dev_name=args.dev_name)
|
|
431
|
+
device.run_action(args.action_name, **(args.params or {}))
|
|
432
|
+
print(f"{device.name} ({device.did}) 的动作 {args.action_name} 指令已发送")
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def get_statistics(api: mijiaAPI, args):
|
|
436
|
+
time_end = args.time_end if args.time_end is not None else int(time.time())
|
|
437
|
+
time_start = args.time_start if args.time_start is not None else time_end - 30 * 24 * 3600
|
|
438
|
+
result = api.get_statistics({
|
|
439
|
+
"did": args.did,
|
|
440
|
+
"key": args.key,
|
|
441
|
+
"data_type": args.data_type,
|
|
442
|
+
"limit": args.limit,
|
|
443
|
+
"time_start": time_start,
|
|
444
|
+
"time_end": time_end,
|
|
445
|
+
})
|
|
446
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
447
|
+
|
|
448
|
+
|
|
336
449
|
def main(args):
|
|
337
450
|
args = parse_args(args)
|
|
338
451
|
|
|
@@ -390,6 +503,10 @@ def main(args):
|
|
|
390
503
|
get(args)
|
|
391
504
|
if args.func == 'set':
|
|
392
505
|
set(args)
|
|
506
|
+
if args.func == 'action':
|
|
507
|
+
run_action(api, args)
|
|
508
|
+
if args.func == 'statistics':
|
|
509
|
+
get_statistics(api, args)
|
|
393
510
|
if args.func == 'run':
|
|
394
511
|
if device_mapping is None:
|
|
395
512
|
device_mapping = get_devices_list(api, verbose=False)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import re
|
|
3
3
|
import time
|
|
4
|
+
from collections import Counter
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import Optional, Union
|
|
6
7
|
|
|
@@ -20,6 +21,19 @@ from .version import version
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
device_url = "https://home.miot-spec.com/spec/"
|
|
24
|
+
device_info_version = 1
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _deduplicate_names(items: list[dict], iid_key: str) -> None:
|
|
28
|
+
name_counts = Counter(item["name"] for item in items)
|
|
29
|
+
for item in items:
|
|
30
|
+
if name_counts[item["name"]] > 1:
|
|
31
|
+
item["name"] = f"{item['name']}-{item['method']['siid']}"
|
|
32
|
+
|
|
33
|
+
name_counts = Counter(item["name"] for item in items)
|
|
34
|
+
for item in items:
|
|
35
|
+
if name_counts[item["name"]] > 1:
|
|
36
|
+
item["name"] = f"{item['name']}-{item['method'][iid_key]}"
|
|
23
37
|
|
|
24
38
|
|
|
25
39
|
class DevProp():
|
|
@@ -252,6 +266,7 @@ def get_device_info(device_model: str, cache_path: Optional[Union[str, Path]] =
|
|
|
252
266
|
|
|
253
267
|
返回值:
|
|
254
268
|
dict: 设备规格信息字典,包含以下字段:
|
|
269
|
+
- version (int): 设备信息缓存格式版本
|
|
255
270
|
- name (str): 设备名称
|
|
256
271
|
- model (str): 设备型号
|
|
257
272
|
- properties (list): 设备属性列表,每个属性包含以下字段:
|
|
@@ -275,12 +290,16 @@ def get_device_info(device_model: str, cache_path: Optional[Union[str, Path]] =
|
|
|
275
290
|
>>> print(info['name']) # 输出设备名称
|
|
276
291
|
>>> print(info['properties'][0]['name']) # 输出第一个属性的名称
|
|
277
292
|
"""
|
|
293
|
+
cache_file = None
|
|
278
294
|
if cache_path is not None:
|
|
279
295
|
cache_file = Path(cache_path) / f"{device_model}.json"
|
|
280
296
|
if cache_file.exists():
|
|
281
297
|
logger.debug(f"从缓存加载设备信息: {cache_file}")
|
|
282
298
|
with cache_file.open("r", encoding="utf-8") as f:
|
|
283
|
-
|
|
299
|
+
cached_result = json.load(f)
|
|
300
|
+
if cached_result.get("version") == device_info_version:
|
|
301
|
+
return cached_result
|
|
302
|
+
logger.debug(f"设备信息缓存版本不匹配,重新获取: {cache_file}")
|
|
284
303
|
response = requests.get(device_url + device_model, headers={
|
|
285
304
|
"User-Agent": f"mijiaAPI/{version}"
|
|
286
305
|
})
|
|
@@ -297,6 +316,7 @@ def get_device_info(device_model: str, cache_path: Optional[Union[str, Path]] =
|
|
|
297
316
|
model = product["model"]
|
|
298
317
|
i18n_zh = content["props"]["i18n"]["zh_cn"]
|
|
299
318
|
result = {
|
|
319
|
+
"version": device_info_version,
|
|
300
320
|
"name": name,
|
|
301
321
|
"model": model,
|
|
302
322
|
"properties": [],
|
|
@@ -304,11 +324,8 @@ def get_device_info(device_model: str, cache_path: Optional[Union[str, Path]] =
|
|
|
304
324
|
}
|
|
305
325
|
services = content["props"]["tree"]["services"]
|
|
306
326
|
|
|
307
|
-
properties_name = []
|
|
308
|
-
actions_name = []
|
|
309
327
|
for svc in services:
|
|
310
328
|
siid = svc["iid"]
|
|
311
|
-
svc_type = svc["type"]
|
|
312
329
|
for prop in svc.get("properties", []):
|
|
313
330
|
piid = prop["iid"]
|
|
314
331
|
if prop["format"].startswith("int"):
|
|
@@ -345,9 +362,6 @@ def get_device_info(device_model: str, cache_path: Optional[Union[str, Path]] =
|
|
|
345
362
|
if vl_zh:
|
|
346
363
|
vl_entry["desc_zh_cn"] = vl_zh
|
|
347
364
|
item["value-list"].append(vl_entry)
|
|
348
|
-
if item["name"] in properties_name:
|
|
349
|
-
item["name"] = f"{svc_type}-{item['name']}"
|
|
350
|
-
properties_name.append(item["name"])
|
|
351
365
|
result["properties"].append(item)
|
|
352
366
|
for act in svc.get("actions", []):
|
|
353
367
|
aiid = act["iid"]
|
|
@@ -360,15 +374,13 @@ def get_device_info(device_model: str, cache_path: Optional[Union[str, Path]] =
|
|
|
360
374
|
"aiid": aiid
|
|
361
375
|
}
|
|
362
376
|
}
|
|
363
|
-
if act_item["name"] in actions_name:
|
|
364
|
-
act_item["name"] = f"{svc_type}-{act_item['name']}"
|
|
365
|
-
actions_name.append(act_item["name"])
|
|
366
377
|
result["actions"].append(act_item)
|
|
367
378
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
379
|
+
_deduplicate_names(result["properties"], "piid")
|
|
380
|
+
_deduplicate_names(result["actions"], "aiid")
|
|
381
|
+
|
|
382
|
+
if cache_file is not None:
|
|
383
|
+
cache_file.parent.mkdir(parents=True, exist_ok=True)
|
|
372
384
|
logger.debug(f"缓存设备信息到: {cache_file}")
|
|
373
385
|
with cache_file.open("w", encoding="utf-8") as f:
|
|
374
386
|
json.dump(result, f, indent=2, ensure_ascii=False)
|
|
@@ -68,7 +68,7 @@ def run(auth_path: Path) -> None:
|
|
|
68
68
|
f"请调用 login 工具重新登录后再使用其他工具"
|
|
69
69
|
)
|
|
70
70
|
|
|
71
|
-
mcp.run()
|
|
71
|
+
mcp.run(show_banner=False)
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
@mcp.tool
|
|
@@ -274,13 +274,20 @@ def get_statistics(
|
|
|
274
274
|
|
|
275
275
|
参数:
|
|
276
276
|
did: 设备ID,可从 list_devices 获取。
|
|
277
|
-
key:
|
|
278
|
-
|
|
277
|
+
key: 设备相关的统计键,通常为 siid.piid。例如 lumi.acpartner.mcn04
|
|
278
|
+
的耗电量使用 "7.1",lumi.acpartner.mcn02 使用 "powerCost"。
|
|
279
|
+
data_type: 统计粒度:stat_hour_v3 / stat_day_v3 / stat_week_v3 /
|
|
280
|
+
stat_month_v3。较旧设备可能使用不带 _v3 的对应类型。
|
|
279
281
|
limit: 返回最大条目数,默认6。
|
|
280
282
|
time_start: 起始时间戳(秒),不传默认为30天前。
|
|
281
283
|
time_end: 结束时间戳(秒),不传默认为当前时间。
|
|
282
284
|
|
|
283
|
-
|
|
285
|
+
返回 JSON 编码的统计条目列表。每项包含 time 时间戳和 value;value 通常仍是
|
|
286
|
+
JSON 数组字符串,例如 "[48.476]"。
|
|
287
|
+
|
|
288
|
+
注意:统计接口仅支持部分设备,不同型号可能需要不同的 key、data_type,甚至使用
|
|
289
|
+
不同 API。详见 https://github.com/Do1e/mijia-api/issues/46
|
|
290
|
+
参考 https://iot.mi.com/new/doc/accesses/direct-access/extension-development/extension-functions/statistical-interface
|
|
284
291
|
"""
|
|
285
292
|
import time
|
|
286
293
|
api = _get_api()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "4.2.0"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[egg_info]
|
|
2
|
-
tag_build =
|
|
3
|
-
tag_date = 0
|
|
4
|
-
|
|
1
|
+
[egg_info]
|
|
2
|
+
tag_build =
|
|
3
|
+
tag_date = 0
|
|
4
|
+
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "4.1.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|