├── .HA_VERSION ├── .gitignore ├── .gitmodules ├── README.md ├── automations ├── co2.yaml ├── disabled │ ├── air.yaml │ ├── cover.yaml │ ├── cube.yaml │ ├── door.yaml │ ├── humidity.yaml │ ├── passage.yaml │ ├── projector.yaml │ ├── sync.yaml │ ├── washer.yaml │ └── washroom.yaml ├── pm25.yaml ├── sleeping.yaml └── temperature.yaml ├── configuration.yaml ├── custom_components ├── zhi ├── zhiact ├── zhiaqara │ ├── __init__.py │ └── manifest.json ├── zhibot ├── zhibravia │ ├── __init__.py │ └── manifest.json ├── zhibroad │ ├── __init__.py │ └── manifest.json ├── zhicaiyun ├── zhilace ├── zhimi ├── zhimijia ├── zhimodbus ├── zhimsg ├── zhiremote └── zhisaswell ├── customize.yaml ├── extras ├── deprecated │ ├── aircat │ │ ├── __init__.py │ │ └── sensor.py │ └── hagenie │ │ ├── access.py │ │ ├── authorize.py │ │ ├── gate.py │ │ └── hagenie.py ├── setup │ ├── Docker.sh │ ├── Hass.sh │ ├── HassFix.sh │ └── HassOp.sh └── test │ ├── test_airer.py │ ├── test_bravia.py │ ├── test_https.py │ ├── test_miot.py │ ├── test_modbus.py │ └── test_washer.py ├── fans.yaml ├── homekit.yaml ├── lights.yaml ├── mqtt.yaml ├── sensors.yaml └── zhilace-dash.yaml /.HA_VERSION: -------------------------------------------------------------------------------- 1 | 2024.6.4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /deps 2 | /blueprints 3 | /secrets.yaml 4 | /known_devices.yaml 5 | /www/*.jpg 6 | __pycache__ 7 | *.crt 8 | *.key 9 | *.pem 10 | *.log 11 | *.db 12 | .* 13 | *.conf 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "www"] 2 | path = www 3 | url = git@github.com:Yonsm/ZhiDash.git 4 | [submodule "modules/Zhi"] 5 | path = modules/Zhi 6 | url = git@github.com:Yonsm/Zhi.git 7 | [submodule "modules/ZhiAct"] 8 | path = modules/ZhiAct 9 | url = git@github.com:Yonsm/ZhiAct.git 10 | [submodule "modules/ZhiBot"] 11 | path = modules/ZhiBot 12 | url = git@github.com:Yonsm/ZhiBot.git 13 | [submodule "modules/ZhiCaiYun"] 14 | path = modules/ZhiCaiYun 15 | url = git@github.com:Yonsm/ZhiCaiYun.git 16 | [submodule "modules/ZhiLace"] 17 | path = modules/ZhiLace 18 | url = git@github.com:Yonsm/ZhiLace.git 19 | [submodule "modules/ZhiMi"] 20 | path = modules/ZhiMi 21 | url = git@github.com:Yonsm/ZhiMi.git 22 | [submodule "modules/ZhiMiJia"] 23 | path = modules/ZhiMiJia 24 | url = git@github.com:Yonsm/ZhiMiJia.git 25 | [submodule "modules/ZhiModBus"] 26 | path = modules/ZhiModBus 27 | url = git@github.com:Yonsm/ZhiModBus.git 28 | [submodule "modules/ZhiMsg"] 29 | path = modules/ZhiMsg 30 | url = git@github.com:Yonsm/ZhiMsg.git 31 | [submodule "modules/ZhiRemote"] 32 | path = modules/ZhiRemote 33 | url = git@github.com:Yonsm/ZhiRemote.git 34 | [submodule "modules/ZhiSaswell"] 35 | path = modules/ZhiSaswell 36 | url = git@github.com:Yonsm/ZhiSaswell.git 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Home Assistant Extras for Yonsm 2 | 3 | 这是我个人的 Home Assistant 扩展和配置,请酌情参考。 4 | 5 | ## 一、[智家面板](https://github.com/Yonsm/ZhiDash) 6 | 7 | [ZhiDash](https://github.com/Yonsm/ZhiDash) 是一个轻量的前端操作面板。 8 | 9 | ## 二、[智家组件](https://github.com/Yonsm/.homeassistant/tree/main/modules) 10 | 11 | ### 0. [Zhi](https://github.com/Yonsm/Zhi) 12 | 13 | 智家通用公共代码,部分组件依赖此目录。 14 | 15 | ### 1. [ZhiAct](https://github.com/Yonsm/ZhiAct) 16 | 17 | 根据传感器数值区间来自动控制设备。 18 | 19 | ### 2. [ZhiBot](https://github.com/Yonsm/ZhiBot) 20 | 21 | 通用交互式机器人平台,目前支持天猫精灵、小爱同学、钉钉群机器人等。其中钉钉机器人依赖 [ZhiMsg](https://github.com/Yonsm/ZhiMsg)。 22 | 23 | ### 3. [ZhiCaiYun](https://github.com/Yonsm/ZhiCaiYun) 24 | 25 | 彩云天气的标准天气插件,支持 15 天预报。 26 | 27 | ### 4. [ZhiMi](https://github.com/Yonsm/ZhiMi) 28 | 29 | 小米云控制的接口,被 `ZhiMsg` 依赖。 30 | 31 | ### 5. [ZhiModBus](https://github.com/Yonsm/ZhiModBus) 32 | 33 | 通用 ModBus 空调插件,比 HA 官方做的更通用、更好。 34 | 35 | ### 6. [ZhiMQTT](https://github.com/Yonsm/ZhiMQTT) 36 | 37 | 基于 MQTT Swicth 的扩展开关。 38 | 39 | ### 7. [ZhiMrBond](https://github.com/Yonsm/ZhiMrBond) 40 | 41 | 邦先生晾衣架组件。 42 | 43 | ### 8. [ZhiMsg](https://github.com/Yonsm/ZhiMsg) 44 | 45 | 通用消息平台,目前支持钉钉群、小爱同学。依赖 [ZhiMi](https://github.com/Yonsm/ZhiMi)。 46 | 47 | ### 9. [ZhiRemote](https://github.com/Yonsm/ZhiRemote) 48 | 49 | 基于 `remote` 遥控器的通用组件。 50 | 51 | ### 10. [ZhiSaswell](https://github.com/Yonsm/ZhiSaswell) 52 | 53 | SasWell 温控面板组件(地暖)。 54 | 55 | ### 11. [ZhiViomi](https://github.com/Yonsm/ZhiViomi) 56 | 57 | 云米洗衣机组件。 58 | 59 | ## 三、个人配置 60 | 61 | ### 1. [configuration.yaml](https://github.com/Yonsm/.homeassistant/tree/main/configuration.yaml) 62 | 63 | 这是我的 Home Assistant 配置文件。 64 | 65 | ### 2. [customize.yaml](https://github.com/Yonsm/.homeassistant/tree/main/customize.yaml) 66 | 67 | 这是我的 Home Assistant 个性化配置文件,主要是中文名称和部分插件的个性化扩展配置。 68 | 69 | ### 3. [automations](https://github.com/Yonsm/.homeassistant/tree/main/automations) 70 | 71 | 这是我的 Home Assistant 自动化文件,其中有些脚本可以参考,如只用 Motion Sensor [解决洗手间自动开关灯](automations/washroom.yaml)的难题。 72 | 73 | ## 四、其它 [extras](https://github.com/Yonsm/.homeassistant/tree/main/extras) 74 | 75 | ### 1. [homeassistant](https://github.com/Yonsm/.homeassistant/tree/main/extras/homeassistant) 76 | 77 | 对 homeassistant 的小修改,解决部分错误、警告、不优雅等困扰问题。 78 | 79 | ### 2. [deprecated](https://github.com/Yonsm/.homeassistant/tree/main/extras/deprecated) 80 | 81 | 一些过期的或者不用的文件,仅供备忘参考。 82 | 83 | ### 3. [setup](https://github.com/Yonsm/.homeassistant/tree/main/extras/setup) 84 | 85 | 树莓派和斐讯 N1 armbian 下安装 Home Assistant 的脚本,仅供参考,请按需逐步执行,不要整个脚本直接运行。 86 | 87 | ### 4. [test](https://github.com/Yonsm/.homeassistant/tree/main/extras/test) 88 | 89 | 部分测试脚本备忘。 90 | -------------------------------------------------------------------------------- /automations/co2.yaml: -------------------------------------------------------------------------------- 1 | - alias: 客厅二氧化碳变化-调控新风机 2 | mode: restart 3 | trigger: 4 | - platform: state 5 | entity_id: sensor.ke_ting_er_yang_hua_tan 6 | action: 7 | - service: zhiact.actuate 8 | data: 9 | sensor_id: sensor.ke_ting_er_yang_hua_tan 10 | sensor_values: [490, 540, 650, 720] 11 | entity_id: fan.ke_ting_xin_feng_ji 12 | entity_attr: preset_mode 13 | entity_values: [自动, 低档, 中档, 高档] 14 | condition_attr: mode 15 | condition_values: [auto, low, middle, strong] 16 | 17 | - alias: 主卧二氧化碳变化-调控新风机 18 | mode: restart 19 | trigger: 20 | - platform: state 21 | entity_id: sensor.zhu_wo_er_yang_hua_tan 22 | action: 23 | - service: zhiact.actuate 24 | data: 25 | sensor_id: sensor.zhu_wo_er_yang_hua_tan 26 | sensor_values: [500, 600, 700, 800] 27 | alt_sensor_values: [500, 700, 900, 1300] 28 | entity_id: fan.zhu_wo_xin_feng_ji 29 | entity_attr: preset_mode 30 | entity_values: [自动, 低档, 中档, 高档] 31 | condition_attr: mode 32 | condition_values: [auto, low, middle, strong] 33 | -------------------------------------------------------------------------------- /automations/disabled/air.yaml: -------------------------------------------------------------------------------- 1 | - alias: 室外空气好 2 | trigger: 3 | - platform: numeric_state 4 | entity_id: sensor.yang_tai_kong_qi_zhi_liang 5 | below: 20 6 | for: 7 | minutes: 10 8 | condition: 9 | - condition: time 10 | after: '07:00' 11 | before: '22:00' 12 | - condition: state 13 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 14 | state: 'off' 15 | - condition: numeric_state 16 | entity_id: sensor.yang_tai_wen_du 17 | above: 10 18 | below: 30 19 | - condition: or 20 | conditions: 21 | - condition: numeric_state 22 | entity_id: sensor.can_ting_kong_qi_zhi_liang 23 | above: 20 24 | - condition: numeric_state 25 | entity_id: sensor.ke_ting_er_yang_hua_tan 26 | above: 800 27 | action: 28 | - service: zhimsg.guo_dao_xiao_ai 29 | data: 30 | message: 外面空气很好,可以打开门窗 31 | 32 | - alias: 室内空气差 33 | mode: restart 34 | trigger: 35 | - platform: numeric_state 36 | entity_id: sensor.can_ting_kong_qi_zhi_liang 37 | above: 35 38 | for: 39 | minutes: 2 40 | condition: 41 | - condition: time 42 | after: '06:00' 43 | before: '23:00' 44 | action: 45 | - service: zhimsg.guo_dao_xiao_ai 46 | data_template: 47 | message: '客厅PM2.5为{{ states("sensor.can_ting_kong_qi_zhi_liang") }},空气不好。{% if is_state("binary_sensor.door_window_sensor_158d0001f3d2d1", "on") or is_state("binary_sensor.door_window_sensor_158d0003cf4735", "on") or is_state("binary_sensor.door_window_sensor_158d000228a52b", "on") %}请关好{% if is_state("binary_sensor.door_window_sensor_158d0001f3d2d1", "on") %}厨房门、{% endif %}{% if is_state("binary_sensor.door_window_sensor_158d0003cf4735", "on") %}洗手间门、{% endif %}{% if is_state("binary_sensor.door_window_sensor_158d000228a52b", "on") %}阳台门{% endif %}{% endif %}' 48 | - delay: 600 49 | - condition: numeric_state 50 | entity_id: sensor.can_ting_kong_qi_zhi_liang 51 | above: 40 52 | - condition: or 53 | conditions: 54 | - condition: state 55 | entity_id: binary_sensor.door_window_sensor_158d0001f3d2d1 56 | state: 'on' 57 | - condition: state 58 | entity_id: binary_sensor.door_window_sensor_158d0003cf4735 59 | state: 'on' 60 | - condition: state 61 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 62 | state: 'on' 63 | - service: automation.trigger 64 | entity_id: automation.shi_nei_kong_qi_chai 65 | 66 | - alias: 室内外环境提醒 67 | trigger: 68 | - platform: time 69 | at: '7:30:00' 70 | action: 71 | - service: zhimsg.ding 72 | data_template: 73 | message: '室内PM2.5为{{ states("sensor.can_ting_kong_qi_zhi_liang") }},温度为{{ states("sensor.can_ting_wen_du") }},CO2为客厅{{ states("sensor.ke_ting_er_yang_hua_tan") }}/主卧{{ states("sensor.zhu_wo_er_yang_hua_tan") }}/儿童房{{ states("sensor.er_tong_fang_er_yang_hua_tan") }}。室外PM2.5为{{ states("sensor.yang_tai_kong_qi_zhi_liang") }},温度为{{ states("sensor.yang_tai_wen_du") }};{{ state_attr("weather.tian_qi", "attribution") }}' 74 | -------------------------------------------------------------------------------- /automations/disabled/cover.yaml: -------------------------------------------------------------------------------- 1 | - alias: 书房亮度高-关窗帘 2 | trigger: 3 | - platform: time 4 | at: '12:30:00' 5 | - platform: numeric_state 6 | entity_id: sensor.shu_fang_liang_du 7 | above: 120 8 | for: 9 | minutes: 10 10 | condition: 11 | - condition: numeric_state 12 | entity_id: sensor.shu_fang_liang_du 13 | above: 100 14 | - condition: time 15 | after: '12:00' 16 | before: '16:00' 17 | action: 18 | - service: cover.close_cover 19 | entity_id: cover.shu_fang_chuang_lian 20 | 21 | - alias: 书房亮度正常-开窗帘 22 | trigger: 23 | - platform: sun 24 | event: sunset 25 | offset: '-01:30:00' 26 | condition: 27 | - condition: state 28 | entity_id: cover.shu_fang_chuang_lian 29 | state: closed 30 | - condition: state 31 | entity_id: media_player.shu_fang_tou_ying_yi 32 | state: 'off' 33 | action: 34 | - service: cover.open_cover 35 | entity_id: cover.shu_fang_chuang_lian 36 | 37 | - alias: 过道门开关-开关卷帘 38 | trigger: 39 | - platform: state 40 | entity_id: binary_sensor.door_window_sensor_158d00041c74da 41 | from: 'off' 42 | to: 'on' 43 | for: 00:00:10 44 | - platform: state 45 | entity_id: binary_sensor.door_window_sensor_158d00041c74da 46 | from: 'on' 47 | to: 'off' 48 | action: 49 | - service_template: 'cover.{% if is_state("binary_sensor.door_window_sensor_158d00041c74da", "off") %}open{% else %}close{% endif %}_cover' 50 | entity_id: cover.curtain_158d0003f7951d 51 | 52 | - alias: 主卧窗帘开关-调整新风机 53 | trigger: 54 | - platform: state 55 | entity_id: cover.curtain_158d000405d535 56 | to: closed 57 | - platform: state 58 | entity_id: cover.curtain_158d000405d535 59 | to: open 60 | action: 61 | # - service_template: 'fan.turn_{% if is_state("cover.curtain_158d000405d535", "closed") %}on{% else %}off{% endif %}' 62 | # entity_id: fan.zhu_wo_feng_shan 63 | - service: fan.set_preset_mode 64 | data_template: 65 | entity_id: fan.zhu_wo_xin_feng_ji 66 | preset_mode: '{% if is_state("cover.curtain_158d000405d535", "closed") %}静音{% else %}中档{% endif %}' 67 | - service: fan.oscillate 68 | data_template: 69 | entity_id: fan.zhu_wo_xin_feng_ji 70 | oscillating: '{% if is_state("cover.curtain_158d000405d535", "closed") %}false{% else %}true{% endif %}' 71 | 72 | - alias: 儿童房窗帘开关-调整风扇 73 | initial_state: false 74 | trigger: 75 | - platform: state 76 | entity_id: cover.curtain_158d00042cf265 77 | to: closed 78 | - platform: state 79 | entity_id: cover.curtain_158d00042cf265 80 | to: open 81 | action: 82 | - service_template: 'fan.turn_{% if is_state("cover.curtain_158d00042cf265", "closed") %}on{% else %}off{% endif %}' 83 | entity_id: fan.er_tong_fang_feng_shan 84 | -------------------------------------------------------------------------------- /automations/disabled/cube.yaml: -------------------------------------------------------------------------------- 1 | - alias: 儿童房魔方摇一摇-召唤神龙爸爸 2 | trigger: 3 | - platform: event 4 | event_type: xiaomi_aqara.cube_action 5 | event_data: 6 | entity_id: binary_sensor.cube_158d0002a66db1 7 | action_type: shake_air 8 | action: 9 | - service: zhimsg.ding 10 | data: 11 | message: 召唤神龙爸爸 12 | - service: xiaomi_aqara.play_ringtone 13 | data: 14 | gw_mac: 34CE0090901A 15 | ringtone_id: 10016 16 | ringtone_vol: 60 17 | 18 | # - alias: 儿童房魔方翻转九十度 19 | # trigger: 20 | # - platform: event 21 | # event_type: xiaomi_aqara.cube_action 22 | # event_data: 23 | # entity_id: binary_sensor.cube_158d0002a66db1 24 | # action_type: flip90 25 | # action: 26 | # - service: zhimsg.guo_dao_xiao_ai 27 | # data_template: 28 | # message: 魔方翻转九十度 29 | 30 | # - alias: 魔方翻转一百八十度 31 | # trigger: 32 | # - platform: event 33 | # event_type: xiaomi_aqara.cube_action 34 | # event_data: 35 | # entity_id: binary_sensor.cube_158d0002a66db1 36 | # action_type: flip180 37 | # action: 38 | # - service: zhimsg.guo_dao_xiao_ai 39 | # data_template: 40 | # message: 魔方翻转一百八十度 41 | 42 | # - alias: 儿童房魔方移动 43 | # trigger: 44 | # - platform: event 45 | # event_type: xiaomi_aqara.cube_action 46 | # event_data: 47 | # entity_id: binary_sensor.cube_158d0002a66db1 48 | # action_type: move 49 | # action: 50 | # - service: zhimsg.guo_dao_xiao_ai 51 | # data_template: 52 | # message: 魔方移动 53 | 54 | # - alias: 儿童房魔方敲击两下 55 | # trigger: 56 | # - platform: event 57 | # event_type: xiaomi_aqara.cube_action 58 | # event_data: 59 | # entity_id: binary_sensor.cube_158d0002a66db1 60 | # action_type: tap_twice 61 | # action: 62 | # - service: zhimsg.guo_dao_xiao_ai 63 | # data_template: 64 | # message: '阳台PM2.5为{{ states("sensor.yang_tai_kong_qi_zhi_liang") }},餐厅PM2.5为{{ states("sensor.can_ting_kong_qi_zhi_liang") }},主卧PM2.5为{{ states("sensor.zhu_wo_kong_qi_zhi_liang") }}。客厅二氧化碳浓度为{{ states("sensor.ke_ting_er_yang_hua_tan") }},主卧二氧化碳浓度为{{ states("sensor.zhu_wo_er_yang_hua_tan") }},儿童房二氧化碳浓度为{{ states("sensor.er_tong_fang_er_yang_hua_tan") }}' 65 | 66 | # - alias: 儿童房魔方摇摆 67 | # trigger: 68 | # - platform: event 69 | # event_type: xiaomi_aqara.cube_action 70 | # event_data: 71 | # entity_id: binary_sensor.cube_158d0002a66db1 72 | # action_type: swing 73 | # action: 74 | # - service: zhimsg.guo_dao_xiao_ai 75 | # data_template: 76 | # message: 魔方摇摆 77 | 78 | # - alias: 儿童房魔方警告 79 | # trigger: 80 | # - platform: event 81 | # event_type: xiaomi_aqara.cube_action 82 | # event_data: 83 | # entity_id: binary_sensor.cube_158d0002a66db1 84 | # action_type: alert 85 | # action: 86 | # - service: zhimsg.guo_dao_xiao_ai 87 | # data_template: 88 | # message: 魔方警告 89 | 90 | # - alias: 儿童房魔方下落 91 | # trigger: 92 | # - platform: event 93 | # event_type: xiaomi_aqara.cube_action 94 | # event_data: 95 | # entity_id: binary_sensor.cube_158d0002a66db1 96 | # action_type: free_fall 97 | # action: 98 | # - service: zhimsg.guo_dao_xiao_ai 99 | # data_template: 100 | # message: 魔方下落 101 | 102 | # - alias: 儿童房魔方旋转 103 | # trigger: 104 | # - platform: event 105 | # event_type: xiaomi_aqara.cube_action 106 | # event_data: 107 | # entity_id: binary_sensor.cube_158d0002a66db1 108 | # action_type: rotate 109 | # action: 110 | # - service: zhimsg.ding 111 | # data: 112 | # message: 魔方旋转 113 | # - service: automation.toggle 114 | # entity_id: automation.guo_dao_deng_bai_tian_kai 115 | # - service: automation.toggle 116 | # entity_id: automation.guo_dao_deng_wan_shang_kai 117 | # - service: automation.toggle 118 | # entity_id: automation.guo_dao_bei_jing_deng_gan_ying 119 | # - service: zhimsg.guo_dao_xiao_ai 120 | # data_template: 121 | # message: '过道灯自动感应功能已{% if is_state("automation.guo_dao_bei_jing_deng_gan_ying", "on") %}启用{% else %}暂停,所有灯光将在10秒后关闭{% endif %}' 122 | # - delay: '00:00:10' 123 | # - condition: state 124 | # entity_id: automation.guo_dao_bei_jing_deng_gan_ying 125 | # state: 'off' 126 | # - service: automation.turn_on 127 | # entity_id: automation.guo_dao_deng_gan_ying_zhong_qi 128 | # - service: light.turn_off 129 | # entity_id: all 130 | 131 | # - alias: 过道灯感应重启 132 | # initial_state: false 133 | # trigger: 134 | # - platform: time 135 | # at: '07:00:00' 136 | # action: 137 | # - service: automation.turn_on 138 | # entity_id: automation.guo_dao_deng_bai_tian_kai 139 | # - service: automation.turn_on 140 | # entity_id: automation.guo_dao_deng_wan_shang_kai 141 | # - service: automation.turn_on 142 | # entity_id: automation.guo_dao_bei_jing_deng_gan_ying 143 | # - service: zhimsg.guo_dao_xiao_ai 144 | # data_template: 145 | # message: 过道灯自动感应功能已重新启用 146 | # - delay: '00:00:10' 147 | # - service: automation.turn_off 148 | # entity_id: automation.guo_dao_deng_gan_ying_zhong_qi 149 | -------------------------------------------------------------------------------- /automations/disabled/door.yaml: -------------------------------------------------------------------------------- 1 | - alias: 入户门欢迎 2 | trigger: 3 | - platform: state 4 | entity_id: binary_sensor.door_window_sensor_158d0001f3e5be 5 | from: 'on' 6 | to: 'off' 7 | action: 8 | - service: xiaomi_aqara.play_ringtone 9 | data: 10 | gw_mac: 34CE0090901A 11 | ringtone_id: 10001 12 | ringtone_vol: 80 13 | 14 | - alias: 入户门提醒 15 | mode: restart 16 | trigger: 17 | - platform: state 18 | entity_id: binary_sensor.door_window_sensor_158d0001f3e5be 19 | from: 'off' 20 | to: 'on' 21 | for: 22 | minutes: 2 23 | action: 24 | - service: zhimsg.ding 25 | data: 26 | message: 入户门长时间开启,请检查 27 | - service: xiaomi_aqara.play_ringtone 28 | data: 29 | gw_mac: 34CE0090901A 30 | ringtone_id: 10013 31 | ringtone_vol: 100 32 | - delay: 120 33 | - condition: state 34 | entity_id: binary_sensor.door_window_sensor_158d0001f3e5be 35 | state: 'on' 36 | - service: automation.trigger 37 | entity_id: automation.ru_hu_men_ti_xing 38 | 39 | - alias: 阳台门感应 40 | trigger: 41 | - platform: state 42 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 43 | from: 'off' 44 | to: 'on' 45 | - platform: state 46 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 47 | from: 'on' 48 | to: 'off' 49 | condition: 50 | - condition: state 51 | entity_id: sun.sun 52 | state: below_horizon 53 | action: 54 | - service_template: '{% if trigger.to_state.state == "on" %}light.turn_on{% else %}light.turn_off{% endif %}' 55 | entity_id: light.balcony_light 56 | 57 | - alias: 阳台门提醒 58 | mode: restart 59 | trigger: 60 | - platform: numeric_state 61 | entity_id: sensor.yang_tai_kong_qi_zhi_liang 62 | above: 60 63 | for: 64 | minutes: 5 65 | - platform: state 66 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 67 | from: 'off' 68 | to: 'on' 69 | for: 70 | seconds: 60 71 | condition: 72 | - condition: state 73 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 74 | state: 'on' 75 | - condition: time 76 | after: '06:00' 77 | before: '23:00' 78 | action: 79 | - service: zhimsg.guo_dao_xiao_ai 80 | data_template: 81 | message: '阳台PM2.5为{% set PM25 = states("sensor.yang_tai_kong_qi_zhi_liang") | int %}{{ PM25 }},{% if PM25 < 20 %}空气很好{% elif PM25 < 40 %}空气不错{% elif PM25 < 60 %}空气一般{% elif PM25 < 80 %}空气不好,请关好阳台门{% else %}空气污染,请关好阳台门和其它门窗{% endif %}' 82 | - delay: 120 83 | - condition: state 84 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 85 | state: 'on' 86 | - condition: numeric_state 87 | entity_id: sensor.yang_tai_kong_qi_zhi_liang 88 | above: 60 89 | - service: automation.trigger 90 | entity_id: automation.yang_tai_men_ti_xing 91 | # 92 | - alias: 厨房门提醒 93 | mode: restart 94 | trigger: 95 | - platform: state 96 | entity_id: binary_sensor.door_window_sensor_158d0001f3d2d1 97 | from: 'off' 98 | to: 'on' 99 | for: 100 | minutes: 2 101 | - platform: time 102 | at: '21:10:00' 103 | condition: 104 | - condition: state 105 | entity_id: binary_sensor.door_window_sensor_158d0001f3d2d1 106 | state: 'on' 107 | - condition: time 108 | after: '21:00' 109 | before: '23:00' 110 | action: 111 | - service: xiaomi_aqara.play_ringtone 112 | data: 113 | gw_mac: 34CE0090901A 114 | ringtone_id: 10015 115 | ringtone_vol: 60 116 | - delay: 120 117 | - condition: state 118 | entity_id: binary_sensor.door_window_sensor_158d0001f3d2d1 119 | state: 'on' 120 | - service: automation.trigger 121 | entity_id: automation.chu_fang_men_ti_xing 122 | -------------------------------------------------------------------------------- /automations/disabled/humidity.yaml: -------------------------------------------------------------------------------- 1 | - alias: 餐厅湿度高-开除湿机 2 | trigger: 3 | - platform: numeric_state 4 | entity_id: sensor.can_ting_shi_du 5 | above: 74 6 | for: 7 | minutes: 10 8 | action: 9 | - service: switch.turn_on 10 | entity_id: switch.can_ting_chu_shi_ji 11 | 12 | - alias: 餐厅湿度正常-关除湿机 13 | trigger: 14 | - platform: numeric_state 15 | entity_id: sensor.can_ting_shi_du 16 | below: 70 17 | for: 18 | minutes: 10 19 | action: 20 | - service: switch.turn_off 21 | entity_id: switch.can_ting_chu_shi_ji 22 | 23 | - alias: 儿童房湿度高-开除湿机 24 | trigger: 25 | - platform: numeric_state 26 | entity_id: sensor.er_tong_fang_shi_du 27 | above: 74 28 | for: 29 | minutes: 10 30 | condition: 31 | - condition: state 32 | entity_id: sun.sun 33 | state: above_horizon 34 | action: 35 | - service: switch.turn_on 36 | entity_id: switch.yi_ju_chu_shi_ji 37 | 38 | - alias: 儿童房湿度正常-开除湿机 39 | trigger: 40 | - platform: numeric_state 41 | entity_id: sensor.er_tong_fang_shi_du 42 | below: 70 43 | for: 44 | minutes: 10 45 | - platform: time 46 | at: '20:30:00' 47 | action: 48 | - service: switch.turn_off 49 | entity_id: switch.yi_ju_chu_shi_ji 50 | 51 | - alias: 餐厅湿度低-开加湿器 52 | initial_state: true 53 | trigger: 54 | - platform: numeric_state 55 | entity_id: sensor.can_ting_shi_du 56 | below: 56 57 | for: 58 | minutes: 10 59 | action: 60 | - service: automation.turn_off 61 | entity_id: automation.can_ting_jing_hua_qi_diao_jie 62 | - service: fan.oscillate 63 | data: 64 | entity_id: fan.can_ting_jing_hua_qi 65 | oscillating: true 66 | - service: fan.set_preset_mode 67 | data: 68 | entity_id: fan.can_ting_jing_hua_qi 69 | preset_mode: low 70 | 71 | - alias: 餐厅湿度正常-关加湿器 72 | trigger: 73 | - platform: numeric_state 74 | entity_id: sensor.can_ting_shi_du 75 | above: 60 76 | for: 77 | minutes: 10 78 | action: 79 | - service: automation.turn_on 80 | entity_id: automation.can_ting_jing_hua_qi_diao_jie 81 | - service: fan.oscillate 82 | data: 83 | entity_id: fan.can_ting_jing_hua_qi 84 | oscillating: false 85 | 86 | - alias: 主卧湿度低-开加湿器 87 | trigger: 88 | - platform: numeric_state 89 | entity_id: sensor.zhu_wo_shi_du 90 | below: 58 91 | for: 92 | minutes: 10 93 | action: 94 | - service: automation.turn_off 95 | entity_id: automation.zhu_wo_jing_hua_qi_diao_jie 96 | - service: fan.oscillate 97 | data: 98 | entity_id: fan.zhu_wo_jing_hua_qi 99 | oscillating: true 100 | - service: fan.set_preset_mode 101 | data: 102 | entity_id: fan.zhu_wo_jing_hua_qi 103 | preset_mode: low 104 | 105 | - alias: 主卧湿度正常-关加湿器 106 | trigger: 107 | - platform: numeric_state 108 | entity_id: sensor.zhu_wo_shi_du 109 | above: 62 110 | for: 111 | minutes: 10 112 | action: 113 | - service: automation.turn_on 114 | entity_id: automation.zhu_wo_jing_hua_qi_diao_jie 115 | - service: fan.oscillate 116 | data: 117 | entity_id: fan.zhu_wo_jing_hua_qi 118 | oscillating: false 119 | 120 | - alias: 儿童房湿度低-开加湿器 121 | trigger: 122 | - platform: numeric_state 123 | entity_id: sensor.er_tong_fang_shi_du 124 | below: 56 125 | for: 126 | minutes: 10 127 | action: 128 | - service: automation.turn_off 129 | entity_id: automation.er_tong_fang_jing_hua_qi_diao_jie 130 | - service: fan.oscillate 131 | data: 132 | entity_id: fan.er_tong_fang_jing_hua_qi 133 | oscillating: true 134 | - service: fan.set_preset_mode 135 | data: 136 | entity_id: fan.er_tong_fang_jing_hua_qi 137 | preset_mode: low 138 | 139 | - alias: 儿童房湿度正常-关加湿器 140 | trigger: 141 | - platform: numeric_state 142 | entity_id: sensor.er_tong_fang_shi_du 143 | above: 60 144 | for: 145 | minutes: 10 146 | action: 147 | - service: automation.turn_on 148 | entity_id: automation.er_tong_fang_jing_hua_qi_diao_jie 149 | - service: fan.oscillate 150 | data: 151 | entity_id: fan.er_tong_fang_jing_hua_qi 152 | oscillating: false 153 | -------------------------------------------------------------------------------- /automations/disabled/passage.yaml: -------------------------------------------------------------------------------- 1 | # 2 | - alias: 过道感应-开关背景灯 3 | trigger: 4 | - platform: state 5 | entity_id: binary_sensor.motion_sensor_158d0001d66ce9 6 | from: 'off' 7 | to: 'on' 8 | condition: 9 | - condition: numeric_state 10 | entity_id: sensor.can_ting_liang_du 11 | below: 550 12 | action: 13 | # - service: mqtt.publish 14 | # data: 15 | # topic: Dashboard/command 16 | # payload: '{wake: true}' 17 | - service: light.turn_on 18 | entity_id: light.guo_dao_ju_deng 19 | - wait_template: '{{ is_state("binary_sensor.motion_sensor_158d0001d66ce9", "off") }}' 20 | - service: light.turn_off 21 | entity_id: light.guo_dao_ju_deng 22 | -------------------------------------------------------------------------------- /automations/disabled/projector.yaml: -------------------------------------------------------------------------------- 1 | - alias: 书房投影仪开启-准备配套 2 | trigger: 3 | - platform: state 4 | entity_id: media_player.shu_fang_tou_ying_yi 5 | from: 'off' 6 | to: 'on' 7 | condition: 8 | - condition: state 9 | entity_id: cover.shu_fang_mu_bu 10 | state: open 11 | action: 12 | - service: cover.close_cover 13 | entity_id: cover.shu_fang_chuang_lian 14 | #- delay: 10 15 | - service: cover.close_cover 16 | entity_id: cover.shu_fang_mu_bu 17 | #- service: cover.close_cover 18 | # entity_id: cover.airer 19 | - service: homeassistant.turn_off 20 | entity_id: 21 | - light.shu_fang_liang_yi_deng 22 | - light.shu_fang_tai_deng 23 | # - condition: numeric_state 24 | # entity_id: sensor.shu_fang_wen_du 25 | # above: 28 26 | # - service: climate.turn_on 27 | # entity_id: climate.shu_fang_kong_diao 28 | 29 | - alias: 书房投影仪关闭-收尾配套 30 | trigger: 31 | - platform: state 32 | entity_id: media_player.shu_fang_tou_ying_yi 33 | from: 'on' 34 | to: 'off' 35 | condition: 36 | - condition: state 37 | entity_id: cover.shu_fang_mu_bu 38 | state: closed 39 | action: 40 | # - service_template: '{% if is_state("sun.sun", "below_horizon") %}light.turn_on{% else %}light.turn_off{% endif %}' 41 | # entity_id: light.shu_fang_liang_yi_deng 42 | - service: cover.open_cover 43 | entity_id: cover.shu_fang_mu_bu 44 | #- delay: 10 45 | # - service: climate.turn_off 46 | # entity_id: climate.shu_fang_kong_diao 47 | - condition: state 48 | entity_id: sun.sun 49 | state: above_horizon 50 | - service: cover.open_cover 51 | entity_id: cover.shu_fang_chuang_lian 52 | 53 | - alias: 书房按钮长按—开关投影仪 54 | trigger: 55 | - platform: event 56 | event_type: xiaomi_aqara.click 57 | event_data: 58 | entity_id: binary_sensor.switch_158d00083a4207 59 | click_type: long_click_press 60 | action: 61 | - service: zhimsg.guo_dao_xiao_ai 62 | data_template: 63 | message: '正在{% if is_state("media_player.shu_fang_tou_ying_yi", "on") %}关闭{% else %}打开{% endif %}投影仪' 64 | - service: media_player.toggle 65 | entity_id: media_player.shu_fang_tou_ying_yi 66 | - service: automation.trigger 67 | data_template: 68 | entity_id: 'automation.shu_fang_tou_ying_yi_{% if is_state("media_player.shu_fang_tou_ying_yi", "off") %}guan_bi_shou_wei{% else %}kai_qi_zhun_bei{% endif %}_pei_tao' 69 | 70 | - alias: 书房按钮双击—开关播放器 71 | trigger: 72 | - platform: event 73 | event_type: xiaomi_aqara.click 74 | event_data: 75 | entity_id: binary_sensor.switch_158d00083a4207 76 | click_type: double 77 | action: 78 | - service_template: 'switch.turn_{% if is_state("media_player.shu_fang_tou_ying_yi", "on") %}off{% else %}on{% endif %}' 79 | entity_id: switch.shu_fang_yin_xiang 80 | - service: automation.trigger 81 | entity_id: automation.shu_fang_an_niu_dan_ji_kai_guan_tou_ying_yi 82 | -------------------------------------------------------------------------------- /automations/disabled/sync.yaml: -------------------------------------------------------------------------------- 1 | - alias: 过道开关1同步调控 2 | trigger: 3 | - platform: state 4 | entity_id: switch.guo_dao_kai_guan_1, light.guo_dao_gui_deng 5 | action: 6 | - service_template: '{% if trigger.to_state.state == "on" %}homeassistant.turn_on{% else %}light.turn_off{% endif %}' 7 | data_template: 8 | entity_id: '{% if trigger.entity_id == "switch.guo_dao_kai_guan_1" %}light.guo_dao_gui_deng{% else %}switch.guo_dao_kai_guan_1{% endif %}' 9 | 10 | - alias: 过道开关2同步调控 11 | trigger: 12 | - platform: state 13 | entity_id: switch.guo_dao_kai_guan_2, light.guo_dao_gui_deng 14 | action: 15 | - service_template: '{% if trigger.to_state.state == "on" %}homeassistant.turn_on{% else %}light.turn_off{% endif %}' 16 | data_template: 17 | entity_id: '{% if trigger.entity_id == "switch.guo_dao_kai_guan_2" %}light.guo_dao_gui_deng{% else %}switch.guo_dao_kai_guan_2{% endif %}' 18 | -------------------------------------------------------------------------------- /automations/disabled/washer.yaml: -------------------------------------------------------------------------------- 1 | - alias: 阳台按钮单击—预约洗衣 2 | trigger: 3 | - platform: event 4 | event_type: xiaomi_aqara.click 5 | event_data: 6 | entity_id: binary_sensor.switch_158d0001e59b33 7 | click_type: single 8 | action: 9 | - service: vacuum.send_command 10 | data: 11 | entity_id: vacuum.yang_tai_xi_yi_ji 12 | command: turn_on;Mode=0;appoint 13 | 14 | - alias: 阳台按钮长按—预约洗烘 15 | trigger: 16 | - platform: event 17 | event_type: xiaomi_aqara.click 18 | event_data: 19 | entity_id: binary_sensor.switch_158d0001e59b33 20 | click_type: long_click_press 21 | action: 22 | - service: vacuum.send_command 23 | data: 24 | entity_id: vacuum.yang_tai_xi_yi_ji 25 | command: turn_on;Mode=2;appoint 26 | 27 | - alias: 阳台按钮双击—取消预约 28 | trigger: 29 | - platform: event 30 | event_type: xiaomi_aqara.click 31 | event_data: 32 | entity_id: binary_sensor.switch_158d0001e59b33 33 | click_type: double 34 | action: 35 | - service: vacuum.stop 36 | entity_id: vacuum.yang_tai_xi_yi_ji 37 | 38 | - alias: 浴室按钮单击—预约洗衣 39 | trigger: 40 | - platform: event 41 | event_type: xiaomi_aqara.click 42 | event_data: 43 | entity_id: binary_sensor.switch_158d000201a73f 44 | click_type: single 45 | action: 46 | - service: vacuum.send_command 47 | data: 48 | entity_id: vacuum.yu_shi_xi_yi_ji 49 | command: turn_on;Mode=0;sleep;sleep;appoint 50 | 51 | - alias: 浴室按钮长按—预约洗烘 52 | trigger: 53 | - platform: event 54 | event_type: xiaomi_aqara.click 55 | event_data: 56 | entity_id: binary_sensor.switch_158d000201a73f 57 | click_type: long_click_press 58 | action: 59 | - service: vacuum.send_command 60 | data: 61 | entity_id: vacuum.yu_shi_xi_yi_ji 62 | command: turn_on;Mode=2;sleep;sleep;appoint 63 | 64 | - alias: 浴室按钮双击—取消预约 65 | trigger: 66 | - platform: event 67 | event_type: xiaomi_aqara.click 68 | event_data: 69 | entity_id: binary_sensor.switch_158d000201a73f 70 | click_type: double 71 | action: 72 | - service: vacuum.stop 73 | entity_id: vacuum.yu_shi_xi_yi_ji 74 | -------------------------------------------------------------------------------- /automations/disabled/washroom.yaml: -------------------------------------------------------------------------------- 1 | - alias: 洗手间感应-开灯 2 | trigger: 3 | - platform: state 4 | entity_id: binary_sensor.motion_sensor_158d0001f4a238 5 | to: 'on' 6 | condition: 7 | # - condition: state 8 | # entity_id: light.xi_shou_jian_deng 9 | # state: 'off' 10 | - condition: time 11 | after: '18:00' 12 | before: '23:59' 13 | action: 14 | - service: light.turn_on 15 | entity_id: light.xi_shou_jian_deng 16 | - service: automation.turn_off 17 | entity_id: automation.xi_shou_jian_gan_ying_yan_shi_guan_deng 18 | - service: automation.turn_on 19 | entity_id: automation.xi_shou_jian_gan_ying_yan_shi_guan_deng 20 | 21 | - alias: 洗手间感应延时-关灯 22 | initial_state: false 23 | mode: restart 24 | trigger: 25 | - platform: time_pattern 26 | minutes: '/3' 27 | condition: 28 | - condition: state 29 | entity_id: binary_sensor.motion_sensor_158d0001f4a238 30 | state: 'off' 31 | - condition: state 32 | entity_id: binary_sensor.door_window_sensor_158d0003cf4735 33 | state: 'on' 34 | action: 35 | - service: light.turn_off 36 | entity_id: light.xi_shou_jian_deng 37 | - service: automation.turn_off 38 | entity_id: automation.xi_shou_jian_gan_ying_yan_shi_guan_deng 39 | -------------------------------------------------------------------------------- /automations/pm25.yaml: -------------------------------------------------------------------------------- 1 | - alias: 餐厅空气质量变化-调控净化器 2 | mode: restart 3 | trigger: 4 | - platform: state 5 | entity_id: sensor.can_ting_kong_qi_zhi_liang 6 | action: 7 | - service: zhiact.actuate 8 | data: 9 | sensor_id: sensor.can_ting_kong_qi_zhi_liang 10 | sensor_values: [10, 20, 50] 11 | entity_id: fan.can_ting_jing_hua_qi 12 | entity_attr: preset_mode 13 | entity_values: [自动, 中档, 高档] 14 | # condition_attr: oscillating 15 | # condition_values: [false] 16 | 17 | - alias: 次卧空气质量变化-调控净化器 18 | mode: restart 19 | trigger: 20 | - platform: state 21 | entity_id: sensor.ci_wo_kong_qi_zhi_liang 22 | action: 23 | - service: zhiact.actuate 24 | data: 25 | sensor_id: sensor.ci_wo_kong_qi_zhi_liang 26 | sensor_values: [15, 25, 35, 45, 50, 60, 70, 80, 90] 27 | alt_sensor_values: [15, 30, 40, 50, 60, 70, 80, 90, 100] 28 | entity_id: fan.ci_wo_jing_hua_qi 29 | entity_attr: favorite_level 30 | service_attr: percentage 31 | entity_values: [20, 30, 40, 50, 60, 70, 80, 90, 100] 32 | condition_attr: mode 33 | condition_values: [idle, auto, favorite] 34 | 35 | - alias: 儿童房空气质量变化-调控净化器 36 | mode: restart 37 | trigger: 38 | - platform: state 39 | entity_id: sensor.er_tong_fang_kong_qi_zhi_liang 40 | action: 41 | - service: zhiact.actuate 42 | data: 43 | sensor_id: sensor.er_tong_fang_kong_qi_zhi_liang 44 | sensor_values: [10, 20, 50] 45 | alt_sensor_values: [12, 30, 50] 46 | entity_id: fan.er_tong_fang_jing_hua_qi 47 | entity_attr: preset_mode 48 | entity_values: [自动, 中档, 高档] 49 | # condition_attr: oscillating 50 | # condition_values: [false] 51 | #delay: 0 52 | -------------------------------------------------------------------------------- /automations/sleeping.yaml: -------------------------------------------------------------------------------- 1 | - alias: 睡眠准备 2 | trigger: 3 | - platform: time 4 | at: '20:30:00' 5 | action: 6 | # - service: cover.close_cover 7 | # entity_id: cover.shu_fang_chuang_lian 8 | - service: climate.set_temperature 9 | data: 10 | entity_id: climate.zhu_wo_kong_diao 11 | temperature: 20 12 | hvac_mode: cool 13 | - service: climate.set_temperature 14 | data: 15 | entity_id: climate.er_tong_fang_kong_diao 16 | temperature: 23 17 | hvac_mode: cool 18 | - service: climate.set_fan_mode 19 | data: 20 | entity_id: climate.zhu_wo_kong_diao 21 | fan_mode: 五档 22 | - service: climate.set_fan_mode 23 | data: 24 | entity_id: climate.er_tong_fang_kong_diao 25 | fan_mode: 五档 26 | 27 | # - alias: 睡眠开始 28 | # trigger: 29 | # - platform: time 30 | # at: '21:30:00' 31 | # action: 32 | # - service: fan.oscillate 33 | # data: 34 | # entity_id: fan.ke_ting_xin_feng_ji 35 | # oscillating: false 36 | # - service: fan.oscillate 37 | # data: 38 | # entity_id: fan.zhu_wo_xin_feng_ji 39 | # oscillating: false 40 | # - service: zhimsg.guo_dao_xiao_ai 41 | # data: 42 | # message: 音量30 43 | 44 | - alias: 睡眠深入 45 | trigger: 46 | - platform: time 47 | at: '23:00:00' 48 | action: 49 | # - service: media_player.turn_off 50 | # entity_id: media_player.tian_mao_jing_ling 51 | - service: climate.set_fan_mode 52 | data: 53 | entity_id: climate.zhu_wo_kong_diao 54 | fan_mode: 一档 55 | - service: climate.set_fan_mode 56 | data: 57 | entity_id: climate.er_tong_fang_kong_diao 58 | fan_mode: 一档 59 | - service: climate.set_temperature 60 | data: 61 | entity_id: climate.zhu_wo_kong_diao 62 | temperature: 23 63 | - service: climate.set_temperature 64 | data: 65 | entity_id: climate.er_tong_fang_kong_diao 66 | temperature: 26 67 | 68 | - alias: 睡眠完成 69 | trigger: 70 | - platform: time 71 | at: '08:00:00' 72 | action: 73 | # - service: fan.oscillate 74 | # data: 75 | # entity_id: fan.ke_ting_xin_feng_ji 76 | # oscillating: true 77 | # - service: fan.oscillate 78 | # data: 79 | # entity_id: fan.zhu_wo_xin_feng_ji 80 | # oscillating: true 81 | # - service: zhimsg.guo_dao_xiao_ai 82 | # data: 83 | # message: 音量70 84 | # - service: fan.set_preset_mode 85 | # data: 86 | # entity_id: fan.zhu_wo_xin_feng_ji 87 | # preset_mode: 中档 88 | - service: climate.set_fan_mode 89 | data: 90 | entity_id: climate.zhu_wo_kong_diao 91 | fan_mode: 自动 92 | - service: climate.set_fan_mode 93 | data: 94 | entity_id: climate.er_tong_fang_kong_diao 95 | fan_mode: 自动 96 | - service: climate.set_temperature 97 | data: 98 | entity_id: climate.zhu_wo_kong_diao 99 | temperature: 22 100 | hvac_mode: cool 101 | - service: climate.set_temperature 102 | data: 103 | entity_id: climate.er_tong_fang_kong_diao 104 | temperature: 24 105 | hvac_mode: cool 106 | - service: climate.turn_off 107 | entity_id: climate.zhu_wo_kong_diao 108 | - service: climate.turn_off 109 | entity_id: climate.er_tong_fang_kong_diao 110 | # - service: climate.turn_off 111 | # entity_id: climate.shu_fang_kong_diao 112 | # - service: cover.open_cover 113 | # entity_id: cover.shu_fang_chuang_lian 114 | -------------------------------------------------------------------------------- /automations/temperature.yaml: -------------------------------------------------------------------------------- 1 | - alias: 客厅温度高-开空调 2 | initial_state: false 3 | trigger: 4 | # - platform: state 5 | # entity_id: binary_sensor.motion_sensor_158d0001d66ce9 6 | # to: 'on' 7 | - platform: state 8 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 9 | to: 'off' 10 | # - platform: numeric_state 11 | # entity_id: sensor.ke_ting_wen_du 12 | # above: 29 13 | # for: 14 | # minutes: 3 15 | condition: 16 | - condition: time 17 | after: '08:00' 18 | before: '21:00' 19 | - condition: numeric_state 20 | entity_id: sensor.ke_ting_wen_du 21 | above: 29 22 | - condition: state 23 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 24 | state: 'off' 25 | - condition: state 26 | entity_id: climate.ke_ting_kong_diao 27 | state: 'off' 28 | - condition: or 29 | conditions: 30 | - condition: state 31 | entity_id: sun.sun 32 | state: above_horizon 33 | - condition: state 34 | entity_id: light.living_light 35 | state: 'on' 36 | action: 37 | - service: climate.turn_on 38 | entity_id: climate.ke_ting_kong_diao 39 | 40 | - alias: 客厅温度正常-关空调 41 | initial_state: false 42 | trigger: 43 | - platform: state 44 | entity_id: binary_sensor.door_window_sensor_158d000228a52b 45 | to: 'on' 46 | for: 47 | minutes: 2 48 | - platform: numeric_state 49 | entity_id: sensor.ke_ting_wen_du 50 | below: 27 51 | for: 52 | minutes: 3 53 | condition: 54 | - condition: or 55 | conditions: 56 | - condition: state 57 | entity_id: climate.can_ting_kong_diao 58 | state: cool 59 | - condition: state 60 | entity_id: climate.can_ting_kong_diao 61 | state: heat 62 | - condition: state 63 | entity_id: climate.can_ting_kong_diao 64 | state: dry 65 | - condition: state 66 | entity_id: climate.can_ting_kong_diao 67 | state: fan_only 68 | - condition: state 69 | entity_id: climate.ke_ting_kong_diao 70 | state: cool 71 | - condition: state 72 | entity_id: climate.ke_ting_kong_diao 73 | state: heat 74 | - condition: state 75 | entity_id: climate.ke_ting_kong_diao 76 | state: dry 77 | - condition: state 78 | entity_id: climate.ke_ting_kong_diao 79 | state: fan_only 80 | action: 81 | - service: climate.turn_off 82 | entity_id: climate.ke_ting_kong_diao 83 | - service: climate.turn_off 84 | entity_id: climate.can_ting_kong_diao 85 | 86 | - alias: 主卧温度变化-调控空调 87 | mode: restart 88 | trigger: 89 | - platform: time 90 | at: '21:00:01' 91 | - platform: time 92 | at: '02:00:01' 93 | - platform: state 94 | entity_id: sensor.zhu_wo_wen_du 95 | condition: 96 | - condition: time 97 | after: '20:30' 98 | before: '07:30' 99 | action: 100 | - service: zhiact.actuate 101 | data: 102 | sensor_id: sensor.zhu_wo_wen_du 103 | sensor_values: [29, 29.2, 29.5, 29.7, 30] 104 | alt_sensor_values: [29.5, 29.8, 30, 30.5, 31] 105 | # sensor_id: climate.zhu_wo_kong_diao 106 | # sensor_attr: current_temperature 107 | # sensor_values: [29, 30, 31, 32, 33] 108 | # alt_sensor_values: [30, 31, 32, 33, 34] 109 | alt_time_range: [0, 8] 110 | entity_id: climate.zhu_wo_kong_diao 111 | entity_attr: fan_mode 112 | entity_values: [一档, 二档, 三档, 四档, 五档] 113 | 114 | - alias: 儿童房温度变化-调控空调 115 | mode: restart 116 | trigger: 117 | - platform: time 118 | at: '21:00:01' 119 | - platform: time 120 | at: '02:00:01' 121 | - platform: state 122 | entity_id: sensor.er_tong_fang_wen_du 123 | condition: 124 | - condition: time 125 | after: '20:30' 126 | before: '07:30' 127 | action: 128 | - service: zhiact.actuate 129 | data: 130 | sensor_id: sensor.er_tong_fang_wen_du 131 | sensor_values: [23.2, 23.4, 23.8, 24, 24.5] 132 | alt_sensor_values: [23.6, 23.8, 24, 24.5, 25] 133 | # sensor_id: climate.er_tong_fang_kong_diao 134 | # sensor_attr: current_temperature 135 | # sensor_values: [29, 30, 31, 32, 33] 136 | # alt_sensor_values: [30, 31, 32, 33, 34] 137 | alt_time_range: [0, 8] 138 | entity_id: climate.er_tong_fang_kong_diao 139 | entity_attr: fan_mode 140 | entity_values: [一档, 二档, 三档, 四档, 五档] 141 | # 142 | # - alias: 书房温度变化-调控空调 143 | # mode: restart 144 | # initial_state: false 145 | # trigger: 146 | # - platform: time 147 | # at: '21:30:01' 148 | # - platform: time 149 | # at: '02:00:01' 150 | # - platform: state 151 | # entity_id: sensor.shu_fang_wen_du 152 | # condition: 153 | # - condition: time 154 | # after: '20:30' 155 | # before: '07:30' 156 | # action: 157 | # - service: zhiact.actuate 158 | # data: 159 | # sensor_id: sensor.shu_fang_wen_du 160 | # sensor_values: [29.5, 30, 30.5, 31] 161 | # alt_sensor_values: [31, 32, 33, 34] 162 | # alt_time_range: [0, 8] 163 | # entity_id: climate.shu_fang_kong_diao 164 | # entity_attr: fan_mode 165 | # entity_values: [低档, 中档, 高档, 超高] 166 | 167 | # - alias: 书房温度变化-调控风扇 168 | # mode: restart 169 | # initial_state: false 170 | # trigger: 171 | # - platform: time 172 | # at: '20:30:01' 173 | # - platform: state 174 | # entity_id: sensor.shu_fang_wen_du 175 | # condition: 176 | # - condition: time 177 | # after: '20:30' 178 | # before: '07:58' 179 | # action: 180 | # - service: zhiact.actuate 181 | # data: 182 | # sensor_id: sensor.shu_fang_wen_du 183 | # sensor_values: [26, 27, 30, 32] 184 | # alt_sensor_values: [27, 29, 32, 34] 185 | # alt_time_range: [0, 8] 186 | # entity_id: fan.shu_fang_feng_shan 187 | # entity_attr: preset_mode 188 | # entity_values: [1档, 2档, 3档, 4档] 189 | 190 | - alias: 儿童房温度变化-调控风扇 191 | mode: restart 192 | trigger: 193 | - platform: time 194 | at: '20:00:01' 195 | - platform: state 196 | entity_id: sensor.er_tong_fang_wen_du 197 | condition: 198 | - condition: time 199 | after: '20:00' 200 | before: '07:58' 201 | action: 202 | - service: zhiact.actuate 203 | data: 204 | sensor_id: fan.er_tong_fang_feng_shan 205 | sensor_attr: temp_dec 206 | sensor_values: [24, 25, 28, 31] 207 | alt_sensor_values: [25, 27, 32, 34] 208 | alt_time_range: [0, 8] 209 | entity_id: fan.er_tong_fang_feng_shan 210 | entity_attr: preset_mode 211 | entity_values: [1档, 2档, 3档, 4档] 212 | 213 | - alias: 主卧温度变化-调控风扇 214 | mode: restart 215 | trigger: 216 | - platform: time 217 | at: '20:00:01' 218 | - platform: state 219 | entity_id: sensor.zhu_wo_wen_du 220 | condition: 221 | - condition: time 222 | after: '20:00' 223 | before: '07:58' 224 | action: 225 | - service: zhiact.actuate 226 | data: 227 | sensor_id: sensor.zhu_wo_wen_du 228 | sensor_values: [25, 27, 29.5, 31, 32] 229 | alt_sensor_values: [26, 29.5, 31, 33, 34] 230 | alt_time_range: [0, 8] 231 | entity_id: fan.zhu_wo_feng_shan 232 | entity_attr: preset_mode 233 | entity_values: [1档, 2档, 3档, 4档, 5档] 234 | -------------------------------------------------------------------------------- /configuration.yaml: -------------------------------------------------------------------------------- 1 | homeassistant: 2 | name: 旌启智家 3 | latitude: 30.23927 4 | longitude: 120.05633 5 | elevation: 32 6 | unit_system: metric 7 | currency: CNY 8 | country: CN 9 | time_zone: Asia/Shanghai 10 | external_url: !secret external_url 11 | internal_url: !secret external_url 12 | customize: !include customize.yaml 13 | 14 | http: 15 | server_port: 88 16 | ssl_key: /root/.homeassistant/ssl.key 17 | ssl_certificate: /root/.homeassistant/ssl.crt 18 | 19 | # default_config: 20 | 21 | # usb: 22 | # bluetooth: 23 | 24 | # backup 25 | # cloud: 26 | config: 27 | # energy: 28 | frontend: 29 | # mobile_app: 30 | system_health: 31 | # homeassistant_alerts: 32 | # webhook: 33 | # updater: 34 | 35 | # dhcp: 36 | # ssdp: 37 | # zeroconf: 38 | 39 | # input_boolean: 40 | # input_button: 41 | # input_datetime: 42 | # input_number: 43 | # input_select: 44 | input_text: 45 | # counter: 46 | # timer: 47 | 48 | #my: 49 | # tag: 50 | sun: 51 | zone: 52 | # stream: 53 | # media_source: 54 | 55 | # map: 56 | logbook: 57 | history: 58 | logger: 59 | default: warning 60 | logs: 61 | custom_components: debug 62 | 63 | recorder: 64 | purge_keep_days: 4 65 | exclude: 66 | domains: 67 | - sun 68 | - group 69 | - script 70 | - climate 71 | - automation 72 | - input_text 73 | - input_select 74 | - input_boolean 75 | 76 | device_tracker: 77 | - platform: ping 78 | scan_interval: 120 79 | hosts: 80 | touyingyi: 192.168.1.5 81 | ketingdianshi: 192.168.1.8 82 | zhuwodianshi: 192.168.1.9 83 | babashouji: 192.168.1.20 84 | mamashouji: 192.168.1.21 85 | dabaopingban: 192.168.1.24 86 | xiaozhipingban: 192.168.1.25 87 | ayishouji: 192.168.1.29 88 | 89 | person: 90 | - name: 爸爸 91 | id: baba 92 | device_trackers: device_tracker.babashouji 93 | - name: 妈妈 94 | id: mama 95 | device_trackers: device_tracker.mamashouji 96 | - name: 大宝 97 | id: dabao 98 | device_trackers: device_tracker.dabaopingban 99 | - name: 小智 100 | id: xiaozhi 101 | device_trackers: device_tracker.xiaozhipingban 102 | - name: 阿姨 103 | id: ayi 104 | device_trackers: device_tracker.ayishouji 105 | 106 | zhimi: 107 | username: !secret zhimi_username 108 | password: !secret zhimi_password 109 | 110 | modbus: 111 | - type: rtuovertcp 112 | host: 192.168.1.60 113 | port: 8899 114 | switches: 115 | # - name: 餐厅空调开关 116 | # address: 5 117 | # verify: 118 | # - name: 客厅空调开关 119 | # address: 9 120 | # verify: 121 | - name: 主卧空调开关 122 | address: 13 123 | # verify: 124 | # - name: 儿童房空调开关 125 | # address: 17 126 | # verify: 127 | 128 | climate: 129 | - platform: zhisaswell 130 | name: 客厅地暖 131 | host: 192.168.1.56 132 | device: 10382435CC059E60 133 | - platform: zhisaswell 134 | name: 主卧地暖 135 | host: 192.168.1.57 136 | device: 10382435CC059F72 137 | - platform: zhimodbus 138 | name: [餐厅空调, 客厅空调, 主卧空调, 儿童房空调] 139 | fan_mode: { registers: [6, 10, 14, 18] } 140 | fan_modes: { 自动: 0, 一档: 1, 二档: 2, 三档: 3, 四档: 4, 五档: 5 } 141 | hvac_mode: { registers: [5, 9, 13, 17] } 142 | hvac_modes: { 'off': 0, cool: 1, heat: 2, dry: 3, fan_only: 4 } 143 | hvac_off: { registers: [1, 2, 3, 4], register_type: coil } 144 | target_temperature: { registers: [4, 8, 12, 16] } 145 | temperature: { registers: [3, 6, 9, 12], register_type: input, scale: 0.1 } 146 | # - platform: zhiremote 147 | # name: 书房空调 148 | # sender: remote.shu_fang_yao_kong 149 | # command: mitsubishi_climate 150 | # sensor: sensor.shu_fang_wen_du 151 | 152 | cover: 153 | - platform: zhimijia 154 | name: 书房晾衣机 155 | did: 57379167 156 | - platform: zhiremote 157 | name: 书房窗帘 158 | sender: remote.shu_fang_yao_kong 159 | travel: 13 160 | command: dooya_cover 161 | - platform: zhiremote 162 | name: 书房幕布 163 | icon: mdi:projector-screen 164 | sender: remote.shu_fang_yao_kong 165 | travel: 45 166 | command: elite_screen 167 | 168 | media_player: 169 | - platform: zhiremote 170 | name: 书房投影仪 171 | icon: mdi:projector 172 | sender: remote.shu_fang_yao_kong 173 | command: viewsonic_projector 174 | sensor: device_tracker.touyingyi 175 | 176 | vacuum: 177 | - platform: zhimijia 178 | model: viomi.washer.v13 179 | name: 阳台洗衣机 180 | did: 410056542 181 | - platform: zhimijia 182 | model: viomi.washer.v33 183 | name: 浴室洗衣机 184 | did: 619765138 185 | # - platform: xiaomi_miio 186 | # name: 扫地机 187 | # host: SaoDiJi 188 | # token: !secret vacuum_token 189 | 190 | weather: 191 | - platform: zhicaiyun 192 | name: 天气 193 | 194 | zhiact: 195 | 196 | zhimsg: 197 | - platform: ding 198 | name: 钉钉信使 199 | token: !secret dingbot_token 200 | secret: !secret dingbot_secret 201 | - platform: miai 202 | name: 过道小爱 203 | did: 380205692 204 | model: x08c 205 | - platform: miai 206 | name: 次卧小爱 207 | did: 89463074 208 | model: lx01 209 | - platform: miai 210 | name: 儿童房小爱 211 | did: 267090026 212 | model: lx04 213 | 214 | zhibot: 215 | - platform: genie2 216 | file: !secret genie2bot_file 217 | text: !secret genie2bot_text 218 | token: !secret zhibot_token 219 | - platform: miai 220 | token: !secret zhibot_token 221 | - platform: ding 222 | token: !secret zhibot_token 223 | - platform: ding 224 | name: 过道小爱 225 | token: !secret zhibot_token 226 | - platform: ding 227 | name: 次卧小爱 228 | token: !secret zhibot_token 229 | - platform: ding 230 | name: 儿童房小爱 231 | token: !secret zhibot_token 232 | 233 | zhiaqara: 234 | name: 小米网关 235 | key: 3ECB50168D7F4AEB 236 | interface: 192.168.1.2 237 | 238 | zhibroad: 239 | # - name: 客厅遥控 240 | # host: 192.168.1.54 241 | - name: 书房遥控 242 | host: 192.168.1.53 243 | - name: 主卧插座 244 | host: 192.168.1.55 245 | 246 | zhibravia: 247 | - name: 客厅电视 248 | host: 192.168.1.8 249 | mac: 04:5D:4B:3F:8D:93 250 | - name: 主卧电视 251 | host: 192.168.1.9 252 | mac: 10:4F:A8:EF:7F:86 253 | 254 | zhilace: 255 | 256 | lovelace: 257 | mode: storage 258 | dashboards: 259 | zhilace-zone: 260 | mode: yaml 261 | title: 分区 262 | icon: mdi:home-floor-a 263 | show_in_sidebar: true 264 | filename: zhilace-zone.yaml 265 | zhilace-type: 266 | mode: yaml 267 | title: 分类 268 | icon: mdi:home-floor-b 269 | show_in_sidebar: true 270 | filename: zhilace-type.yaml 271 | zhilace-dash: 272 | mode: yaml 273 | title: 面板 274 | icon: mdi:microsoft 275 | show_in_sidebar: true 276 | filename: zhilace-dash.yaml 277 | 278 | # shell_command: 279 | #server_off: 'ssh root@192.168.1.2 shutdown -h now' 280 | # magic_on: "adb connect 192.168.1.15 && adb -s 192.168.1.15 shell 'input keyevent 82; am start -n com.thanksmister.iot.wallpanel/.ui.activities.WelcomeActivity'" 281 | # magic_off: "adb connect 192.168.1.15 && adb -s 192.168.1.15 shell 'input keyevent 82; input keyevent 26'" 282 | # x9300d_off: 'adb connect 192.168.1.9 && adb -s 192.168.1.9 shell reboot -p' 283 | # x9400d_off: 'adb connect 192.168.1.8 && adb -s 192.168.1.8 shell reboot -p' 284 | 285 | command_line: 286 | - switch: 287 | name: 聚合网盘 288 | icon: mdi:google-drive 289 | command_on: 'ssh -p 222 192.168.1.2 "docker start xiaoya"' 290 | command_off: 'ssh -p 222 192.168.1.2 "docker stop xiaoya"' 291 | command_state: 'ssh -p 222 192.168.1.2 "docker inspect -f {{json\ .State.Running}} xiaoya"' 292 | value_template: '{{ value == "true" }}' 293 | scan_interval: 600 294 | 295 | fan: !include fans.yaml 296 | mqtt: !include mqtt.yaml 297 | light: !include lights.yaml 298 | #sensor: !include sensors.yaml 299 | #switch: !include switches.yaml 300 | 301 | # scene: !include scenes.yaml 302 | # script: !include scripts.yaml 303 | homekit: !include homekit.yaml 304 | automation: !include_dir_merge_list automations 305 | -------------------------------------------------------------------------------- /custom_components/zhi: -------------------------------------------------------------------------------- 1 | ../modules/Zhi/custom_components/zhi -------------------------------------------------------------------------------- /custom_components/zhiact: -------------------------------------------------------------------------------- 1 | ../modules/ZhiAct/custom_components/zhiact -------------------------------------------------------------------------------- /custom_components/zhiaqara/__init__.py: -------------------------------------------------------------------------------- 1 | from homeassistant.components.xiaomi_aqara import DOMAIN, CONF_HOST, CONF_MAC, CONF_SID, CONF_KEY, CONF_INTERFACE, CONF_PORT, CONF_PROTOCOL 2 | from homeassistant.config_entries import ConfigEntry, SOURCE_USER 3 | from homeassistant.helpers.device_registry import format_mac 4 | from homeassistant.util import slugify 5 | from xiaomi_gateway import XiaomiGatewayDiscovery 6 | 7 | 8 | async def async_setup(hass, config): 9 | conf = config['zhiaqara'] 10 | name = conf['name'] 11 | unique_id = slugify(name) 12 | if hass.config_entries.async_get_entry(unique_id): 13 | return True 14 | 15 | interface = conf.get(CONF_INTERFACE, 'any') 16 | xiaomi = XiaomiGatewayDiscovery(interface) 17 | await hass.async_add_executor_job(xiaomi.discover_gateways) 18 | if len(xiaomi.gateways) == 0: 19 | return False 20 | 21 | gateway = list(xiaomi.gateways.values())[0] 22 | data = { 23 | CONF_HOST: gateway.ip_adress, 24 | CONF_PORT: gateway.port, 25 | CONF_MAC: format_mac(gateway.sid), 26 | CONF_INTERFACE: interface, 27 | CONF_PROTOCOL: gateway.proto, 28 | CONF_KEY: conf.get(CONF_KEY), 29 | CONF_SID: gateway.sid, 30 | } 31 | await hass.config_entries.async_add(ConfigEntry( 32 | version=1, 33 | minor_version=0, 34 | options={}, 35 | domain=DOMAIN, 36 | title=name, 37 | data= data, 38 | source=SOURCE_USER, 39 | unique_id=unique_id, 40 | entry_id=unique_id)) 41 | return True 42 | -------------------------------------------------------------------------------- /custom_components/zhiaqara/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "zhiaqara", 3 | "name": "Zhi Aqara Gateway Component", 4 | "documentation": "https://github.com/Yonsm/.homeassistant", 5 | "version": "1.0.1", 6 | "requirements": [], 7 | "dependencies": ["xiaomi_aqara"], 8 | "codeowners": ["@Yonsm"] 9 | } 10 | -------------------------------------------------------------------------------- /custom_components/zhibot: -------------------------------------------------------------------------------- 1 | ../modules/ZhiBot/custom_components/zhibot -------------------------------------------------------------------------------- /custom_components/zhibravia/__init__.py: -------------------------------------------------------------------------------- 1 | from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PIN 2 | from homeassistant.config_entries import ConfigEntry, SOURCE_USER 3 | from homeassistant.util import slugify 4 | 5 | 6 | async def async_setup(hass, config): 7 | confs = config['zhibravia'] 8 | for conf in confs: 9 | name = conf.get('name') 10 | unique_id = slugify(name) 11 | if hass.config_entries.async_get_entry(unique_id): 12 | continue 13 | 14 | host = conf[CONF_HOST] 15 | pin = conf.get(CONF_PIN, '0000') 16 | data = { 17 | CONF_HOST: host, 18 | CONF_MAC: conf.get(CONF_MAC) or await bravia_get_mac(hass, host, pin), 19 | CONF_PIN: pin 20 | } 21 | await hass.config_entries.async_add(ConfigEntry( 22 | version=1, 23 | minor_version=0, 24 | options={}, 25 | domain='braviatv', 26 | title=name, 27 | data=data, 28 | source=SOURCE_USER, 29 | unique_id=unique_id, 30 | entry_id=unique_id)) 31 | return True 32 | 33 | 34 | async def bravia_get_mac(hass, host, pin): 35 | from aiohttp import CookieJar 36 | from pybravia import BraviaClient 37 | from homeassistant.components.braviatv.const import ATTR_MAC 38 | from homeassistant.helpers.aiohttp_client import async_create_clientsession 39 | session = async_create_clientsession(hass, cookie_jar=CookieJar(unsafe=True, quote_cookie=False),) 40 | client = BraviaClient(host=host, session=session) 41 | await client.connect(psk=pin) 42 | await client.set_wol_mode(True) 43 | info = await client.get_system_info() 44 | # info = await hass.async_add_executor_job(client.get_system_info) 45 | if not info: 46 | return None 47 | return info[ATTR_MAC] 48 | -------------------------------------------------------------------------------- /custom_components/zhibravia/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "zhibravia", 3 | "name": "Zhi Bravia TV Component", 4 | "documentation": "https://github.com/Yonsm/.homeassistant", 5 | "version": "1.0.1", 6 | "requirements": [], 7 | "dependencies": ["braviatv"], 8 | "codeowners": ["@Yonsm"] 9 | } 10 | -------------------------------------------------------------------------------- /custom_components/zhibroad/__init__.py: -------------------------------------------------------------------------------- 1 | from json import load 2 | from homeassistant.const import CONF_NAME, CONF_HOST, CONF_MAC, CONF_TYPE, CONF_TIMEOUT 3 | from homeassistant.config_entries import ConfigEntry, SOURCE_USER 4 | from homeassistant.util import slugify 5 | import broadlink as blk 6 | 7 | 8 | async def async_setup(hass, config): 9 | confs = config['zhibroad'] 10 | for conf in confs: 11 | name = conf[CONF_NAME] 12 | unique_id = slugify(name) 13 | if hass.config_entries.async_get_entry(unique_id): 14 | continue 15 | 16 | try: 17 | device = await hass.async_add_executor_job(blk.hello, conf[CONF_HOST], 80, 5) 18 | data = { 19 | CONF_HOST: device.host[0], 20 | CONF_MAC: device.mac.hex(), 21 | CONF_TYPE: device.devtype, 22 | CONF_TIMEOUT: device.timeout, 23 | } 24 | await hass.config_entries.async_add(ConfigEntry( 25 | version=1, 26 | minor_version=0, 27 | options={}, 28 | domain='broadlink', 29 | title=name, 30 | data=data, 31 | source=SOURCE_USER, 32 | unique_id=unique_id, 33 | entry_id=unique_id)) 34 | except Exception as e: 35 | import logging 36 | logging.getLogger(__name__).error("Could not find %s, %s", name, e) 37 | return True 38 | -------------------------------------------------------------------------------- /custom_components/zhibroad/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "zhibroad", 3 | "name": "Zhi Broadlink Component", 4 | "documentation": "https://github.com/Yonsm/.homeassistant", 5 | "version": "1.0.1", 6 | "requirements": [], 7 | "dependencies": ["broadlink"], 8 | "codeowners": ["@Yonsm"] 9 | } 10 | -------------------------------------------------------------------------------- /custom_components/zhicaiyun: -------------------------------------------------------------------------------- 1 | ../modules/ZhiCaiYun/custom_components/zhicaiyun -------------------------------------------------------------------------------- /custom_components/zhilace: -------------------------------------------------------------------------------- 1 | ../modules/ZhiLace/custom_components/zhilace -------------------------------------------------------------------------------- /custom_components/zhimi: -------------------------------------------------------------------------------- 1 | ../modules/ZhiMi/custom_components/zhimi -------------------------------------------------------------------------------- /custom_components/zhimijia: -------------------------------------------------------------------------------- 1 | ../modules/ZhiMiJia/custom_components/zhimijia -------------------------------------------------------------------------------- /custom_components/zhimodbus: -------------------------------------------------------------------------------- 1 | ../modules/ZhiModBus/custom_components/zhimodbus -------------------------------------------------------------------------------- /custom_components/zhimsg: -------------------------------------------------------------------------------- 1 | ../modules/ZhiMsg/custom_components/zhimsg -------------------------------------------------------------------------------- /custom_components/zhiremote: -------------------------------------------------------------------------------- 1 | ../modules/ZhiRemote/custom_components/zhiremote -------------------------------------------------------------------------------- /custom_components/zhisaswell: -------------------------------------------------------------------------------- 1 | ../modules/ZhiSaswell/custom_components/zhisaswell -------------------------------------------------------------------------------- /customize.yaml: -------------------------------------------------------------------------------- 1 | person.ba_ba: 2 | dash_extra_forced: 客厅摄像机 3 | dash_click: mihome://device?did=1029782073&uid=8816080&server=cn 4 | person.ma_ma: 5 | dash_extra_forced: 主卧摄像机 6 | dash_click: mihome://device?did=63538723&uid=8816080&server=cn 7 | person.da_bao: 8 | dash_extra_forced: 儿童房摄像机 9 | dash_click: mihome://device?did=130040912&uid=8816080&server=cn 10 | person.xiao_zhi: 11 | dash_extra_forced: 过道摄像机 12 | dash_click: hejiaqin:// 13 | person.a_yi: 14 | dash_extra_forced: 厨房摄像机 15 | dash_click: mihome://device?did=449689101&uid=8816080&server=cn 16 | binary_sensor.cube_158d0002a66db1: 17 | friendly_name: 儿童房魔方 18 | binary_sensor.door_window_sensor_158d0001f3e5be: 19 | friendly_name: 入户门 20 | dash_extra_forced: 老家摄像机 21 | dash_click: jooancloud.com:// 22 | binary_sensor.door_window_sensor_158d0001f3d2d1: 23 | friendly_name: 厨房门 24 | dash_extra_forced: 定南小阳台 25 | dash_click: smarthome.cloud.189.cn:// 26 | binary_sensor.door_window_sensor_158d00041c74da: 27 | friendly_name: 过道门 28 | dash_extra_forced: 定南客厅 29 | dash_click: mihome://device?did=1039136862&uid=8816080&server=cn 30 | binary_sensor.door_window_sensor_158d0003cf4735: 31 | friendly_name: 洗手间门 32 | dash_extra_forced: 定南儿童房 33 | dash_click: mihome://device?did=yunyi.BSYZ92EXT4NRDJSK111A&uid=8816080&server=cn 34 | binary_sensor.door_window_sensor_158d0004611461: 35 | friendly_name: 浴室门 36 | dash_extra_forced: 定南主卧 37 | dash_click: mihome://device?did=79750727&uid=8816080&server=cn 38 | binary_sensor.door_window_sensor_158d000228a52b: 39 | friendly_name: 阳台门 40 | dash_extra_forced: 定南大阳台 41 | dash_click: videogo:// 42 | binary_sensor.motion_sensor_158d0001d66ce9: 43 | friendly_name: 过道感应 44 | binary_sensor.motion_sensor_158d0001f4a238: 45 | friendly_name: 厨房感应 46 | binary_sensor.motion_sensor_158d0003d0d46e: 47 | friendly_name: 衣柜感应 48 | binary_sensor.switch_158d0001e59b33: 49 | friendly_name: 阳台按钮 50 | binary_sensor.switch_158d000201a73f: 51 | friendly_name: 浴室按钮 52 | binary_sensor.switch_158d00054e98b0: 53 | friendly_name: 主卧按钮 54 | binary_sensor.switch_158d00083a4207: 55 | friendly_name: 书房按钮 56 | cover.curtain_158d0003f7951d: 57 | friendly_name: 过道卷帘 58 | cover.curtain_158d000405d535: 59 | friendly_name: 主卧窗帘 60 | cover.curtain_158d00042cf265: 61 | friendly_name: 儿童房窗帘 62 | fan.can_ting_jing_hua_qi: 63 | dash_icon: ${sensor.can_ting_kong_qi_zhi_liang} 64 | fan.ci_wo_jing_hua_qi: 65 | dash_icon: ${aqi} 66 | fan.er_tong_fang_feng_shan: 67 | dash_icon: ${temp_dec} 68 | fan.er_tong_fang_jing_hua_qi: 69 | dash_icon: ${sensor.er_tong_fang_kong_qi_zhi_liang} 70 | fan.ke_ting_xin_feng_ji: 71 | dash_icon: ${co2} 72 | fan.zhu_wo_xin_feng_ji: 73 | dash_icon: ${co2} 74 | light.er_tong_fang_tai_deng: 75 | icon: mdi:lamp 76 | light.gateway_light_34ce0090901a: 77 | friendly_name: 过道壁灯 78 | icon: mdi:car-light-high 79 | sensor.can_ting_kong_qi_zhi_liang: 80 | dash_click: /zhilace-type 81 | dash_extra_forced: 分类 82 | dash_relation: fan.can_ting_jing_hua_qi 83 | sensor.can_ting_wen_du: 84 | dash_click: /zhilace-zone/can_ting 85 | dash_extra_forced: 餐厅 86 | sensor.ci_wo_kong_qi_zhi_liang: 87 | dash_click: https://qq.ip138.com/day 88 | dash_extra_forced: 万年历 89 | sensor.ci_wo_wen_du: 90 | dash_click: /zhilace-zone/ci_wo 91 | dash_extra_forced: 次卧 92 | sensor.er_tong_fang_er_yang_hua_tan: 93 | dash_extra_forced: 数字电视 94 | dash_click: /local/iptv.html 95 | sensor.er_tong_fang_kong_qi_zhi_liang: 96 | dash_click: https://www.lewei50.com/u/g/33981 97 | dash_relation: fan.er_tong_fang_jing_hua_qi 98 | sensor.er_tong_fang_wen_du: 99 | dash_click: /zhilace-zone/er_tong_fang 100 | dash_extra_forced: 儿童房 101 | sensor.illumination_34ce0090901a: 102 | friendly_name: 过道亮度 103 | dash_click: /zhilace-zone/guo_dao 104 | dash_extra_forced: 过道 105 | sensor.ke_ting_er_yang_hua_tan: 106 | dash_extra_forced: 路由器 107 | dash_click: !secret router_url 108 | sensor.ke_ting_kong_qi_zhi_liang: 109 | dash_click: /zhilace-zone 110 | dash_extra_forced: 分区 111 | sensor.ke_ting_wen_du: 112 | dash_click: /zhilace-zone/ke_ting 113 | dash_extra_forced: 客厅 114 | sensor.shu_fang_er_yang_hua_tan: 115 | dash_extra_forced: 聚合网盘 116 | dash_click: !secret wangpan_url 117 | sensor.shu_fang_wen_du: 118 | dash_click: /zhilace-zone/shu_fang 119 | dash_extra_forced: 书房 120 | sensor.yang_tai_kong_qi_zhi_liang: 121 | dash_click: https://www.lewei50.com/u/g/34131 122 | dash_order: '3' 123 | sensor.yang_tai_shi_du: 124 | dash_click: https://m.weathercn.com/index.do?id=106832 125 | dash_extra_forced: 杭州天气 126 | dash_order: '2' 127 | sensor.yang_tai_wen_du: 128 | dash_click: http://m.nmc.cn/publish/forecast/AZJ/hangzhou.html 129 | dash_extra_forced: 中央气象台 130 | dash_order: '1' 131 | sensor.zhu_wo_er_yang_hua_tan: 132 | dash_extra_forced: 小主机 133 | dash_click: !secret server_url 134 | sensor.zhu_wo_kong_qi_zhi_liang: 135 | dash_click: /local/aha.html 136 | dash_extra_forced: 啊哈网校 137 | dash_relation: fan.zhu_wo_jing_hua_qi 138 | sensor.zhu_wo_wen_du: 139 | dash_click: /zhilace-zone/zhu_wo 140 | dash_extra_forced: 主卧 141 | sun.sun: 142 | friendly_name: 日照 143 | switch.zhu_wo_cha_zuo: 144 | device_class: outlet 145 | icon: mdi:head-flash 146 | switch.zhu_wo_kong_tiao_kai_guan: 147 | hidden: true 148 | switch.guo_dao_kai_guan_1: 149 | hidden: true 150 | switch.guo_dao_kai_guan_2: 151 | hidden: true 152 | switch.plug_158d0003a58422: 153 | friendly_name: 客厅插座 154 | light.shu_fang_yin_xiang: 155 | dash_extra: effect 156 | dash_extra_click: mqttPublish("YinXiang/relay/0/set", "toggle") 157 | switch.wang_luo_cun_chu: 158 | icon: mdi:nas 159 | weather.tian_qi: 160 | dash_click: https://caiyunapp.com/weather 161 | dash_name: ${temperature}℃ ${humidity}% ${pm25}μg 162 | switch.ju_he_wang_pan: 163 | dash_extra: 查看 164 | dash_extra_click: !secret wangpan_url 165 | -------------------------------------------------------------------------------- /extras/deprecated/aircat/__init__.py: -------------------------------------------------------------------------------- 1 | """The Phicomm M1 aircat component.""" 2 | -------------------------------------------------------------------------------- /extras/deprecated/aircat/sensor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import json 4 | import socket 5 | import select 6 | import logging 7 | 8 | # Bridge receive: b'\xaaO\x01UA\xf19\x8f\x0b\x00\x00\x00\x00\x00\x00\x00\x00\xb0\xf8\x93\x1f\x14U\x00Z\x00\x00\x02{"sleep":"1","startTime":82800,"endTime":21600,"type":1}\xff#END#' 9 | # Bridge receive: b'\xaaO\x01UA\xf19\x8f\x0b\x00\x00\x00\x00\x00\x00\x00\x00\xb0\xf8\x93\x1f\x14U\x00>\x00\x00\x02{"brightness":"25","type":2}\xff#END#' 10 | # Bridge receive: b'\xaaO\x01UA\xf19\x8f\x0b\x00\x00\x00\x00\x00\x00\x00\x00\xb0\xf8\x93\x1f\x14U\x007\x00\x00\x02{"type":5,"status":1}\xff#END#' 11 | 12 | _LOGGER = logging.getLogger(__name__) 13 | 14 | 15 | class AirCatData: 16 | """Class for handling the data retrieval.""" 17 | 18 | def __init__(self): 19 | """Initialize the data object.""" 20 | self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 21 | self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 22 | self._socket.settimeout(1) 23 | self._socket.bind(('', 9000)) # aircat.phicomm.com 24 | self._socket.listen(5) 25 | self._rlist = [self._socket] 26 | self._times = 0 27 | self.devs = {} 28 | 29 | def shutdown(self): 30 | """Shutdown.""" 31 | if self._socket is not None: 32 | #_LOGGER.debug("Socket shutdown") 33 | self._socket.close() 34 | self._socket = None 35 | 36 | def loop(self): 37 | while True: 38 | self.update(None) # None = wait forever 39 | 40 | def update(self, timeout=0): # 0 = return right now 41 | rfd, wfd, efd = select.select(self._rlist, [], [], timeout) 42 | for fd in rfd: 43 | try: 44 | if fd is self._socket: 45 | conn, addr = self._socket.accept() 46 | _LOGGER.debug('Connected %s', addr) 47 | self._rlist.append(conn) 48 | conn.settimeout(1) 49 | else: 50 | self.handle(fd) 51 | except: 52 | #import traceback 53 | #_LOGGER.error('Exception: %s', traceback.format_exc()) 54 | pass 55 | 56 | def handle(self, conn): 57 | """Handle connection.""" 58 | data = conn.recv( 59 | 4096) # If connection is closed, recv() will result a timeout exception and receive '' next time, so we can purge connection list 60 | if not data: 61 | _LOGGER.debug('Closed %s', conn) 62 | self._rlist.remove(conn) 63 | conn.close() 64 | return 65 | 66 | if data.startswith(b'GET'): 67 | _LOGGER.debug('Request from HTTP -->\n%s', data) 68 | conn.sendall(b'HTTP/1.0 200 OK\nContent-Type: text/json\n\n' + 69 | json.dumps(self.devs, indent=2).encode('utf-8')) 70 | self._rlist.remove(conn) 71 | conn.close() 72 | return 73 | 74 | end = data.rfind(b'\xff#END#') 75 | payload = data.rfind(b'{', 0, end) 76 | 77 | self._times += 1 78 | if payload >= 11: 79 | mac = ''.join(['%02X' % (x if isinstance(x, int) else ord(x)) 80 | for x in data[payload-11:payload-5]]) 81 | try: 82 | jsonStr = data[payload:end].decode('utf-8') 83 | attributes = json.loads(jsonStr) 84 | self.devs[mac] = attributes 85 | _LOGGER.debug('%d Received %s: %s', 86 | self._times, mac, attributes) 87 | except: 88 | _LOGGER.error('%d Received invalid: %s', self._times, data) 89 | else: 90 | _LOGGER.debug('%d Received short payload: %s', self._times, data) 91 | 92 | response = self.response(data, payload, end) 93 | if response: 94 | _LOGGER.debug(' Response %s\n', response) 95 | conn.sendall(response) 96 | 97 | def response(self, data, payload, end): 98 | # begin(17) + mac(6)+size(5) + payload(0~) + end(6) 99 | if payload == -1 and end >= 28 and data[end-1] != (125 if isinstance(data[end-1], int) else '}'): 100 | _LOGGER.info(' Control message: %s', data) 101 | payload = end 102 | self._times = 0 103 | else: 104 | if self._times % 5 != 0: 105 | return None 106 | 107 | if payload >= 28: 108 | prefix = data[payload-28:payload-5] 109 | else: 110 | _LOGGER.error(' Invalid prefix: %s', data) 111 | #prefix = b'\xaaO\x01UA\xf19\x8f\x0b\x00\x00\x00\x00\x00\x00\x00\x00\xb0\xf8\x93\x1f\x14U' 112 | return None 113 | 114 | return prefix + b'\x00\x37\x00\x00\x02{"type":5,"status":1}\xff#END#' 115 | 116 | 117 | class AirCatBridge(AirCatData): 118 | """Class for handling the data retrieval.""" 119 | 120 | def __init__(self): 121 | """Initialize the data object.""" 122 | super(AirCatBridge, self).__init__() 123 | self._phicomm = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 124 | self._phicomm.settimeout(5) 125 | self._phicomm.connect(('47.102.38.171', 9000)) 126 | 127 | def shutdown(self): 128 | """Shutdown.""" 129 | super(AirCatBridge, self).shutdown() 130 | if self._phicomm is not None: 131 | self._phicomm.close() 132 | self._phicomm = None 133 | 134 | def response(self, data, payload, end): 135 | print(' Bridge send: %s' % data) 136 | self._phicomm.sendall(data) 137 | try: 138 | response = self._phicomm.recv(4096) 139 | print(' Bridge receive: %s' % response) 140 | return response 141 | except: 142 | print(' Bridge receive: None!') 143 | return super(AirCatBridge, self).response(data, payload, end) 144 | 145 | 146 | if __name__ == '__main__': 147 | _LOGGER.setLevel(logging.DEBUG) 148 | _LOGGER.addHandler(logging.StreamHandler()) 149 | aircat = AirCatBridge() 150 | try: 151 | aircat.loop() 152 | except KeyboardInterrupt: 153 | pass 154 | aircat.shutdown() 155 | exit(0) 156 | 157 | 158 | """ 159 | Support for AirCat air sensor. 160 | 161 | For more details about this platform, please refer to the documentation at 162 | https://home-assistant.io/components/sensor.aircat/ 163 | """ 164 | from homeassistant.helpers import config_validation as cv 165 | from homeassistant.helpers.entity import Entity 166 | from homeassistant.const import CONF_NAME, CONF_MAC, CONF_SENSORS, TEMP_CELSIUS 167 | from homeassistant.components.sensor import PLATFORM_SCHEMA 168 | import voluptuous as vol 169 | 170 | 171 | SENSOR_PM25 = 'pm25' 172 | SENSOR_HCHO = 'hcho' 173 | SENSOR_TEMPERATURE = 'temperature' 174 | SENSOR_HUMIDITY = 'humidity' 175 | 176 | DEFAULT_NAME = 'AirCat' 177 | DEFAULT_SENSORS = [SENSOR_PM25, SENSOR_HCHO, 178 | SENSOR_TEMPERATURE, SENSOR_HUMIDITY] 179 | 180 | SENSOR_MAP = { 181 | SENSOR_PM25: ('µg/m³', 'blur'), 182 | SENSOR_HCHO: ('mg/m³', 'biohazard'), 183 | SENSOR_TEMPERATURE: (TEMP_CELSIUS, 'thermometer'), 184 | SENSOR_HUMIDITY: ('%', 'water-percent') 185 | } 186 | 187 | PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ 188 | vol.Optional(CONF_NAME, default=DEFAULT_NAME): vol.Any(cv.string, list), 189 | vol.Optional(CONF_MAC, default=['']): 190 | vol.All(cv.ensure_list, vol.Length(min=1)), 191 | vol.Optional(CONF_SENSORS, default=DEFAULT_SENSORS): 192 | vol.All(cv.ensure_list, vol.Length(min=1), [vol.In(SENSOR_MAP)]), 193 | }) 194 | 195 | # True: Thread mode, False: HomeAssistant update/poll mode 196 | AIRCAT_SENSOR_THREAD_MODE = True 197 | 198 | 199 | def setup_platform(hass, conf, add_devices, discovery_info=None): 200 | """Set up the AirCat sensor.""" 201 | name = conf[CONF_NAME] 202 | macs = conf[CONF_MAC] 203 | sensors = conf[CONF_SENSORS] 204 | 205 | aircat = AirCatData() 206 | count = len(macs) 207 | 208 | if AIRCAT_SENSOR_THREAD_MODE: 209 | import threading 210 | threading.Thread(target=aircat.loop).start() 211 | else: 212 | AirCatSensor.times = 0 213 | AirCatSensor.interval = len(sensors) * count 214 | 215 | devices = [] 216 | for index in range(count): 217 | device_name = name[index] if isinstance(name, list) else name + str(index + 1) 218 | for sensor_index in range(len(sensors)): 219 | sensor_type = sensors[sensor_index] 220 | sensor_name = device_name[sensor_index] if isinstance(device_name, list) else device_name + ' ' + sensor_type 221 | devices.append(AirCatSensor(aircat, sensor_name, macs[index], sensor_type)) 222 | 223 | add_devices(devices) 224 | 225 | 226 | class AirCatSensor(Entity): 227 | """Implementation of a AirCat sensor.""" 228 | 229 | def __init__(self, aircat, name, mac, sensor_type): 230 | """Initialize the AirCat sensor.""" 231 | unit, icon = SENSOR_MAP[sensor_type] 232 | self._name = name 233 | self._mac = mac 234 | self._sensor_type = sensor_type 235 | self._unit = unit 236 | self._icon = 'mdi:' + icon 237 | self._aircat = aircat 238 | 239 | @property 240 | def name(self): 241 | """Return the name of the sensor.""" 242 | return self._name 243 | 244 | @property 245 | def icon(self): 246 | """Return the icon of the sensor.""" 247 | return self._icon 248 | 249 | @property 250 | def unit_of_measurement(self): 251 | """Return the unit the value is expressed in.""" 252 | return self._unit 253 | 254 | @property 255 | def device_class(self): 256 | """Return the class of this device, from component DEVICE_CLASSES.""" 257 | return self._sensor_type 258 | 259 | @property 260 | def available(self): 261 | """Return if the sensor data are available.""" 262 | return self.attributes is not None 263 | 264 | @property 265 | def state(self): 266 | """Return the state of the device.""" 267 | attributes = self.attributes 268 | if attributes is None: 269 | return None 270 | state = attributes['value' if self._sensor_type == SENSOR_PM25 else self._sensor_type] 271 | if self._sensor_type == SENSOR_PM25: 272 | return state 273 | elif self._sensor_type == SENSOR_HCHO: 274 | return float(state) / 1000 275 | else: 276 | return round(float(state), 1) 277 | 278 | @property 279 | def extra_state_attributes(self): 280 | """Return the state attributes.""" 281 | return self.attributes if self._sensor_type == SENSOR_PM25 else None 282 | 283 | @property 284 | def attributes(self): 285 | """Return the attributes of the device.""" 286 | if self._mac: 287 | return self._aircat.devs.get(self._mac) 288 | for mac in self._aircat.devs: 289 | return self._aircat.devs[mac] 290 | return None 291 | 292 | def update(self): 293 | """Update state.""" 294 | if AIRCAT_SENSOR_THREAD_MODE: 295 | #_LOGGER.debug("Running in thread mode") 296 | return 297 | 298 | if AirCatSensor.times % AirCatSensor.interval == 0: 299 | # _LOGGER.debug("Begin update %d: %s %s", AirCatSensor.times, 300 | # self._mac, self._sensor_type) 301 | self._aircat.update() 302 | # _LOGGER.debug("Ended update %d: %s %s", AirCatSensor.times, 303 | # self._mac, self._sensor_type) 304 | AirCatSensor.times += 1 305 | 306 | def shutdown(self, event): 307 | """Signal shutdown.""" 308 | # _LOGGER.debug('Shutdown') 309 | self._aircat.shutdown() 310 | -------------------------------------------------------------------------------- /extras/deprecated/hagenie/access.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | 4 | import os, sys, cgi 5 | 6 | print('Content-Type: text/json\r\n') 7 | 8 | str = "HTTP_CLIENT_IP=%s\nHTTP_X_FORWARDED_FOR=%s\nREMOTE_ADDR=%s\n\n" % (os.getenv("HTTP_CLIENT_IP"), os.getenv("HTTP_X_FORWARDED_FOR"), os.getenv("REMOTE_ADDR")) 9 | sys.stderr.write(str) 10 | 11 | # Log HTTP request 12 | REQUEST_METHOD = os.getenv('REQUEST_METHOD') 13 | #if REQUEST_METHOD: 14 | try: 15 | sys.stderr.write(REQUEST_METHOD + ' ' + os.environ['SCRIPT_NAME'] + '?' + os.environ['QUERY_STRING'] + '\n') 16 | #if REQUEST_METHOD == 'POST': 17 | # sys.stderr.write(sys.stdin.read() + '\n') 18 | form = cgi.FieldStorage() 19 | for key in form.keys(): 20 | sys.stderr.write(key + '=' + form[key].value + '\n') 21 | #access_token = form['client_id'].value + '?' + form['client_secret'].value # Trick: Use access_token to pass client_id and client_secret 22 | access_token = form['code'].value if 'code' in form else form['refresh_token'].value 23 | except: 24 | import traceback 25 | sys.stderr.write(traceback.format_exc()) 26 | access_token = 'http_192.168.1.10_8123_password' 27 | 28 | # Print content 29 | print('{\ 30 | "access_token": "' + access_token + '",\ 31 | "expires_in": 3600,\ 32 | "token_type": "Bearer",\ 33 | "scope": null,\ 34 | "refresh_token": "' + access_token + '"\ 35 | }') 36 | -------------------------------------------------------------------------------- /extras/deprecated/hagenie/authorize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | 4 | import os, sys 5 | from urllib import parse 6 | 7 | print('Content-Type: text/html\r\n') 8 | 9 | str = "HTTP_CLIENT_IP=%s\nHTTP_X_FORWARDED_FOR=%s\nREMOTE_ADDR=%s\n\n" % (os.getenv("HTTP_CLIENT_IP"), os.getenv("HTTP_X_FORWARDED_FOR"), os.getenv("REMOTE_ADDR")) 10 | sys.stderr.write(str) 11 | 12 | qs = os.environ['QUERY_STRING'] 13 | if not qs: 14 | sn = os.environ['SCRIPT_NAME'].split('?') 15 | if len(sn) > 1: 16 | qs = sn[1] 17 | form = parse.parse_qs(qs) 18 | 19 | if 'HAPI' in form and 'redirect_uri' in form: 20 | url = form['redirect_uri'][0] + '&code=' + form['HAPI'][0] + '&state=' + form['state'][0] 21 | 22 | print("转跳中..."); 23 | exit(0) 24 | 25 | print(""" 26 | 27 | 28 | 欢迎使用 HAGenie - 天猫精灵 + HomeAssistant 网关

29 |
30 |

地址:
31 | * 32 |

密码:
33 |

34 |


35 | 36 |

37 | 38 | """) 39 | -------------------------------------------------------------------------------- /extras/deprecated/hagenie/gate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | 4 | # http://doc-bot.tmall.com/docs/doc.htm?treeId=393&articleId=107674&docType=1 5 | 6 | import os, sys, json 7 | try: 8 | from urllib2 import urlopen 9 | reload(sys) 10 | sys.setdefaultencoding('utf8') 11 | except ImportError: 12 | from urllib.request import urlopen 13 | 14 | # 15 | def log(message): 16 | pass 17 | sys.stderr.write(message + '\n') 18 | 19 | str = "HTTP_CLIENT_IP=%s\nHTTP_X_FORWARDED_FOR=%s\nREMOTE_ADDR=%s\n\n" % (os.getenv("HTTP_CLIENT_IP"), os.getenv("HTTP_X_FORWARDED_FOR"), os.getenv("REMOTE_ADDR")) 20 | sys.stderr.write(str) 21 | 22 | 23 | # Log HTTP payload 24 | REQUEST_METHOD = os.getenv('REQUEST_METHOD') 25 | if REQUEST_METHOD: 26 | log(REQUEST_METHOD + ' ' + os.environ['SCRIPT_NAME'] + '?' + os.environ['QUERY_STRING'] + '\n') 27 | #if payload_METHOD == 'POST': 28 | # log(sys.stdin.read()) 29 | 30 | 31 | _haUrl = None 32 | _accessToken = None 33 | _checkAlias = False 34 | def validateToken(payload): 35 | if 'accessToken' in payload: 36 | accessToken = payload['accessToken'] 37 | if accessToken.startswith('http'): 38 | global _haUrl 39 | global _checkAlias 40 | global _accessToken 41 | parts = accessToken.split('_') 42 | _checkAlias = parts[1][-1:].isupper() # Trick 43 | _haUrl = parts[0] + '://' + parts[1] + ':' + parts[2] + '/api/%s' 44 | _accessToken = parts[3] 45 | #log('HA URL: ' + _haUrl + ', accessToken: ' + _accessToken) 46 | return True 47 | return False 48 | 49 | 50 | def haCall(cmd, data=None): 51 | url = _haUrl % cmd 52 | method = 'POST' if data else 'GET' 53 | log('HA ' + method + ' ' + url) 54 | if data: 55 | log(data) 56 | 57 | headers = {'Authorization': 'Bearer ' + _accessToken, 'Content-Type': 'application/json'} if _accessToken else None 58 | 59 | if url.startswith('https') or headers: # We need extra requests lib for HTTPS POST 60 | import requests 61 | result = requests.request(method, url, data=data, headers=headers, timeout=3).text 62 | else: 63 | result = urlopen(url, data=data, timeout=3).read() 64 | 65 | #log('HA RESPONSE: ' + result) 66 | return json.loads(result) 67 | 68 | 69 | def errorResult(errorCode, messsage=None): 70 | messages = { 71 | 'INVALIDATE_CONTROL_ORDER': 'invalidate control order', 72 | 'SERVICE_ERROR': 'service error', 73 | 'DEVICE_NOT_SUPPORT_FUNCTION': 'device not support', 74 | 'INVALIDATE_PARAMS': 'invalidate params', 75 | 'DEVICE_IS_NOT_EXIST': 'device is not exist', 76 | 'IOT_DEVICE_OFFLINE': 'device is offline', 77 | 'ACCESS_TOKEN_INVALIDATE': ' access_token is invalidate' 78 | } 79 | return {'errorCode': errorCode, 'message': messsage if messsage else messages[errorCode]} 80 | 81 | 82 | DEVICE_TYPES = [ 83 | 'television',#: '电视', 84 | 'light',#: '灯', 85 | 'aircondition',#: '空调', 86 | 'airpurifier',#: '空气净化器', 87 | 'outlet',#: '插座', 88 | 'switch',#: '开关', 89 | 'roboticvacuum',#: '扫地机器人', 90 | 'curtain',#: '窗帘', 91 | 'humidifier',#: '加湿器', 92 | 'fan',#: '风扇', 93 | 'bottlewarmer',#: '暖奶器', 94 | 'soymilkmaker',#: '豆浆机', 95 | 'kettle',#: '电热水壶', 96 | 'watercooler',#: '饮水机', 97 | 'cooker',#: '电饭煲', 98 | 'waterheater',#: '热水器', 99 | 'oven',#: '烤箱', 100 | 'waterpurifier',#: '净水器', 101 | 'fridge',#: '冰箱', 102 | 'STB',#: '机顶盒', 103 | 'sensor',#: '传感器', 104 | 'washmachine',#: '洗衣机', 105 | 'smartbed',#: '智能床', 106 | 'aromamachine',#: '香薰机', 107 | 'window',#: '窗', 108 | 'kitchenventilator',#: '抽油烟机', 109 | 'fingerprintlock',#: '指纹锁' 110 | 'telecontroller',#: '万能遥控器' 111 | 'dishwasher',#: '洗碗机' 112 | 'dehumidifier',#: '除湿机' 113 | ] 114 | 115 | INCLUDE_DOMAINS = { 116 | 'climate': 'aircondition', 117 | 'fan': 'fan', 118 | 'sensor': 'sensor', 119 | 'light': 'light', 120 | 'media_player': 'television', 121 | 'remote': 'telecontroller', 122 | 'switch': 'switch', 123 | 'vacuum': 'roboticvacuum', 124 | } 125 | 126 | EXCLUDE_DOMAINS = [ 127 | 'automation', 128 | 'binary_sensor', 129 | 'device_tracker', 130 | 'group', 131 | 'zone', 132 | ] 133 | 134 | # http://doc-bot.tmall.com/docs/doc.htm?treeId=393&articleId=108271&docType=1 135 | def guessDeviceType(entity_id, attributes): 136 | if 'hagenie_deviceType' in attributes: 137 | return attributes['hagenie_deviceType'] 138 | 139 | # Exclude with domain 140 | domain = entity_id[:entity_id.find('.')] 141 | if domain in EXCLUDE_DOMAINS: 142 | return None 143 | 144 | # Map from domain 145 | return INCLUDE_DOMAINS[domain] if domain in INCLUDE_DOMAINS else None 146 | 147 | 148 | # https://open.bot.tmall.com/oauth/api/aliaslist 149 | def guessDeviceName(entity_id, attributes, places, aliases): 150 | if 'hagenie_deviceName' in attributes: 151 | return attributes['hagenie_deviceName'] 152 | 153 | # Remove place prefix 154 | name = attributes['friendly_name'] 155 | for place in places: 156 | if name.startswith(place): 157 | name = name[len(place):] 158 | break 159 | 160 | if aliases is None or entity_id.startswith('sensor'): 161 | return name 162 | 163 | 164 | # Name validation 165 | for alias in aliases: 166 | if name == alias['key'] or name in alias['value']: 167 | return name 168 | 169 | return None 170 | 171 | 172 | # 173 | def groupsAttributes(items): 174 | groups_attributes = [] 175 | for item in items: 176 | group_entity_id = item['entity_id'] 177 | if group_entity_id.startswith('group.') and not group_entity_id.startswith('group.all_') and group_entity_id != 'group.default_view': 178 | group_attributes = item['attributes'] 179 | if 'entity_id' in group_attributes: 180 | groups_attributes.append(group_attributes) 181 | return groups_attributes 182 | 183 | 184 | # https://open.bot.tmall.com/oauth/api/placelist 185 | def guessZone(entity_id, attributes, places, groups_attributes): 186 | if 'hagenie_zone' in attributes: 187 | return attributes['hagenie_zone'] 188 | 189 | # Guess with friendly_name prefix 190 | name = attributes['friendly_name'] 191 | for place in places: 192 | if name.startswith(place): 193 | return place 194 | 195 | # Guess from HomeAssistant group 196 | for group_attributes in groups_attributes: 197 | for child_entity_id in group_attributes['entity_id']: 198 | if child_entity_id == entity_id: 199 | if 'hagenie_zone' in group_attributes: 200 | return group_attributes['hagenie_zone'] 201 | return group_attributes['friendly_name'] 202 | 203 | return None 204 | 205 | # 206 | def guessPropertyAndAction(entity_id, attributes, state): 207 | # http://doc-bot.tmall.com/docs/doc.htm?treeId=393&articleId=108264&docType=1 208 | # http://doc-bot.tmall.com/docs/doc.htm?treeId=393&articleId=108268&docType=1 209 | # Support On/Off/Query only at this time 210 | if 'hagenie_propertyName' in attributes: 211 | name = attributes['hagenie_propertyName'] 212 | 213 | elif entity_id.startswith('sensor.'): 214 | unit = attributes['unit_of_measurement'] if 'unit_of_measurement' in attributes else '' 215 | if unit == u'°C' or unit == u'℃': 216 | name = 'Temperature' 217 | elif unit == 'lx' or unit == 'lm': 218 | name = 'Brightness' 219 | elif ('hcho' in entity_id): 220 | name = 'Fog' 221 | elif ('humidity' in entity_id): 222 | name = 'Humidity' 223 | elif ('pm25' in entity_id): 224 | name = 'PM2.5' 225 | elif ('co2' in entity_id): 226 | name = 'WindSpeed' 227 | else: 228 | return (None, None) 229 | else: 230 | name = 'PowerState' 231 | if state != 'off': 232 | state = 'on' 233 | return ({'name': name.lower(), 'value': state}, 'Query' + name) 234 | 235 | # 236 | def discoveryDevice(): 237 | 238 | items = haCall('states') 239 | #services = haCall('services') 240 | 241 | places = json.loads(urlopen('https://open.bot.tmall.com/oauth/api/placelist').read())['data'] 242 | if _checkAlias: 243 | aliases = json.loads(urlopen('https://open.bot.tmall.com/oauth/api/aliaslist').read())['data'] 244 | aliases.append({'key': '电视', 'value': ['电视机']}) 245 | else: 246 | aliases = None 247 | log('Ignore alias checking to speed up!') 248 | groups_ttributes = groupsAttributes(items) 249 | 250 | devices = [] 251 | for item in items: 252 | attributes = item['attributes'] 253 | 254 | if attributes.get('hidden'): 255 | continue 256 | 257 | friendly_name = attributes.get('friendly_name') 258 | if friendly_name is None: 259 | continue 260 | 261 | entity_id = item['entity_id'] 262 | deviceType = guessDeviceType(entity_id, attributes) 263 | if deviceType is None: 264 | continue 265 | 266 | deviceName = guessDeviceName(entity_id, attributes, places, aliases) 267 | if deviceName is None: 268 | continue 269 | 270 | zone = guessZone(entity_id, attributes, places, groups_ttributes) 271 | if zone is None: 272 | continue 273 | 274 | prop,action = guessPropertyAndAction(entity_id, attributes, item['state']) 275 | if prop is None: 276 | continue 277 | 278 | # Merge all sensors into one for a zone 279 | # https://bbs.hassbian.com/thread-2982-1-1.html 280 | if deviceType == 'sensor': 281 | for sensor in devices: 282 | if sensor['deviceType'] == 'sensor' and zone == sensor['zone']: 283 | deviceType = None 284 | if not action in sensor['actions']: 285 | sensor['properties'].append(prop) 286 | sensor['actions'].append(action) 287 | sensor['model'] += ' ' + friendly_name 288 | # SHIT, length limition in deviceId: sensor['deviceId'] += '_' + entity_id 289 | else: 290 | log('SKIP: ' + entity_id) 291 | break 292 | if deviceType is None: 293 | continue 294 | deviceName = '传感器' 295 | entity_id = zone 296 | 297 | devices.append({ 298 | 'deviceId': entity_id, 299 | 'deviceName': deviceName, 300 | 'deviceType': deviceType, 301 | 'zone': zone, 302 | 'model': friendly_name, 303 | 'brand': 'HomeAssistant', 304 | 'icon': 'https://home-assistant.io/demo/favicon-192x192.png', 305 | 'properties': [prop], 306 | 'actions': ['TurnOn', 'TurnOff', 'Query', action] if action == 'QueryPowerState' else ['Query', action] 307 | }) 308 | 309 | if not REQUEST_METHOD: 310 | log(str(len(devices)) + '. ' + deviceType + ':' + zone + '/' + deviceName + ((' <= ' + friendly_name) if friendly_name != deviceName else '')) 311 | 312 | return {'devices': devices} 313 | 314 | 315 | # 316 | def getControlService(action): 317 | i = 0 318 | service = '' 319 | for c in action: 320 | service += (('_' if i else '') + c.lower()) if c.isupper() else c 321 | i += 1 322 | return service; 323 | 324 | 325 | # 326 | def controlDevice(name, payload): 327 | entity_id = payload['deviceId'] 328 | service = getControlService(name) 329 | domain = entity_id[:entity_id.find('.')] 330 | data = '{"entity_id":"' + entity_id + '"}' 331 | if domain == 'cover': 332 | service = 'close_cover' if service == 'turn_off' else 'open_cover' 333 | items = haCall('services/' + domain + '/' + service, data) 334 | #for item in items: 335 | # if item['entity_id'] == entity_id: 336 | # return {} 337 | return {} if (type(items) is list) else errorResult('IOT_DEVICE_OFFLINE') 338 | 339 | 340 | # 341 | def queryDevice(name, payload): 342 | deviceId = payload['deviceId'] 343 | 344 | if payload['deviceType'] == 'sensor': 345 | items = haCall('states') 346 | 347 | entity_ids = None 348 | for item in items: 349 | attributes = item['attributes'] 350 | if item['entity_id'].startswith('group.') and (attributes['friendly_name'] == deviceId or attributes.get('hagenie_zone') == deviceId): 351 | entity_ids = attributes.get('entity_id') 352 | break 353 | 354 | if entity_ids: 355 | properties = [{'name':'powerstate', 'value':'on'}] 356 | for item in items: 357 | entity_id = item['entity_id'] 358 | attributes = item['attributes'] 359 | if entity_id.startswith('sensor.') and (entity_id in entity_ids or attributes['friendly_name'].startswith(deviceId) or attributes.get('hagenie_zone') == deviceId): 360 | prop,action = guessPropertyAndAction(entity_id, attributes, item['state']) 361 | if prop is None: 362 | continue 363 | properties.append(prop) 364 | return properties 365 | else: 366 | item = haCall('states/' + deviceId) 367 | if type(item) is dict: 368 | return {'name':'powerstate', 'value':item['state']} 369 | return errorResult('IOT_DEVICE_OFFLINE') 370 | 371 | 372 | # 373 | def handleRequest(request): 374 | header = request['header'] 375 | payload = request['payload'] 376 | properties = None 377 | name = header['name'] 378 | if validateToken(payload): 379 | namespace = header['namespace'] 380 | if namespace == 'AliGenie.Iot.Device.Discovery': 381 | result = discoveryDevice() 382 | elif namespace == 'AliGenie.Iot.Device.Control': 383 | result = controlDevice(name, payload) 384 | elif namespace == 'AliGenie.Iot.Device.Query': 385 | result = queryDevice(name, payload) 386 | if not 'errorCode' in result: 387 | properties = result 388 | result = {} 389 | else: 390 | result = errorResult('SERVICE_ERROR') 391 | else: 392 | result = errorResult('ACCESS_TOKEN_INVALIDATE') 393 | 394 | # Check error and fill response name 395 | header['name'] = ('Error' if 'errorCode' in result else name) + 'Response' 396 | 397 | # Fill response deviceId 398 | if 'deviceId' in payload: 399 | result['deviceId'] = payload['deviceId'] 400 | 401 | response = {'header': header, 'payload': result} 402 | if properties: 403 | response['properties'] = properties 404 | return response 405 | 406 | 407 | # Main process 408 | try: 409 | if REQUEST_METHOD == 'POST': 410 | _request = json.load(sys.stdin) 411 | log(json.dumps(_request, indent=2)) 412 | else: 413 | # TEST only 414 | _request = { 415 | 'header':{'namespace': 'AliGenie.Iot.Device.Discovery', 'name': 'DiscoveryDevices', 'messageId': 'd0c17289-55df-4c8c-955f-b735e9bdd305'}, 416 | #'header':{'namespace': 'AliGenie.Iot.Device.Control', 'name': 'TurnOn', 'messageId': 'd0c17289-55df-4c8c-955f-b735e9bdd305'}, 417 | #'header':{'namespace': 'AliGenie.Iot.Device.Query', 'name': 'Query', 'messageId': 'd0c17289-55df-4c8c-955f-b735e9bdd305'}, 418 | 'payload':{'accessToken':'https_192.168.1.10_8123_token'} 419 | } 420 | _response = handleRequest(_request) 421 | except: 422 | import traceback 423 | log(traceback.format_exc()) 424 | _response = {'header': {'name': 'errorResult'}, 'payload': errorResult('SERVICE_ERROR', 'service exception')} 425 | 426 | # Process final result 427 | _result = json.dumps(_response, indent=2, ensure_ascii=False) 428 | if REQUEST_METHOD: 429 | log('RESPONSE ' + _result) 430 | 431 | print('Content-Type: application/json\r\n') 432 | print(_result) 433 | -------------------------------------------------------------------------------- /extras/deprecated/hagenie/hagenie.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | 4 | 5 | try: 6 | from BaseHTTPServer import HTTPServer 7 | from CGIHTTPServer import CGIHTTPRequestHandler 8 | except ImportError: 9 | from http.server import HTTPServer, CGIHTTPRequestHandler 10 | 11 | import os, sys, ssl 12 | import cgi, json 13 | from stat import * 14 | 15 | def _url_collapse_path_split(path): 16 | path_parts = [] 17 | for part in path.split('/'): 18 | if part == '.': 19 | path_parts.append('') 20 | else: 21 | path_parts.append(part) 22 | # Filter out blank non trailing parts before consuming the '..'. 23 | path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] 24 | if path_parts: 25 | tail_part = path_parts.pop() 26 | else: 27 | tail_part = '' 28 | head_parts = [] 29 | for part in path_parts: 30 | if part == '..': 31 | head_parts.pop() 32 | else: 33 | head_parts.append(part) 34 | if tail_part and tail_part == '..': 35 | head_parts.pop() 36 | tail_part = '' 37 | return ('/' + '/'.join(head_parts), tail_part) 38 | 39 | class ServerHandler(CGIHTTPRequestHandler): 40 | 41 | def do_POST(self): 42 | if self.is_cgi(): 43 | self.run_cgi() 44 | else: 45 | self.send_error(501, "is_cgi:NO"); 46 | self.do_GET() 47 | 48 | have_fork = False 49 | #cgi_directories = ['/'] 50 | def is_cgi(self): 51 | self.cgi_info = _url_collapse_path_split(self.path) 52 | return True 53 | #is_cgi = CGIHTTPRequestHandler.is_cgi(self) 54 | #if is_cgi == True: 55 | # pathname = '.' + self.path.split("?")[0] 56 | # is_cgi = os.path.isfile(pathname) and self.is_executable(pathname) 57 | #return is_cgi 58 | 59 | server = HTTPServer(('', 8122), ServerHandler) 60 | certfile = os.path.dirname(sys.argv[0]) + '/ssl.crt' 61 | keyfile = os.path.dirname(sys.argv[0]) + '/ssl.key' 62 | if os.path.isfile(certfile): 63 | server.socket = ssl.wrap_socket (server.socket, certfile=certfile, keyfile=keyfile, server_side=True) 64 | server.serve_forever() 65 | -------------------------------------------------------------------------------- /extras/setup/Docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat <<\EOF >> ~/.profile 4 | alias mqttsub='mqttsub() { mosquitto_sub -v -t "$1#"; }; mqttsub' 5 | alias dockre='dockre() { cat /dev/null > `docker inspect -f "{{json .LogPath}}" $1 | tr -d \"`; docker restart $1; }; dockre' 6 | alias docksh='docksh() { docker exec -it $1 /bin/bash; }; docksh' 7 | alias docklog='docker logs -f' 8 | alias hasssh='docksh homeassistant' 9 | alias hassre='dockre homeassistant' 10 | alias hasslog="docklog homeassistant" 11 | alias hassrl='hassre; hasslog' 12 | EOF 13 | 14 | # Docker 15 | docker run -d --name=homeassistant --privileged --restart=unless-stopped -e TZ=Asia/Shanghai -v /opt/.homeassistant:/config --network=host ghcr.nju.edu.cn/home-assistant/home-assistant:stable 16 | -------------------------------------------------------------------------------- /extras/setup/Hass.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | apt update && apt upgrade -y 3 | #apt autoclean 4 | #apt clean 5 | #apt autoremove -y 6 | 7 | # Mosquitto 8 | apt install mosquitto mosquitto-clients 9 | cat < /etc/mosquitto/mosquitto.conf 10 | listener 1883 11 | allow_anonymous true 12 | allow_zero_length_clientid true 13 | EOF 14 | 15 | # Depends 16 | apt install -y python3 python3-dev python3-pip 17 | apt install -y libavahi-compat-libdnssd-dev # HomeKit 18 | apt install -y bluez libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libopenjp2-7 libtiff5 libturbojpeg0-dev tzdata 19 | 20 | # PIP 21 | cat < ~/.pip/pip.conf 22 | [global] 23 | index-url = https://pypi.tuna.tsinghua.edu.cn/simple/ 24 | EOF 25 | 26 | # Hass 27 | pip3 install homeassistant 28 | 29 | # Auto start 30 | cat < /etc/systemd/system/homeassistant.service 31 | [Unit] 32 | Description=Home Assistant 33 | After=network-online.target 34 | 35 | [Service] 36 | Type=simple 37 | User=root 38 | ExecStart=/usr/local/bin/hass 39 | Restart=always 40 | 41 | [Install] 42 | WantedBy=multi-user.target 43 | 44 | EOF 45 | systemctl --system daemon-reload 46 | systemctl enable homeassistant 47 | #systemctl start homeassistant 48 | 49 | # Alias 50 | cat <<\EOF >> ~/.bashrc 51 | alias ll='ls --color=auto -lA' 52 | alias mqttsub='mqttsub() { mosquitto_sub -v -t "$1#"; }; mqttsub' 53 | alias mqttre='systemctl stop mosquitto; sleep 2; rm -rf /var/lib/mosquitto/mosquitto.db; systemctl start mosquitto' 54 | alias hassre='echo .>~/.homeassistant/home-assistant.log; systemctl restart homeassistant' 55 | alias hasste='systemctl stop homeassistant; hass' 56 | alias hassup='systemctl stop homeassistant; pip3 install homeassistant --upgrade; systemctl start homeassistant' 57 | alias hasslog='tail -f ~/.homeassistant/home-assistant.log' 58 | alias hassrl='hassre; hasslog' 59 | EOF 60 | 61 | # Docker 62 | docker run -d --name=homeassistant --privileged --restart=unless-stopped -e TZ=Asia/Shanghai -v /opt/.homeassistant:/config --network=host ghcr.nju.edu.cn/home-assistant/home-assistant:stable 63 | -------------------------------------------------------------------------------- /extras/setup/HassFix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd /usr/src/homeassistant/homeassistant || cd /usr/lib/python3.10/site-packages/homeassistant 3 | 4 | sed -i 's/_LOGGER.warning(CUSTOM_WARNING/#LOGGER.warning(CUSTOM_WARNING/' loader.py 5 | sed -i 's/minutes=30/days=30/' auth/const.py 6 | sed -i 's/ATTERY_MODELS:/ATTERY_MODELS and False:/' components/xiaomi_aqara/sensor.py 7 | sed -i 's/await hass.config_entries.async_forward_entry_setups/#wait hass.config_entries.async_forward_entry_setups/' components/mobile_app/__init__.py 8 | 9 | sed -i 's/Platform.BUTTON/#latform.BUTTON/' components/braviatv/__init__.py 10 | sed -i 's/f"{ATTR_MANUFACTURER} {model}"/model/' components/braviatv/entity.py 11 | 12 | sed -i 's/"RM4PRO", "RM4MINI"/"RM4PRO", "RMPRO", "RM4MINI"/' components/broadlink/sensor.py 13 | 14 | sed -i 's/await hass.config_entries.async_forward_entry_setups/#wait hass.config_entries.async_forward_entry_setups/' components/sun/__init__.py 15 | sed -i 's/await hass.config_entries.async_unload_platforms/True or await hass.config_entries.async_unload_platforms/' components/sun/__init__.py 16 | 17 | grep 'CONF_ICON_TEMPLATE,' components/mqtt/switch.py || sed -i 's/CONF_VALUE_TEMPLATE,/CONF_VALUE_TEMPLATE, CONF_ICON_TEMPLATE,/' components/mqtt/switch.py 18 | grep 'CONF_ICON_TEMPLATE)' components/mqtt/switch.py || sed -i 's/cv.template,/cv.template, vol.Optional(CONF_ICON_TEMPLATE): cv.template,/' components/mqtt/switch.py 19 | grep '"original_state": m' components/mqtt/switch.py || sed -i 's/payload = self._value_template/if CONF_VALUE_TEMPLATE in self._config: self._attr_state_attributes = {"original_state": msg.payload}\n if CONF_ICON_TEMPLATE in self._config: self._attr_icon = self._config[CONF_ICON_TEMPLATE].async_render_with_possible_json_value(msg.payload)\n payload = self._value_template/' components/mqtt/switch.py 20 | grep 'state_attributes(s,' components/mqtt/switch.py || sed -i 's/def _prepare_subscribe_topics/@property\n def state_attributes(self): return self._attr_state_attributes if hasattr(self, "_attr_state_attributes") else None\n\n def _prepare_subscribe_topics/' components/mqtt/switch.py 21 | -------------------------------------------------------------------------------- /extras/setup/HassOp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Install Home Assistant on OpenWrt 3 | 4 | # BASE 5 | opkg install python3 python3-pip 6 | opkg install python3-dev gcc 7 | opkg install python3-cffi # N1 Only 8 | source /usr/bin/gcc_env.sh 9 | 10 | # PIP 11 | sed -i '/index-url/d' /etc/pip.conf 12 | echo "index-url = https://pypi.tuna.tsinghua.edu.cn/simple/" >> /etc/pip.conf 13 | pip install --upgrade pip 14 | 15 | # PIP SO Fix 16 | cat <<\EOF > /usr/bin/pip3sofix 17 | #!/bin/sh 18 | FILE="${1##*/}" 19 | ln -s "$FILE" "${1%/*}/${FILE%%.*}.so" 20 | EOF 21 | cat <<\EOF > /usr/bin/pip3fix 22 | #!/bin/sh 23 | cd /usr/lib/python3.10/site-packages && find . -name "*cpython-*.so" -exec pip3sofix {} \; 24 | cd /root/.homeassistant/deps/lib/python3.10/site-packages && find . -name "*cpython-*.so" -exec pip3sofix {} \; 25 | EOF 26 | chmod +x /usr/bin/pip*fix 27 | 28 | # HASS 29 | pip install tzdata homeassistant 30 | 31 | # Fix 32 | rm -rf /root/.homeassistant/deps/lib/python3.10/site-packages/zeroconf* 33 | pip3fix 34 | hass 35 | pip3fix 36 | hass -v 37 | 38 | # Launch 39 | sed -i '/exit 0/d' /etc/rc.local 40 | echo -e 'hass -c /root/.homeassistant > dev/null &\nexit 0' >> /etc/rc.local 41 | 42 | # MQTT 43 | opkg install mosquitto-nossl 44 | cat << \EOF > /etc/mosquitto/mosquitto.conf 45 | listener 1883 46 | allow_anonymous true 47 | allow_zero_length_clientid true 48 | EOF 49 | 50 | # MISC 51 | opkg install ffmpeg #adb ... 52 | -------------------------------------------------------------------------------- /extras/test/test_airer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from miio.device import Device 4 | 5 | device = Device('Airer', 'fe5a1e19a1fd91ca4138646a494a6f19') 6 | #device_info = device.info() 7 | #device.send("set_led", [0]) 8 | #print('%s' % device_info) 9 | 10 | for prop in ["dry","led","motor","drytime","airer_location"]: 11 | try: 12 | ret = device.send("get_prop", [prop]) 13 | except Exception as exc: 14 | ret = exc 15 | print('%s=%s' % (prop, ret)) 16 | 17 | #device.send("set_motor", [1]) # 1-Up/0=Pause/2=Down 18 | -------------------------------------------------------------------------------- /extras/test/test_bravia.py: -------------------------------------------------------------------------------- 1 | #/user/bin/env python3 2 | 3 | from braviarc.braviarc import BraviaRC 4 | braviarc = BraviaRC('x9400e') 5 | 6 | #connect to the instance (or register) 7 | pin = '8404' 8 | braviarc.connect(pin, 'HomeAssistant', 'Home Assistant') 9 | 10 | #check connection 11 | if braviarc.is_connected(): 12 | 13 | #get power status 14 | power_status = braviarc.get_power_status() 15 | print (power_status) 16 | 17 | #get playing info 18 | playing_content = braviarc.get_playing_info() 19 | 20 | #print current playing channel 21 | print (playing_content.get('title')) 22 | 23 | #get volume info 24 | volume_info = braviarc.get_volume_info() 25 | 26 | #print current volume 27 | print (volume_info.get('volume')) 28 | 29 | #change channel 30 | braviarc.play_content('https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4') 31 | 32 | #get app list 33 | app_info = braviarc.load_app_list() 34 | print (app_info) 35 | 36 | #start a given app 37 | braviarc.start_app("Kodi") 38 | 39 | #turn off the TV 40 | #braviarc.turn_off() 41 | -------------------------------------------------------------------------------- /extras/test/test_https.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | import BaseHTTPServer, SimpleHTTPServer 5 | import os, sys, ssl 6 | 7 | httpd = BaseHTTPServer.HTTPServer(('', 8122), SimpleHTTPServer.SimpleHTTPRequestHandler) 8 | certfile = os.path.dirname(sys.argv[0]) + '/server.pem' 9 | if os.path.isfile(certfile): 10 | httpd.socket = ssl.wrap_socket (httpd.socket, certfile=certfile, server_side=True) 11 | httpd.serve_forever() 12 | -------------------------------------------------------------------------------- /extras/test/test_miot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from miio.miot_device import MiotDevice 4 | 5 | device = MiotDevice( 6 | { 7 | 'power': {'siid': 2, 'piid': 1}, 8 | 'power2': {'siid': 5, 'piid': 10}, 9 | 'power3': {'siid': 2, 'piid': 3}, 10 | 'power4': {'siid': 2, 'piid': 4}, 11 | 'power5': {'siid': 2, 'piid': 5}, 12 | 'power6': {'siid': 2, 'piid': 6}, 13 | 'power7': {'siid': 2, 'piid': 7}, 14 | 'power8': {'siid': 2, 'piid': 8}, 15 | 'power9': {'siid': 2, 'piid': 10}, 16 | 'powerA': {'siid': 2, 'piid': 11}, 17 | 'powerB': {'siid': 5, 'piid': 2}, 18 | 'powerC': {'siid': 6, 'piid': 1}, 19 | 'powerD': {'siid': 5, 'piid': 4}, 20 | 'powerE': {'siid': 5, 'piid': 5}, 21 | }, '192.168.1.28', '6dd1ec1c895a61d1b994b4a6242efe56') 22 | 23 | print('%s' % device.get_properties_for_mapping()) 24 | -------------------------------------------------------------------------------- /extras/test/test_modbus.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import struct 4 | from pymodbus.client import ModbusTcpClient 5 | from pymodbus.transaction import ModbusRtuFramer 6 | 7 | HOST = '192.168.1.60' 8 | PORT = 8899 9 | 10 | 11 | def reset(host, port): 12 | import socket 13 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 14 | s.settimeout(5) 15 | s.connect((host, port)) 16 | s.sendall(b'\x55\xAA\x55\x00\x25\x80\x03\xA8') # For USR initialize 17 | s.close() 18 | 19 | 20 | ATTR_MAP = { 21 | 'target_temp': {'registers': [4, 8, 12, 16]}, 22 | 'temperature': {'registers': [3, 6, 9, 12], 'register_type': 'input'}, 23 | 'operation': {'registers': [5, 9, 13, 17]}, 24 | 'fan_mode': {'registers': [6, 10, 14, 18]}, 25 | 'state_is_on': {'registers': [1, 2, 3, 4], 'register_type': 'coil'} 26 | } 27 | 28 | #reset(HOST, PORT) 29 | 30 | client = ModbusTcpClient(host=HOST, port=PORT, framer=ModbusRtuFramer) 31 | kwargs = {'unit': 1} 32 | ret = client.connect() 33 | 34 | for k, v in ATTR_MAP.items(): 35 | print("%s:\t" % k, end='') 36 | for register in v['registers']: 37 | register_type = v.get('register_type') 38 | if register_type == 'coil': 39 | result = client.read_coils(register, 1, **kwargs) 40 | value = bool(result.bits[0]) 41 | else: 42 | if register_type == 'input': 43 | result = client.read_input_registers(register, 1, **kwargs) 44 | else: 45 | result = client.read_holding_registers(register) 46 | if isinstance(result, Exception): 47 | print("Exception: %s" % result) 48 | continue 49 | byte_string = b''.join([x.to_bytes(2, byteorder='big') for x in result.registers]) 50 | value = struct.unpack('>H', byte_string)[0] 51 | print("%s\t" % value, end='') 52 | print("") 53 | -------------------------------------------------------------------------------- /extras/test/test_washer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from miio.device import Device 4 | 5 | device = Device('Washer', '1f63e0afaa20d062223b24c98eca7c11') 6 | info = device.info() 7 | print('%s' % info) 8 | 9 | device.send("set_wash_program", ['goldenwash']) 10 | 11 | #device.send("set_wash_action", [0]) # 0=Pause/1=Wash/2=PowerOff 12 | #device.send("SetDryMode", ['17922']) # 0 13 | # print('set_appoint_time=0: %s' % device.send("set_appoint_time", [0])) 14 | # print('set_appoint_time: %s' % device.send("set_appoint_time", [20])) 15 | 16 | properties = [ 17 | "program", # dry=黄金烘/weak_dry=低温烘/refresh=空气洗/wool=羊毛/down=羽绒服/drumclean=筒清洁/goldenwash=黄金洗/super_quick=超快洗/cottons=棉织物/antibacterial=除菌洗/rinse_spin=漂+脱/spin单脱水/quick=快洗/shirt=衬衣/jeans=牛仔/underwears=内衣 18 | "wash_process", # 0=Idle/1=Prepare/1=Pause/.../7=Stop/预约等待=0 19 | "wash_status", # 1=Idle/1=Prepare/0=Pause/1=Stop/预约等待=1 20 | "water_temp", 21 | "rinse_status", 22 | "spin_level", 23 | "remain_time", 24 | "appoint_time", 25 | "be_status", 26 | "run_status", 27 | "DryMode", # 0=NA/33282=智能/半小时=7681/15361=一小时/30721=两小时 28 | "child_lock" 29 | ] 30 | 31 | # Limited to a single property per request 32 | values = {} 33 | for prop in properties: 34 | values[prop] = device.send("get_prop", [prop]) 35 | 36 | print('%s' % values) 37 | -------------------------------------------------------------------------------- /fans.yaml: -------------------------------------------------------------------------------- 1 | - platform: zhimijia 2 | model: zhimi.fan.v3 3 | name: 儿童房风扇 4 | did: 63038010 5 | - platform: zhimijia 6 | model: zhimi.fan.fa1 7 | name: 主卧风扇 8 | did: 242978949 9 | # - platform: zhimijia 10 | # model: zhimi.fan.za3 11 | # name: 定南风扇 12 | # did: 106565511 13 | - platform: zhimijia 14 | model: zhimi.airfresh.va2 15 | name: 客厅新风机 16 | icon: mdi:leaf 17 | did: 80578920 18 | sensors: 19 | temp_dec: 客厅温度 20 | humidity: 客厅湿度 21 | aqi: 客厅空气质量 22 | co2: 客厅二氧化碳 23 | - platform: zhimijia 24 | model: zhimi.airfresh.va2 25 | name: 主卧新风机 26 | icon: mdi:leaf 27 | did: 99281481 28 | sensors: 29 | temp_dec: 主卧温度 30 | humidity: 主卧湿度 31 | aqi: 主卧空气质量 32 | co2: 主卧二氧化碳 33 | - platform: zhimijia 34 | model: zhimi.airpurifier.m1 35 | name: 次卧净化器 36 | icon: mdi:cupcake 37 | did: 61061613 38 | sensors: 39 | temp_dec: 次卧温度 40 | humidity: 次卧湿度 41 | aqi: 次卧空气质量 42 | - platform: zhiremote 43 | name: 客厅风扇 44 | sender: remote.ke_ting_yao_kong 45 | command: midea_fan 46 | -------------------------------------------------------------------------------- /homekit.yaml: -------------------------------------------------------------------------------- 1 | name: 旌启智家 2 | filter: 3 | exclude_domains: 4 | - automation 5 | - camera 6 | - device_tracker 7 | - input_boolean 8 | - media_player 9 | - script 10 | exclude_entities: 11 | - binary_sensor.switch_158d0001e59b33 12 | - binary_sensor.switch_158d000201a73f 13 | - binary_sensor.switch_158d00054e98b0 14 | - climate.ke_ting_di_nuan 15 | - climate.zhu_wo_di_nuan 16 | - sensor.er_tong_fang_er_yang_hua_tan 17 | - switch.can_ting_tong_deng 18 | - switch.ke_ting_tong_deng 19 | - remote.ke_ting_yao_kong 20 | - remote.shu_fang_yao_kong 21 | entity_config: 22 | switch.can_ting_chu_shi_ji: 23 | type: outlet 24 | switch.yi_ju_chu_shi_ji: 25 | type: outlet 26 | media_player.zhu_wo_dian_shi: 27 | feature_list: 28 | - feature: on_off 29 | media_player.ke_ting_dian_shi: 30 | feature_list: 31 | - feature: on_off 32 | -------------------------------------------------------------------------------- /lights.yaml: -------------------------------------------------------------------------------- 1 | - platform: zhimijia 2 | name: 书房台灯 3 | icon: mdi:lamp 4 | did: 65074727 5 | power_prop: 2-1 6 | brightness_prop: 2-2 7 | - platform: zhimijia 8 | name: 儿童房台灯 9 | icon: mdi:lamp 10 | did: 119154367 11 | power_prop: 2-1 12 | brightness_prop: 2-2 13 | - platform: zhimijia 14 | name: 书房晾衣灯 15 | icon: mdi:spotlight 16 | did: 57379167 17 | power_prop: 3-1 18 | - platform: zhimijia 19 | name: 浴室浴霸灯 20 | icon: mdi:ceiling-light 21 | did: 493852339 22 | #ignore_state: true 23 | brightness_prop: bright 24 | -------------------------------------------------------------------------------- /mqtt.yaml: -------------------------------------------------------------------------------- 1 | # binary_sensor: 2 | # - device_class: motion 3 | # state_topic: JingHuaQi3/digital 4 | # payload_on: 1 5 | # payload_off: 0 6 | # name: 主卧感应 7 | # availability_topic: JingHuaQi3/status 8 | 9 | sensor: 10 | - name: 阳台温度 11 | device_class: temperature 12 | state_topic: ChuanGanQi/temperature 13 | unit_of_measurement: °C 14 | availability_topic: ChuanGanQi/status 15 | - name: 阳台湿度 16 | device_class: humidity 17 | state_topic: ChuanGanQi/humidity 18 | unit_of_measurement: '%' 19 | availability_topic: ChuanGanQi/status 20 | - name: 阳台空气质量 21 | device_class: pm25 22 | state_topic: ChuanGanQi/pm2dot5 23 | unit_of_measurement: µg/m³ 24 | availability_topic: ChuanGanQi/status 25 | - name: 书房温度 26 | device_class: temperature 27 | state_topic: YinXiang/temperature 28 | unit_of_measurement: °C 29 | availability_topic: YinXiang/status 30 | - name: 书房湿度 31 | device_class: humidity 32 | state_topic: YinXiang/humidity 33 | unit_of_measurement: '%' 34 | availability_topic: YinXiang/status 35 | - name: 书房二氧化碳 36 | device_class: carbon_dioxide 37 | state_topic: YinXiang/co2 38 | unit_of_measurement: ppm 39 | availability_topic: YinXiang/status 40 | - name: 书房亮度 41 | device_class: illuminance 42 | state_topic: YinXiang/lux 43 | unit_of_measurement: lx 44 | availability_topic: YinXiang/status 45 | - name: 餐厅亮度 46 | device_class: illuminance 47 | state_topic: JingHuaQi3/analog 48 | availability_topic: JingHuaQi3/status 49 | unit_of_measurement: lx 50 | - name: 儿童房温度 51 | device_class: temperature 52 | state_topic: JingHuaQi4/temperature 53 | unit_of_measurement: °C 54 | availability_topic: JingHuaQi4/status 55 | - name: 儿童房湿度 56 | device_class: humidity 57 | state_topic: JingHuaQi4/humidity 58 | unit_of_measurement: '%' 59 | availability_topic: JingHuaQi4/status 60 | - name: 儿童房空气质量 61 | device_class: pm25 62 | state_topic: JingHuaQi4/pm2dot5 63 | unit_of_measurement: µg/m³ 64 | availability_topic: JingHuaQi4/status 65 | - name: 儿童房二氧化碳 66 | device_class: carbon_dioxide 67 | state_topic: JingHuaQi4/co2 68 | unit_of_measurement: ppm 69 | availability_topic: JingHuaQi4/status 70 | 71 | - name: 餐厅温度 72 | device_class: temperature 73 | state_topic: device/zm1/b0f893249132/sensor 74 | value_template: '{{ value_json.temperature }}' 75 | unit_of_measurement: °C 76 | - name: 餐厅湿度 77 | device_class: humidity 78 | state_topic: device/zm1/b0f893249132/sensor 79 | value_template: '{{ value_json.humidity }}' 80 | unit_of_measurement: '%' 81 | - name: 餐厅空气质量 82 | device_class: pm25 83 | state_topic: device/zm1/b0f893249132/sensor 84 | value_template: '{{ value_json.PM25 }}' 85 | unit_of_measurement: µg/m³ 86 | - name: 餐厅甲醛 87 | icon: mdi:biohazard 88 | state_topic: device/zm1/b0f893249132/sensor 89 | value_template: '{{ value_json.formaldehyde }}' 90 | unit_of_measurement: mg/m³ 91 | # - name: 过道温度 92 | # device_class: temperature 93 | # state_topic: device/zm1/b0f8931ea148/sensor 94 | # value_template: '{{ value_json.temperature }}' 95 | # unit_of_measurement: °C 96 | # - name: 过道湿度 97 | # device_class: humidity 98 | # state_topic: device/zm1/b0f8931ea148/sensor 99 | # value_template: '{{ value_json.humidity }}' 100 | # unit_of_measurement: '%' 101 | # - name: 过道空气质量 102 | # device_class: pm25 103 | # state_topic: device/zm1/b0f8931ea148/sensor 104 | # value_template: '{{ value_json.PM25 }}' 105 | # unit_of_measurement: µg/m³ 106 | # - name: 过道甲醛 107 | # icon: mdi:biohazard 108 | # state_topic: device/zm1/b0f8931ea148/sensor 109 | # value_template: '{{ value_json.formaldehyde }}' 110 | # unit_of_measurement: mg/m³ 111 | 112 | # switch: 113 | # - name: 过道开关1 114 | # state_topic: GuoDaoGuiDeng/relay/1 115 | # command_topic: GuoDaoGuiDeng/relay/1/set 116 | # availability_topic: GuoDaoGuiDeng/status 117 | # - name: 过道开关2 118 | # state_topic: GuoDaoGuiDeng/relay/2 119 | # command_topic: GuoDaoGuiDeng/relay/2/set 120 | # availability_topic: GuoDaoGuiDeng/status 121 | # - name: 洗手间排气扇 122 | # state_topic: XiShouJianDeng/relay/1 123 | # command_topic: XiShouJianDeng/relay/1/set 124 | # availability_topic: XiShouJianDeng/status 125 | # icon: mdi:fan 126 | # - name: 书房音箱 127 | # state_topic: YinXiang/relay/0 128 | # command_topic: YinXiang/relay/0/set 129 | # availability_topic: YinXiang/status 130 | # value_template: '{% if value == "关闭" %}OFF{% else %}ON{% endif %}' 131 | #icon_template: '{% if value == "关闭" %}mdi:speaker-off{% elif value == "蓝牙" %}mdi:speaker-bluetooth{% elif value == "光纤" %}mdi:speaker-wireless{% elif value == "优盘" %}mdi:usb{% elif value == "辅助" %}mdi:video-input-component{% else %}mdi:speaker{% endif %}' 132 | 133 | light: 134 | - name: 书房音箱 135 | state_topic: YinXiang/relay/0 136 | command_topic: YinXiang/relay/0/set 137 | availability_topic: YinXiang/status 138 | state_value_template: '{% if value == "关闭" %}OFF{% else %}ON{% endif %}' 139 | effect_command_topic: YinXiang/relay/0/set 140 | #effect_command_template: 141 | effect_list: [关闭, 蓝牙, 光纤, 优盘, 辅助] 142 | effect_state_topic: YinXiang/relay/0 143 | icon: mdi:speaker 144 | #icon_template: '{% if value == "关闭" %}mdi:speaker-off{% elif value == "蓝牙" %}mdi:speaker-bluetooth{% elif value == "光纤" %}mdi:speaker-wireless{% elif value == "优盘" %}mdi:usb{% elif value == "辅助" %}mdi:video-input-component{% else %}mdi:speaker{% endif %}' 145 | - name: 洗手间排气扇 146 | icon: mdi:fan 147 | state_topic: XiShouJianDeng/relay/1 148 | command_topic: XiShouJianDeng/relay/1/set 149 | availability_topic: XiShouJianDeng/status 150 | - name: 洗手间灯 151 | icon: mdi:ceiling-light 152 | state_topic: XiShouJianDeng/relay/0 153 | command_topic: XiShouJianDeng/relay/0/set 154 | availability_topic: XiShouJianDeng/status 155 | # - name: 浴室灯 156 | # icon: mdi:ceiling-light 157 | # state_topic: Hassmart3/relay/1 158 | # command_topic: Hassmart3/relay/1/set 159 | # availability_topic: Hassmart3/status 160 | - name: 过道柜灯 161 | icon: mdi:car-light-dimmed 162 | state_topic: GuoDaoGuiDeng/relay/0 163 | command_topic: GuoDaoGuiDeng/relay/0/set 164 | availability_topic: GuoDaoGuiDeng/status 165 | # - name: 主卧吸顶灯 166 | # state_topic: JingHuaQi3/analog 167 | # state_value_template: '{% if (value | int > 1000) or ((value | int > 600) and is_state("sun.sun", "below_horizon")) %}3526,1658,426,418,426,1292,426,420,426,1288,428,418,426,1290,430,418,426,1290,428,418,426,418,426,416,426,1290,428,416,430,1290,428,1290,428,418,428,1288,428,416,428,418,426,418,428,1288,428,1288,428,1290,428,418,428,1290,428,418,428,1290,428,416,428,1290,428,1290,428,416,428,418,426,418,428,416,428,418,426,416,428,418,426,416,428,416,428,418,426,1292,426,418,428,1290,428,416,428,1292,424,1292,424,1294,424,418,426,1290,426,420,424,418,426,420,424,422,424,1294,424,420,424,420,424,1294,424,420,424,422,422,422,422,1298,422,422,422,1296,422,422,422,1,2,38{% else %}3528,1658,426,418,426,1292,380,462,382,1334,382,464,382,1338,380,462,382,1336,382,462,382,462,382,462,382,1336,382,462,382,1336,380,1336,382,464,382,1338,378,462,384,462,382,464,380,1336,382,1336,382,1336,382,462,382,1334,384,464,382,1336,382,462,382,1336,382,1336,382,464,382,462,382,464,382,464,380,462,382,462,382,464,382,464,380,464,382,464,382,464,380,1338,380,462,382,464,382,462,380,464,380,464,380,464,380,1334,382,464,380,464,380,464,380,464,382,1336,382,464,382,462,382,1334,382,464,382,464,382,464,380,1336,382,1336,382,464,382,1338,380,1,2,38{% endif %}' 168 | # command_topic: JingHuaQi3/irout/set 169 | # availability_topic: JingHuaQi3/status 170 | # payload_on: 3526,1658,426,418,426,1292,426,420,426,1288,428,418,426,1290,430,418,426,1290,428,418,426,418,426,416,426,1290,428,416,430,1290,428,1290,428,418,428,1288,428,416,428,418,426,418,428,1288,428,1288,428,1290,428,418,428,1290,428,418,428,1290,428,416,428,1290,428,1290,428,416,428,418,426,418,428,416,428,418,426,416,428,418,426,416,428,416,428,418,426,1292,426,418,428,1290,428,416,428,1292,424,1292,424,1294,424,418,426,1290,426,420,424,418,426,420,424,422,424,1294,424,420,424,420,424,1294,424,420,424,422,422,422,422,1298,422,422,422,1296,422,422,422,1,2,38 171 | # payload_off: 3528,1658,426,418,426,1292,380,462,382,1334,382,464,382,1338,380,462,382,1336,382,462,382,462,382,462,382,1336,382,462,382,1336,380,1336,382,464,382,1338,378,462,384,462,382,464,380,1336,382,1336,382,1336,382,462,382,1334,384,464,382,1336,382,462,382,1336,382,1336,382,464,382,462,382,464,382,464,380,462,382,462,382,464,382,464,380,464,382,464,382,464,380,1338,380,462,382,464,382,462,380,464,380,464,380,464,380,1334,382,464,380,464,380,464,380,464,382,1336,382,464,382,462,382,1334,382,464,382,464,382,464,380,1336,382,1336,382,464,382,1338,380,1,2,38 172 | # brightness_state_topic: JingHuaQi3/analog 173 | # brightness_command_topic: JingHuaQi3_/analog/set 174 | # brightness_scale: 1024 175 | # - name: 儿童房吸顶灯 176 | # command_topic: JingHuaQi4/irout/set 177 | # availability_topic: JingHuaQi4/status 178 | # payload_on: 3526,1658,426,418,426,1292,426,420,426,1288,428,418,426,1290,430,418,426,1290,428,418,426,418,426,416,426,1290,428,416,430,1290,428,1290,428,418,428,1288,428,416,428,418,426,418,428,1288,428,1288,428,1290,428,418,428,1290,428,418,428,1290,428,416,428,1290,428,1290,428,416,428,418,426,418,428,416,428,418,426,416,428,418,426,416,428,416,428,418,426,1292,426,418,428,1290,428,416,428,1292,424,1292,424,1294,424,418,426,1290,426,420,424,418,426,420,424,422,424,1294,424,420,424,420,424,1294,424,420,424,422,422,422,422,1298,422,422,422,1296,422,422,422,1,2,38 179 | # payload_off: 3528,1658,426,418,426,1292,380,462,382,1334,382,464,382,1338,380,462,382,1336,382,462,382,462,382,462,382,1336,382,462,382,1336,380,1336,382,464,382,1338,378,462,384,462,382,464,380,1336,382,1336,382,1336,382,462,382,1334,384,464,382,1336,382,462,382,1336,382,1336,382,464,382,462,382,464,382,464,380,462,382,462,382,464,382,464,380,464,382,464,382,464,380,1338,380,462,382,464,382,462,380,464,380,464,380,464,380,1334,382,464,380,464,380,464,380,464,382,1336,382,464,382,462,382,1334,382,464,382,464,382,464,380,1336,382,1336,382,464,382,1338,380,1,2,38 180 | # - name: 餐厅检测仪 181 | # schema: template 182 | # command_topic: device/zm1/b0f8931ea148/set 183 | # state_topic: device/zm1/b0f8931ea148/state 184 | # command_on_template: '{"mac":"b0f8931ea148","brightness":{%- if brightness is defined -%}{{ ((brightness-1) / 64 )|int +1 }}{%- else -%}4{%- endif -%}}' 185 | # command_off_template: '{"mac":"b0f8931ea148","brightness":0}' 186 | # state_template: '{%- if value_json.brightness == 0 -%}off{%- else -%}on{%- endif -%}' 187 | # brightness_template: '{%- if value_json.brightness is defined -%}{{ ( value_json.brightness *64 )|int }}{%- endif -%}' 188 | # - name: 过道检测仪 189 | # schema: template 190 | # command_topic: device/zm1/b0f893249132/set 191 | # state_topic: device/zm1/b0f893249132/state 192 | # command_on_template: '{"mac":"b0f893249132","brightness":{%- if brightness is defined -%}{{ ((brightness-1) / 64 )|int +1 }}{%- else -%}4{%- endif -%}}' 193 | # command_off_template: '{"mac":"b0f893249132","brightness":0}' 194 | # state_template: '{%- if value_json.brightness == 0 -%}off{%- else -%}on{%- endif -%}' 195 | # brightness_template: '{%- if value_json.brightness is defined -%}{{ ( value_json.brightness *64 )|int }}{%- endif -%}' 196 | 197 | fan: 198 | # - name: 书房净化器 199 | # state_topic: NodeMCU3/relay/0 200 | # command_topic: NodeMCU3/relay/0/set 201 | # availability_topic: NodeMCU3/status 202 | # oscillation_state_topic: NodeMCU3/relay/1 203 | # oscillation_command_topic: NodeMCU3/relay/1/set 204 | # preset_mode_state_topic: NodeMCU3/relay/0 205 | # preset_mode_command_topic: NodeMCU3/relay/0/set 206 | # state_value_template: '{% if value == "0" %}OFF{% else %}ON{% endif %}' 207 | # preset_modes: 208 | # - 'off' 209 | # - low 210 | # - medium 211 | # - high 212 | # preset_mode_command_template: '{% if value == "off" %}OFF{% elif value == "low" %}1{% elif value == "high" %}3{% else %}2{% endif %}' 213 | # preset_mode_value_template: '{% if value == "0" %}off{% elif value == "1" %}low{% elif value == "3" %}high{% else %}medium{% endif %}' 214 | # payload_oscillation_on: 'ON' 215 | # payload_oscillation_off: 'OFF' 216 | # - name: 客厅净化器 217 | # state_topic: NodeMCU4/relay/0 218 | # command_topic: NodeMCU4/relay/0/set 219 | # availability_topic: NodeMCU4/status 220 | # oscillation_state_topic: NodeMCU4/relay/1 221 | # oscillation_command_topic: NodeMCU4/relay/1/set 222 | # preset_mode_state_topic: NodeMCU4/relay/0 223 | # preset_mode_command_topic: NodeMCU4/relay/0/set 224 | # state_value_template: '{% if value == "0" %}OFF{% else %}ON{% endif %}' 225 | # preset_modes: 226 | # - 'off' 227 | # - low 228 | # - medium 229 | # - high 230 | # preset_mode_command_template: '{% if value == "off" %}OFF{% elif value == "low" %}1{% elif value == "high" %}4{% else %}5{% endif %}' 231 | # preset_mode_value_template: '{% if value == "0" %}off{% elif value == "1" %}low{% elif value == "4" %}high{% else %}medium{% endif %}' 232 | # payload_oscillation_on: 'ON' 233 | # payload_oscillation_off: 'OFF' 234 | - name: 餐厅净化器 235 | icon: mdi:cupcake 236 | state_topic: JingHuaQi3/relay/0 237 | command_topic: JingHuaQi3/relay/0/set 238 | availability_topic: JingHuaQi3/status 239 | oscillation_state_topic: JingHuaQi3/relay/1 240 | oscillation_command_topic: JingHuaQi3/relay/1/set 241 | preset_mode_state_topic: JingHuaQi3/relay/0 242 | preset_mode_command_topic: JingHuaQi3/relay/0/set 243 | state_value_template: '{% if value == "0" %}OFF{% else %}ON{% endif %}' 244 | preset_modes: [关闭, 自动, 梅雨, 花粉, 静音, 中档, 高档] 245 | preset_mode_command_template: '{% if value == "自动" %}1{% elif value == "梅雨" %}2{% elif value == "花粉" %}3{% elif value == "静音" %}4{% elif value == "中档" %}5{% elif value == "高档" %}6{% else %}0{% endif %}' 246 | preset_mode_value_template: '{% if value == "1" %}自动{% elif value == "2" %}梅雨{% elif value == "3" %}花粉{% elif value == "4" %}静音{% elif value == "5" %}中档{% elif value == "6" %}高档{% else %}关闭{% endif %}' 247 | payload_oscillation_on: 'ON' 248 | payload_oscillation_off: 'OFF' 249 | - name: 儿童房净化器 250 | icon: mdi:cupcake 251 | state_topic: JingHuaQi4/relay/0 252 | command_topic: JingHuaQi4/relay/0/set 253 | availability_topic: JingHuaQi4/status 254 | oscillation_state_topic: JingHuaQi4/relay/1 255 | oscillation_command_topic: JingHuaQi4/relay/1/set 256 | preset_mode_state_topic: JingHuaQi4/relay/0 257 | preset_mode_command_topic: JingHuaQi4/relay/0/set 258 | state_value_template: '{% if value == "0" %}OFF{% else %}ON{% endif %}' 259 | preset_modes: [关闭, 自动, 梅雨, 花粉, 静音, 中档, 高档] 260 | preset_mode_command_template: '{% if value == "自动" %}1{% elif value == "梅雨" %}2{% elif value == "花粉" %}3{% elif value == "静音" %}4{% elif value == "中档" %}5{% elif value == "高档" %}6{% else %}0{% endif %}' 261 | preset_mode_value_template: '{% if value == "1" %}自动{% elif value == "2" %}梅雨{% elif value == "3" %}花粉{% elif value == "4" %}静音{% elif value == "5" %}中档{% elif value == "6" %}高档{% else %}关闭{% endif %}' 262 | payload_oscillation_on: 'ON' 263 | payload_oscillation_off: 'OFF' 264 | # - name: 主卧壁扇 265 | # availability_topic: JingHuaQi3/status 266 | # command_topic: JingHuaQi3/irout/set 267 | # payload_on: 9150,4770,380,812,438,782,410,754,436,756,412,778,812,380,812,408,782,384,410,806,810,358,408,808,782,410,782,410,784,408,784,408,782,382,382,814,410,806,384,780,386,806,410,762,432,808,806,386,402,762,808,382,810,384,808,382,808,382,812,380,810,410,382,808,784,382,1208,8334,9130,4796,356,814,408,782,408,782,410,782,408,782,810,382,808,384,808,382,410,782,808,382,412,780,810,382,810,384,832,358,808,382,810,382,384,810,412,780,412,778,412,780,412,780,412,780,810,384,408,782,810,382,810,382,810,382,808,382,834,358,810,382,410,780,810,382,1210,8338,9126,4796,382,812,382,808,382,784,408,808,382,786,806,410,782,410,780,412,382,808,782,410,358,832,758,434,758,434,780,412,758,434,758,434,378,788,386,808,384,830,360,830,360,804,388,832,760,432,360,830,762,430,762,432,760,432,760,430,762,430,762,428,388,804,784,408,1186,1,2,38 268 | # payload_off: 9150,4770,380,812,438,782,410,754,436,756,412,778,812,380,812,408,782,384,410,806,810,358,408,808,782,410,782,410,784,408,784,408,782,382,382,814,410,806,384,780,386,806,410,762,432,808,806,386,402,762,808,382,810,384,808,382,808,382,812,380,810,410,382,808,784,382,1208,8334,9130,4796,356,814,408,782,408,782,410,782,408,782,810,382,808,384,808,382,410,782,808,382,412,780,810,382,810,384,832,358,808,382,810,382,384,810,412,780,412,778,412,780,412,780,412,780,810,384,408,782,810,382,810,382,810,382,808,382,834,358,810,382,410,780,810,382,1210,8338,9126,4796,382,812,382,808,382,784,408,808,382,786,806,410,782,410,780,412,382,808,782,410,358,832,758,434,758,434,780,412,758,434,758,434,378,788,386,808,384,830,360,830,360,804,388,832,760,432,360,830,762,430,762,432,760,432,760,430,762,430,762,428,388,804,784,408,1186,1,2,38 269 | # oscillation_state_topic: JingHuaQi3/status 270 | # oscillation_command_topic: JingHuaQi3/irout/set 271 | # payload_oscillation_on: 9152,4774,428,764,386,832,360,808,384,806,386,830,760,432,758,434,758,434,358,808,784,432,362,830,760,432,760,432,758,434,758,432,760,432,380,790,384,830,360,832,362,830,760,432,360,832,360,830,364,828,762,430,762,428,762,432,760,432,362,802,788,432,762,430,762,430,1162,8334,9158,4766,432,786,388,778,390,826,364,804,388,828,762,430,760,430,762,430,364,828,764,428,364,804,786,430,760,432,760,432,762,430,760,432,380,814,386,806,364,828,362,830,762,432,360,830,362,830,362,830,760,432,760,432,758,434,760,432,360,806,784,434,758,434,758,434,1156,8336,9178,4748,406,790,404,810,382,810,382,786,406,808,782,410,780,412,780,412,380,786,804,412,382,784,806,412,780,412,780,412,780,412,780,410,380,814,382,784,408,810,382,808,782,410,382,784,408,808,384,784,806,412,780,410,780,412,782,410,380,810,780,412,782,410,780,410,1180,1,2,38 272 | # payload_oscillation_off: 9152,4774,428,764,386,832,360,808,384,806,386,830,760,432,758,434,758,434,358,808,784,432,362,830,760,432,760,432,758,434,758,432,760,432,380,790,384,830,360,832,362,830,760,432,360,832,360,830,364,828,762,430,762,428,762,432,760,432,362,802,788,432,762,430,762,430,1162,8334,9158,4766,432,786,388,778,390,826,364,804,388,828,762,430,760,430,762,430,364,828,764,428,364,804,786,430,760,432,760,432,762,430,760,432,380,814,386,806,364,828,362,830,762,432,360,830,362,830,362,830,760,432,760,432,758,434,760,432,360,806,784,434,758,434,758,434,1156,8336,9178,4748,406,790,404,810,382,810,382,786,406,808,782,410,780,412,780,412,380,786,804,412,382,784,806,412,780,412,780,412,780,412,780,410,380,814,382,784,408,810,382,808,782,410,382,784,408,808,384,784,806,412,780,410,780,412,782,410,380,810,780,412,782,410,780,410,1180,1,2,38 273 | # preset_mode_command_topic: JingHuaQi3/irout/set 274 | # preset_modes: 275 | # - 'off' 276 | # - low 277 | # - high 278 | # preset_mode_command_template: '{% if value == "off" %}OFF{% elif value == "low" %}9126,4798,380,784,438,754,412,780,436,754,438,754,810,382,810,382,810,382,436,756,810,382,412,778,812,380,812,380,810,380,812,382,810,382,408,786,412,778,436,758,434,756,410,780,810,382,434,756,412,780,808,386,806,384,832,360,808,384,832,358,410,778,812,384,808,384,1230,8294,9148,4772,406,786,412,778,418,774,412,780,412,780,812,380,812,380,810,382,412,778,812,382,412,780,810,382,810,382,810,382,810,382,810,382,382,810,412,780,412,780,412,780,410,780,812,382,410,780,412,780,810,384,808,382,808,382,810,382,808,384,412,780,810,384,808,382,1208,8316,9152,4776,378,810,412,778,412,778,412,780,412,780,810,382,810,382,810,382,412,780,810,384,410,780,810,382,810,382,810,382,808,384,810,382,384,810,412,780,412,780,412,780,412,780,812,382,412,780,410,780,810,382,808,382,810,382,810,382,810,380,412,782,808,384,808,382,1208,1,2,38{% else %}9126,4798,380,784,438,754,412,780,436,754,438,754,810,382,810,382,810,382,436,756,810,382,412,778,812,380,812,380,810,380,812,382,810,382,408,786,412,778,436,758,434,756,410,780,810,382,434,756,412,780,808,386,806,384,832,360,808,384,832,358,410,778,812,384,808,384,1230,8294,9148,4772,406,786,412,778,418,774,412,780,412,780,812,380,812,380,810,382,412,778,812,382,412,780,810,382,810,382,810,382,810,382,810,382,382,810,412,780,412,780,412,780,410,780,812,382,410,780,412,780,810,384,808,382,808,382,810,382,808,384,412,780,810,384,808,382,1208,8316,9152,4776,378,810,412,778,412,778,412,780,412,780,810,382,810,382,810,382,412,780,810,384,410,780,810,382,810,382,810,382,808,384,810,382,384,810,412,780,412,780,412,780,412,780,812,382,412,780,410,780,810,382,808,382,810,382,810,382,810,380,412,782,808,384,808,382,1208,1,2,38{% endif %}' 279 | -------------------------------------------------------------------------------- /sensors.yaml: -------------------------------------------------------------------------------- 1 | # - platform: template 2 | # sensors: 3 | # ke_ting_kong_diao_mo_shi: 4 | # friendly_name: 客厅空调模式 5 | # value_template: '{% set mode = state_attr("climate.ke_ting_kong_diao", "fan_mode") %}{% if is_state("climate.ke_ting_kong_diao", "off") %}off{% elif mode == "自动" %}自{% elif mode == "一档" %}一{% elif mode == "二档" %}二{% elif mode == "三档" %}三{% elif mode == "四档" %}四{% elif mode == "五档" %}五{% else %}{{ mode }}{% endif %}' 6 | # can_ting_kong_diao_mo_shi: 7 | # friendly_name: 餐厅空调模式 8 | # value_template: '{% set mode = state_attr("climate.can_ting_kong_diao", "fan_mode") %}{% if is_state("climate.can_ting_kong_diao", "off") %}off{% elif mode == "自动" %}自{% elif mode == "一档" %}一{% elif mode == "二档" %}二{% elif mode == "三档" %}三{% elif mode == "四档" %}四{% elif mode == "五档" %}五{% else %}{{ mode }}{% endif %}' 9 | # zhu_wo_kong_diao_mo_shi: 10 | # friendly_name: 主卧空调模式 11 | # value_template: '{% set mode = state_attr("climate.zhu_wo_kong_diao", "fan_mode") %}{% if is_state("climate.zhu_wo_kong_diao", "off") %}off{% elif mode == "自动" %}自{% elif mode == "一档" %}一{% elif mode == "二档" %}二{% elif mode == "三档" %}三{% elif mode == "四档" %}四{% elif mode == "五档" %}五{% else %}{{ mode }}{% endif %}' 12 | # er_tong_fang_kong_diao_mo_shi: 13 | # friendly_name: 儿童房空调模式 14 | # value_template: '{% set mode = state_attr("climate.er_tong_fang_kong_diao", "fan_mode") %}{% if is_state("climate.er_tong_fang_kong_diao", "off") %}off{% elif mode == "自动" %}自{% elif mode == "一档" %}一{% elif mode == "二档" %}二{% elif mode == "三档" %}三{% elif mode == "四档" %}四{% elif mode == "五档" %}五{% else %}{{ mode }}{% endif %}' 15 | # shu_fang_kong_diao_mo_shi: 16 | # friendly_name: 书房空调模式 17 | # value_template: '{% set mode = state_attr("climate.shu_fang_kong_diao", "fan_mode") %}{% if is_state("climate.shu_fang_kong_diao", "off") %}off{% elif mode == "low" %}一{% elif mode == "mid" %}二{% elif mode == "high" %}三{% elif mode == "highest" %}四{% else %}{{ mode }}{% endif %}' 18 | -------------------------------------------------------------------------------- /zhilace-dash.yaml: -------------------------------------------------------------------------------- 1 | strategy: 2 | type: iframe 3 | url: /local/dash.html 4 | --------------------------------------------------------------------------------