Home Assistant Git Exporter
This commit is contained in:
5
config/01capteur/.vscode/settings.json
vendored
Normal file
5
config/01capteur/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.yaml": "yaml"
|
||||
}
|
||||
}
|
||||
65
config/01capteur/binary_sensor/binary_sensors.yaml
Normal file
65
config/01capteur/binary_sensor/binary_sensors.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
#----------------------------------------
|
||||
#
|
||||
# jour de semaine
|
||||
#----------------------------------------
|
||||
#_ platform: workday
|
||||
#country: FR
|
||||
# workdays: [mon, tue, wed, thu, fri]
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# pi computer & esp & other hardware
|
||||
#----------------------------------------
|
||||
|
||||
# - platform: ping
|
||||
# host: 10.0.0.30
|
||||
# name: pi0_bureau
|
||||
# count: 2
|
||||
# scan_interval: 300
|
||||
# - platform: ping
|
||||
# host: 10.0.0.31
|
||||
# name: pi0_comble2
|
||||
# count: 2
|
||||
# scan_interval: 300
|
||||
# - platform: ping
|
||||
# host: 10.0.0.251
|
||||
# name: WifiHome
|
||||
# count: 2
|
||||
# scan_interval: 300
|
||||
# - platform: ping
|
||||
# host: 10.0.0.100
|
||||
# name: Linksys g
|
||||
# count: 2
|
||||
# scan_interval: 300
|
||||
# - platform: ping
|
||||
# host: 10.0.0.106
|
||||
# name: RM pro
|
||||
# count: 2
|
||||
# scan_interval: 300
|
||||
# - platform: ping
|
||||
# host: 10.0.0.78
|
||||
# name: ArduinoESP
|
||||
# count: 2
|
||||
# scan_interval: 300
|
||||
# - platform: ping
|
||||
# host: 10.0.0.237
|
||||
# name: TV
|
||||
# count: 2
|
||||
# scan_interval: 60
|
||||
|
||||
# - platform: ping
|
||||
# host: 10.0.0.208
|
||||
# name: sonnete
|
||||
# count: 2
|
||||
# scan_interval: 1
|
||||
|
||||
# - platform: template
|
||||
# sensors:
|
||||
# your_sensor:
|
||||
# friendly_name: fenetre
|
||||
# value_template: "{{ is_state('binary_sensor.trigger_sensor', 'off') and (states.trigger_sensor.last_changed < (now() - timedelta(minutes=10))) }}"
|
||||
- platform: meteoalarm
|
||||
country: "france"
|
||||
province: "Haute-Loire"
|
||||
language: "fr-FR"
|
||||
33
config/01capteur/binary_sensor/chaudiere.yaml.old
Normal file
33
config/01capteur/binary_sensor/chaudiere.yaml.old
Normal file
@@ -0,0 +1,33 @@
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## digital inputs
|
||||
# input_type: discrete_input
|
||||
## FC=02 lire discrete inputs de 10001-10086 enlever 1 a register
|
||||
######################################################################
|
||||
|
||||
- platform: modbus
|
||||
scan_interval: 5
|
||||
inputs:
|
||||
- name: porte_chaudiere
|
||||
hub: pimodbus
|
||||
slave: 2
|
||||
address: 0
|
||||
input_type: discrete_input
|
||||
device_class: door
|
||||
|
||||
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## digital outputs
|
||||
# input_type: coil
|
||||
## FC=01 lire coil inputs de 00001-00158 enlever 1 a register
|
||||
######################################################################
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
inputs:
|
||||
- name: circuit chauffage pompe 1
|
||||
hub: pimodbus
|
||||
slave: 2
|
||||
address: 0
|
||||
input_type: coil
|
||||
device_class: moving
|
||||
0
config/01capteur/cover/cover.yaml
Normal file
0
config/01capteur/cover/cover.yaml
Normal file
33
config/01capteur/device_tracker/ping.yaml
Normal file
33
config/01capteur/device_tracker/ping.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
# Example configuration.yaml entry
|
||||
device_tracker:
|
||||
- platform: ping
|
||||
hosts:
|
||||
ipad_denis_p: 10.0.0.150
|
||||
ipad_gilles_p: 10.0.0.223
|
||||
iphone_gilles_p: 10.0.0.103
|
||||
iphone_denis_p: 10.0.0.141
|
||||
|
||||
binary_sensor:
|
||||
- platform: ping
|
||||
hosts:
|
||||
d_pc_domotic: 10.0.0.4
|
||||
d_vm_mqtt: 10.0.0.3
|
||||
d_vm_node_red: 10.0.0.9
|
||||
d_vm_docker: 10.0.0.8
|
||||
d_pi_chauff: 10.0.0.7
|
||||
d_pi0_comble: 10.0.0.6
|
||||
# d_pi_solar: 10.0.0.14
|
||||
# d_pi0_cave: 10.0.0.35
|
||||
d_sonoff_ballon: 10.0.0.52
|
||||
d_sonoff_ecl_bois: 10.0.0.60
|
||||
d_sonoff_dressing: 10.0.0.62
|
||||
d_nodemcu_volet_sal1: 10.0.0.74
|
||||
d_nodemcu_volet_sal2: 10.0.0.75
|
||||
#d_port_lenovo: 10.0.0.113
|
||||
#h_sonnette: 10.0.0.208
|
||||
pi0_bureau: 10.0.0.30
|
||||
pi0_comble: 10.0.0.31
|
||||
h_wifi_home: 10.0.0.251
|
||||
h_wifi_linksys_g: 10.0.0.100
|
||||
h_rm_pro: 10.0.0.112
|
||||
h_tv: 10.0.0.237
|
||||
58
config/01capteur/irrigation.yaml
Normal file
58
config/01capteur/irrigation.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
#https://github.com/rgc99/irrigation_unlimited
|
||||
controllers:
|
||||
zones:
|
||||
- name: "Rosiers"
|
||||
entity_id: "switch.rosier_1"
|
||||
duration: "00:03:00"
|
||||
- name: "Terrasse"
|
||||
entity_id: "switch.terrasse_2"
|
||||
duration: "00:02:00"
|
||||
- name: "Vigne"
|
||||
entity_id: "switch.vigne_3"
|
||||
duration: "00:05:00"
|
||||
sequences:
|
||||
- name: "hiver"
|
||||
duration: "00:02"
|
||||
delay: "00:01"
|
||||
schedules:
|
||||
- time: "06:30"
|
||||
weekday: [mon, tue, wed, thu, fri, sat, sun]
|
||||
month: [dec, jan, feb]
|
||||
zones:
|
||||
- zone_id: 1
|
||||
- zone_id: 2
|
||||
- zone_id: 3
|
||||
- name: "Eté"
|
||||
duration: "00:02"
|
||||
delay: "00:01"
|
||||
schedules:
|
||||
- time: "06:30"
|
||||
weekday: [mon, tue, wed, thu, fri, sat, sun]
|
||||
month: [jun, jul, aug]
|
||||
zones:
|
||||
- zone_id: 1
|
||||
- zone_id: 2
|
||||
- zone_id: 3
|
||||
- name: "Printemp & Automne"
|
||||
duration: "00:02"
|
||||
delay: "00:01"
|
||||
schedules:
|
||||
- time: "06:30"
|
||||
weekday: [mon, tue, wed, thu, fri, sat, sun]
|
||||
month: [mar, apr, may, sep, oct, nov]
|
||||
zones:
|
||||
- zone_id: 3
|
||||
- zone_id: 2
|
||||
- zone_id: 1
|
||||
|
||||
- name: "Soirée"
|
||||
duration: "00:02"
|
||||
delay: "00:01"
|
||||
schedules:
|
||||
- time: "20:30"
|
||||
weekday: [mon, tue, wed, thu, fri, sat, sun]
|
||||
month: [jun, jul, aug]
|
||||
zones:
|
||||
- zone_id: 3
|
||||
- zone_id: 2
|
||||
- zone_id: 1
|
||||
5
config/01capteur/light/.vscode/settings.json
vendored
Normal file
5
config/01capteur/light/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.yaml": "home-assistant"
|
||||
}
|
||||
}
|
||||
8
config/01capteur/light/group_lights.yaml
Normal file
8
config/01capteur/light/group_lights.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
#salon:
|
||||
# name: plafond_salon_z
|
||||
# entities:
|
||||
# - light.tz3000_qd7hej8u_ts0505b_9037cafe_level_light_color_on_off
|
||||
# - light.tz3000_qd7hej8u_ts0505b_fc94bafe_level_light_color_on_off
|
||||
|
||||
|
||||
|
||||
70
config/01capteur/light/lights.yaml
Normal file
70
config/01capteur/light/lights.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
|
||||
# #----------------------------------------
|
||||
# #
|
||||
# # RFXCOM with Node-red
|
||||
# #
|
||||
# #----------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# name: "applique_salon"
|
||||
# schema: json
|
||||
# state_topic: "home/light/a_salon"
|
||||
# command_topic: "home/light/a_salon/set"
|
||||
# brightness: true
|
||||
# rgb: false
|
||||
# brightness_scale: 100
|
||||
# unique_id: "AC/0x011E611E/1"
|
||||
# # state_topic: "home/app_salon/light/status"
|
||||
# # command_topic: "home/app_salon/light/switch"
|
||||
# # brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# # brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# # qos: 0
|
||||
# # payload_on: "On"
|
||||
# # payload_off: "Off"
|
||||
# # optimistic: false
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# name: "applique_cuisine"
|
||||
# schema: json
|
||||
# state_topic: "home/light/a_cuisine"
|
||||
# command_topic: "home/light/a_cuisine/set"
|
||||
# brightness: true
|
||||
# rgb: false
|
||||
# brightness_scale: 100
|
||||
# unique_id: "AC/0x011E611E/2"
|
||||
# # state_topic: "home/app_salon/light/status"
|
||||
# # command_topic: "home/app_salon/light/switch"
|
||||
# # brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# # brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# # qos: 0
|
||||
# # payload_on: "On"
|
||||
# # payload_off: "Off"
|
||||
# # optimistic: false
|
||||
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# name: "plafond_cuisine"
|
||||
# schema: json
|
||||
# state_topic: "home/light/p_cuisine"
|
||||
# command_topic: "home/light/p_cuisine/set"
|
||||
# brightness: true
|
||||
# rgb: false
|
||||
# brightness_scale: 100
|
||||
# unique_id: "AC/0x011E611E/4"
|
||||
# # state_topic: "home/app_salon/light/status"
|
||||
# # command_topic: "home/app_salon/light/switch"
|
||||
# # brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# # brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# # qos: 0
|
||||
# # payload_on: "On"
|
||||
# # payload_off: "Off"
|
||||
# # optimistic: false
|
||||
|
||||
|
||||
|
||||
417
config/01capteur/light/lights.yaml.old
Normal file
417
config/01capteur/light/lights.yaml.old
Normal file
@@ -0,0 +1,417 @@
|
||||
- platform: mqtt
|
||||
name: "LED"
|
||||
command_topic: "cmnd/20/Output/14"
|
||||
state_topic: "stat/20/Output/14"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 1"
|
||||
command_topic: "cmnd/20/Output/1"
|
||||
state_topic: "stat/20/Output/1"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 2"
|
||||
command_topic: "cmnd/20/Output/2"
|
||||
state_topic: "stat/20/Output/2"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 3"
|
||||
command_topic: "cmnd/20/Output/3"
|
||||
state_topic: "stat/20/Output/3"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 4"
|
||||
command_topic: "cmnd/20/Output/4"
|
||||
state_topic: "stat/20/Output/4"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 5"
|
||||
command_topic: "cmnd/20/Output/5"
|
||||
state_topic: "stat/20/Output/5"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 6"
|
||||
command_topic: "cmnd/20/Output/6"
|
||||
state_topic: "stat/20/Output/6"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 7"
|
||||
command_topic: "cmnd/20/Output/7"
|
||||
state_topic: "stat/20/Output/7"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 8"
|
||||
command_topic: "cmnd/20/Output/8"
|
||||
state_topic: "stat/20/Output/8"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 9"
|
||||
command_topic: "cmnd/20/Output/9"
|
||||
state_topic: "stat/20/Output/9"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 10"
|
||||
command_topic: "cmnd/20/Output/10"
|
||||
state_topic: "stat/20/Output/10"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 11"
|
||||
command_topic: "cmnd/20/Output/11"
|
||||
state_topic: "stat/20/Output/11"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 12"
|
||||
command_topic: "cmnd/20/Output/12"
|
||||
state_topic: "stat/20/Output/12"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay_13"
|
||||
command_topic: "cmnd/20/Output/13"
|
||||
state_topic: "stat/20/Output/13"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
- platform: mqtt
|
||||
name: "relay 14"
|
||||
command_topic: "cmnd/20/Output/14"
|
||||
state_topic: "stat/20/Output/14"
|
||||
payload_on: "0"
|
||||
payload_off: "1"
|
||||
|
||||
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# tasmota
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
- platform: mqtt
|
||||
name: "Comble"
|
||||
state_topic: "stat/comble/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/comble/Power1"
|
||||
availability_topic: "tele/comble/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
- platform: mqtt
|
||||
name: "Cave"
|
||||
state_topic: "stat/cave/RESULT"
|
||||
value_template: "{{ value_json.POWER1 }}"
|
||||
command_topic: "cmnd/cave/Power1"
|
||||
availability_topic: "tele/cave/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
|
||||
- platform: mqtt
|
||||
name: "Cave2"
|
||||
state_topic: "stat/cave/RESULT"
|
||||
value_template: "{{ value_json.POWER4 }}"
|
||||
command_topic: "cmnd/cave/Power4"
|
||||
availability_topic: "tele/cave/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
- platform: mqtt
|
||||
name: "VMC1"
|
||||
state_topic: "stat/sonoffVMC/RESULT"
|
||||
value_template: "{{ value_json.POWER1 }}"
|
||||
command_topic: "cmnd/sonoffVMC/Power1"
|
||||
availability_topic: "tele/sonoffVMC/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "VMC2"
|
||||
state_topic: "stat/sonoffVMC/RESULT"
|
||||
value_template: "{{ value_json.POWER2 }}"
|
||||
command_topic: "cmnd/sonoffVMC/Power2"
|
||||
availability_topic: "tele/sonoffVMC/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
- platform: mqtt
|
||||
name: "Eclairage bois"
|
||||
state_topic: "stat/garage/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/garage/Power"
|
||||
availability_topic: "tele/garage/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "Couloir"
|
||||
state_topic: "stat/couloir/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/couloir/Power"
|
||||
availability_topic: "tele/couloir/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "Escalier"
|
||||
state_topic: "stat/escalier/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/escalier/POWER"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
availability_topic: "tele/escalier/LWT"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
qos: 1
|
||||
retain: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "Dressing"
|
||||
state_topic: "stat/dressing/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/dressing/Power"
|
||||
availability_topic: "tele/dressing/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
|
||||
|
||||
- platform: mqtt
|
||||
name: "bureau1"
|
||||
state_topic: "stat/bureau1/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/bureau1/Power1"
|
||||
availability_topic: "tele/bureau1/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "bureau2"
|
||||
state_topic: "stat/bureau2/RESULT"
|
||||
value_template: "{{ value_json.POWER }}"
|
||||
command_topic: "cmnd/bureau2/Power1"
|
||||
availability_topic: "tele/bureau2/LWT"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "lampe_bureau"
|
||||
state_topic: "stat/desklamp/POWER"
|
||||
command_topic: "cmnd/desklamp/POWER"
|
||||
availability_topic: "tele/desklamp/LWT"
|
||||
brightness_state_topic: "stat/desklamp/RESULT"
|
||||
brightness_command_topic: "cmnd/desklamp/Dimmer"
|
||||
brightness_scale: 100
|
||||
brightness_value_template: "{{ value_json.Dimmer }}"
|
||||
qos: 1
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# dimmer TUYA
|
||||
#
|
||||
#----------------------------------------
|
||||
- platform: mqtt
|
||||
name: "plafond_cuisine2"
|
||||
state_topic: "stat/plafond_cuisine/POWER"
|
||||
command_topic: "cmnd/plafond_cuisine/POWER"
|
||||
availability_topic: "tele/plafond_cuisine/LWT"
|
||||
brightness_state_topic: "stat/plafond_cuisine/RESULT"
|
||||
brightness_command_topic: "cmnd/plafond_cuisine/Dimmer"
|
||||
brightness_scale: 100
|
||||
brightness_value_template: "{{ value_json.Dimmer }}"
|
||||
qos: 1
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
- platform: mqtt
|
||||
name: "plafond_salon2"
|
||||
state_topic: "stat/plafond_salon/POWER"
|
||||
command_topic: "cmnd/plafond_salon/POWER"
|
||||
availability_topic: "tele/plafond_salon/LWT"
|
||||
brightness_state_topic: "stat/plafond_salon/RESULT"
|
||||
brightness_command_topic: "cmnd/plafond_salon/Dimmer"
|
||||
brightness_scale: 100
|
||||
brightness_value_template: "{{ value_json.Dimmer }}"
|
||||
qos: 1
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
payload_available: "Online"
|
||||
payload_not_available: "Offline"
|
||||
retain: false
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# H801 tasmota RGB
|
||||
#
|
||||
#----------------------------------------
|
||||
- platform: mqtt
|
||||
name: "RGB"
|
||||
state_topic: "stat/sonoffrgb/POWER"
|
||||
command_topic: "cmnd/sonoffrgb/POWER"
|
||||
#brightness_state_topic: "008565AA/rgb/brightness/status"
|
||||
#brightness_command_topic: "008565AA/rgb/brightness/set"
|
||||
rgb_state_topic: "state/sonoffrgb/color"
|
||||
rgb_command_topic: "cmnd/sonoffrgb/color"
|
||||
state_value_template: "{{ value_json.state }}"
|
||||
brightness_value_template: "{{ value_json.brightness }}"
|
||||
rgb_value_template: "{{ value_json.rgb | join(',') }}"
|
||||
qos: 0
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
optimistic: false
|
||||
#brightness: true
|
||||
#rgb: true
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# RFXCOM with Node-red
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
- platform: mqtt
|
||||
name: "applique_salon"
|
||||
schema: json
|
||||
state_topic: "home/light/a_salon"
|
||||
command_topic: "home/light/a_salon/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
unique_id: "AC/0x011E611E/1"
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
|
||||
|
||||
- platform: mqtt
|
||||
name: "applique_cuisine"
|
||||
schema: json
|
||||
state_topic: "home/light/a_cuisine"
|
||||
command_topic: "home/light/a_cuisine/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
unique_id: "AC/0x011E611E/2"
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "plafond_salon"
|
||||
schema: json
|
||||
state_topic: "home/light/p_salon"
|
||||
command_topic: "home/light/p_salon/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
unique_id: "AC/0x011E611E/3"
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
|
||||
- platform: mqtt
|
||||
name: "plafond_cuisine"
|
||||
schema: json
|
||||
state_topic: "home/light/p_cuisine"
|
||||
command_topic: "home/light/p_cuisine/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
unique_id: "AC/0x011E611E/4"
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
|
||||
|
||||
- platform: mqtt
|
||||
name: "chambre"
|
||||
schema: json
|
||||
state_topic: "home/light/chambre"
|
||||
command_topic: "home/light/chambre/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
unique_id: "AC/0x011E611E/5"
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
9
config/01capteur/light/yeelight.yaml.old
Normal file
9
config/01capteur/light/yeelight.yaml.old
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
yeelight:
|
||||
devices:
|
||||
10.0.0.107:
|
||||
name: plafondSalon2
|
||||
transition: 1000
|
||||
use_music_mode: true
|
||||
save_on_change: true
|
||||
model: color4
|
||||
64
config/01capteur/light/yeelight_mqtt.yaml.old
Normal file
64
config/01capteur/light/yeelight_mqtt.yaml.old
Normal file
@@ -0,0 +1,64 @@
|
||||
- platform: mqtt
|
||||
name: "bureau etage"
|
||||
state_topic: "yeelight/light/bureau/status"
|
||||
command_topic: "yeelight/light/bureau/status/set"
|
||||
brightness_state_topic: "yeelight/light/bureau/bright"
|
||||
brightness_command_topic: "yeelight/light/bureau/bright/set"
|
||||
brightness_scale: 100
|
||||
color_temp_state_topic: "yeelight/light/bureau/ct"
|
||||
color_temp_command_topic: "yeelight/light/bureau/ct/set"
|
||||
qos: 0
|
||||
payload_on: "on"
|
||||
payload_off: "off"
|
||||
optimistic: false
|
||||
- platform: mqtt
|
||||
name: "salon 2"
|
||||
state_topic: "yeelight/light/salon2/status"
|
||||
command_topic: "yeelight/light/salon2/status/set"
|
||||
brightness_state_topic: "yeelight/light/salon2/bright"
|
||||
brightness_command_topic: "yeelight/light/salon2/bright/set"
|
||||
brightness_scale: 100
|
||||
color_temp_state_topic: "yeelight/light/salon2/ct"
|
||||
color_temp_command_topic: "yeelight/light/salon2/ct/set"
|
||||
min_mireds: 1700
|
||||
max_mireds: 6500
|
||||
rgb_state_topic: "yeelight/light/salon2/rgb"
|
||||
rgb_command_topic: "yeelight/light/salon2/rgb/set"
|
||||
qos: 0
|
||||
payload_on: "on"
|
||||
payload_off: "off"
|
||||
optimistic: false
|
||||
- platform: mqtt
|
||||
name: "salon 1"
|
||||
state_topic: "yeelight/light/salon1/status"
|
||||
command_topic: "yeelight/light/salon1/status/set"
|
||||
brightness_state_topic: "yeelight/light/salon1/bright"
|
||||
brightness_command_topic: "yeelight/light/salon1/bright/set"
|
||||
brightness_scale: 100
|
||||
color_temp_state_topic: "yeelight/light/salon1/ct"
|
||||
color_temp_command_topic: "yeelight/light/salon1/ct/set"
|
||||
min_mireds: 1700
|
||||
max_mireds: 6500
|
||||
rgb_state_topic: "yeelight/light/salon1/rgb"
|
||||
rgb_command_topic: "yeelight/light/salon1/rgb/set"
|
||||
qos: 0
|
||||
payload_on: "on"
|
||||
payload_off: "off"
|
||||
optimistic: false
|
||||
- platform: mqtt
|
||||
name: "chambre1"
|
||||
state_topic: "yeelight/light/chambre1/status"
|
||||
command_topic: "yeelight/light/chambre1/status/set"
|
||||
brightness_state_topic: "yeelight/light/chambre1/bright"
|
||||
brightness_command_topic: "yeelight/light/chambre1/bright/set"
|
||||
brightness_scale: 100
|
||||
color_temp_state_topic: "yeelight/light/chambre1/ct"
|
||||
color_temp_command_topic: "yeelight/light/chambre1/ct/set"
|
||||
min_mireds: 1700
|
||||
max_mireds: 6500
|
||||
rgb_state_topic: "yeelight/light/chambre1/rgb"
|
||||
rgb_command_topic: "yeelight/light/chambre1/rgb/set"
|
||||
qos: 0
|
||||
payload_on: "on"
|
||||
payload_off: "off"
|
||||
optimistic: false
|
||||
324
config/01capteur/modbus/modbus.yaml
Normal file
324
config/01capteur/modbus/modbus.yaml
Normal file
@@ -0,0 +1,324 @@
|
||||
# Digital Outputs
|
||||
# Function: Read Coil Status (FC=01)
|
||||
# Address Range: 00001-00158
|
||||
|
||||
# Digital Inputs
|
||||
# Function: Read Input Status (FC=02)
|
||||
# Address Range: 10001-10086
|
||||
|
||||
# Actual Values
|
||||
# Function: Read Input Registers(FC=04)
|
||||
# Address Range: 30001-30272
|
||||
# input_type : input
|
||||
|
||||
# Parameters
|
||||
# Function: Read Holding Registers(FC=03)
|
||||
# Address Range: 40001-41094
|
||||
# input_type: holding
|
||||
|
||||
#- name: froling_S3
|
||||
# type: tcp
|
||||
# host: 10.0.0.12
|
||||
# port: 502
|
||||
# maybe need 1 second delay after connect for device to get ready
|
||||
#delay: 1
|
||||
# sensors:
|
||||
# # SYSTEM STATUS
|
||||
# - name: Modbus PE1 System Status Enum
|
||||
# unique_id: modbus_pe1_system_status_enum
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 4000
|
||||
# scan_interval: 30
|
||||
# device_class: enum
|
||||
# - name: Modbus PE1 Furnace Status Enum
|
||||
# unique_id: modbus_pe1_furnace_status_enum
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 4001
|
||||
# scan_interval: 30
|
||||
# device_class: enum
|
||||
# # - name: Modbus PE1 Heating Mode Enum
|
||||
# # unique_id: modbus_pe1_heating_mode_enum
|
||||
# # slave: 2
|
||||
# # input_type: holding
|
||||
# # address: 8046
|
||||
# # scan_interval: 30
|
||||
# # device_class: enum
|
||||
|
||||
# # TEMPERATURES
|
||||
# - name: Modbus PE1 Hotwater Temperature Top
|
||||
# unique_id: modbus_pe1_hotwater_temperature_top
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# # 31631 - 30001 = 1630
|
||||
# address: 1630
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Furnace Temperature
|
||||
# unique_id: modbus_pe1_furnace_temperature
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 0
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Calculated Heater Target Temperature
|
||||
# unique_id: modbus_pe1_calculated_heater_target_temperature
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 27
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Return Flow Temperature
|
||||
# unique_id: modbus_pe1_return_flow_temperature
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 9
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Calculated Target Return Flow Temperature
|
||||
# unique_id: modbus_pe1_calculated_target_return_flow_temperature
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 66
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Target Flow Temperature At Circulation Line
|
||||
# unique_id: modbus_pe1_return_flow_temperature_at_circulation_line
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 711
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Outside Temperature
|
||||
# unique_id: modbus_pe1_outside_temperature
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 1000
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Flow Temperature Actual
|
||||
# unique_id: modbus_pe1_flow_temperature_actual
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 1030
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Flow Temperature Target
|
||||
# unique_id: modbus_pe1_flow_temperature_target
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 1031
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Room Temperature
|
||||
# unique_id: modbus_pe1_room_temperature
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 1032
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Buffer Temperature Top
|
||||
# unique_id: modbus_pe1_buffer_temperature_top
|
||||
# slave: 2
|
||||
# data_type: float16
|
||||
# input_type: input
|
||||
# address: 30121
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
# - name: Modbus PE1 Buffer Temperature Bottom
|
||||
# unique_id: modbus_pe1_buffer_temperature_bottom
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# data_type: float16
|
||||
# address: 30119
|
||||
# scan_interval: 30
|
||||
# scale: 0.5
|
||||
# precision: 0
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: °C
|
||||
|
||||
# # CONSUMPTION
|
||||
# - name: Modbus PE1 Total Pellet Consumption
|
||||
# unique_id: modbus_pe1_total_pellet_consumption
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 83
|
||||
# scan_interval: 3600
|
||||
# scale: 0.1
|
||||
# precision: 1
|
||||
# device_class: weight
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: mg
|
||||
# - name: Modbus PE1 Pellet Consumption KG
|
||||
# unique_id: modbus_pe1_pellet_consumption_kg
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 81
|
||||
# scan_interval: 3600
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: weight
|
||||
# state_class: total
|
||||
# unit_of_measurement: kg
|
||||
# - name: Modbus PE1 Pellet Fill Level
|
||||
# unique_id: modbus_pe1_pellet_fill_level
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 21
|
||||
# scan_interval: 3600
|
||||
# scale: 0.005
|
||||
# precision: 1
|
||||
# device_class: battery
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '%'
|
||||
|
||||
# # PUMP CONTROLS
|
||||
# - name: Modbus PE1 Return Flow Pump Control
|
||||
# unique_id: modbus_pe1_return_flow_pump_control
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 36
|
||||
# scan_interval: 30
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: power_factor
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '%'
|
||||
# - name: Modbus PE1 Water Boiler Pump Control
|
||||
# unique_id: modbus_pe1_water_boiler_pump_control
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 1632
|
||||
# scan_interval: 30
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: power_factor
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '%'
|
||||
# - name: Modbus PE1 Buffer Pump Control
|
||||
# unique_id: modbus_pe1_buffer_pump_control
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 2003
|
||||
# scan_interval: 30
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: power_factor
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '%'
|
||||
|
||||
# # BUFFER CHARGE
|
||||
# - name: Modbus PE1 Buffer Charge
|
||||
# unique_id: modbus_pe1_buffer_charge
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 2006
|
||||
# scan_interval: 30
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: battery
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '%'
|
||||
|
||||
# # MISC
|
||||
# - name: Modbus PE1 Operating Hours
|
||||
# unique_id: modbus_pe1_operating_hours
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 20
|
||||
# scan_interval: 3600
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: duration
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'h'
|
||||
# - name: Modbus PE1 Hours Since Last Maintenance
|
||||
# unique_id: modbus_pe1_hours_since_last_maintenance
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 55
|
||||
# scan_interval: 3600
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: duration
|
||||
# state_class: total
|
||||
# unit_of_measurement: 'h'
|
||||
# - name: Modbus PE1 Hours Of Pellets Operation
|
||||
# unique_id: modbus_pe1_hours_of_pellets_operation
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 62
|
||||
# scan_interval: 3600
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: duration
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'h'
|
||||
# - name: Modbus PE1 Hours Of Heating
|
||||
# unique_id: modbus_pe1_hours_of_heating
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 63
|
||||
# scan_interval: 3600
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: duration
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'h'
|
||||
# - name: Modbus PE1 Hours Until Ash Removal
|
||||
# unique_id: modbus_pe1_hours_until_ash_removal
|
||||
# slave: 2
|
||||
# input_type: input
|
||||
# address: 86
|
||||
# scan_interval: 3600
|
||||
# scale: 1
|
||||
# precision: 0
|
||||
# device_class: duration
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: 'h'
|
||||
5
config/01capteur/mqtt/.vscode/settings.json
vendored
Normal file
5
config/01capteur/mqtt/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.yaml": "home-assistant"
|
||||
}
|
||||
}
|
||||
36
config/01capteur/mqtt/binary_sensor/binarysensor.yaml
Normal file
36
config/01capteur/mqtt/binary_sensor/binarysensor.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
- unique_id: "door_swith_04"
|
||||
name: "porte bureau"
|
||||
state_topic: "switch/porte/bureau"
|
||||
# command_topic: "switch/porte/bureau"
|
||||
device_class: door
|
||||
payload_on: "1"
|
||||
payload_off: "0"
|
||||
#- unique_id: "door_swith_02"
|
||||
# name: "porte garage"
|
||||
# state_topic: "arduino/garage/p_garage"
|
||||
# command_topic: "switch/porte/bureau"
|
||||
# device_class: door
|
||||
# payload_on: "OPEN"
|
||||
# payload_off: "CLOSED"
|
||||
|
||||
#- unique_id: "door_swith_03"
|
||||
# name: "porte cave"
|
||||
# state_topic: "switch/porte/cave"
|
||||
# command_topic: "switch/porte/bureau"
|
||||
# device_class: door
|
||||
# payload_on: "1"
|
||||
# payload_off: "0"
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# Bouton poussoir
|
||||
#
|
||||
#----------------------------------------
|
||||
#- unique_id: switch_chambre_01
|
||||
# name: "Chambre1"
|
||||
# state_topic: "switch/chambre"
|
||||
# command_topic: "switch/porte/bureau"
|
||||
# device_class: light
|
||||
# payload_on: "1"
|
||||
# payload_off: "0"
|
||||
19
config/01capteur/mqtt/binary_sensor/chaudiere.yaml.old
Normal file
19
config/01capteur/mqtt/binary_sensor/chaudiere.yaml.old
Normal file
@@ -0,0 +1,19 @@
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## digital inputs
|
||||
# input_type: discrete_input
|
||||
## FC=02 lire discrete inputs de 10001-10086 enlever 1 a register
|
||||
######################################################################
|
||||
- unique_id: "porte_chaudiere"
|
||||
state_topic: "chaudiere/porte"
|
||||
#device_class: "opening"
|
||||
name: "porte chaudiere"
|
||||
payload_on: "1"
|
||||
payload_off: "0"
|
||||
device_class: door
|
||||
|
||||
|
||||
#state_topic: "switch/porte/chaudiere"
|
||||
# command_topic: "switch/porte/bureau"
|
||||
|
||||
|
||||
62
config/01capteur/mqtt/light/light.yaml
Normal file
62
config/01capteur/mqtt/light/light.yaml
Normal file
@@ -0,0 +1,62 @@
|
||||
#----------------------------------------
|
||||
#
|
||||
# RFXCOM with Node-red
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
- unique_id: "AC/0x011E611E/1"
|
||||
name: "applique_salon"
|
||||
schema: json
|
||||
state_topic: "home/light/a_salon"
|
||||
command_topic: "home/light/a_salon/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
|
||||
|
||||
- unique_id: "AC/0x011E611E/2"
|
||||
name: "applique_cuisine"
|
||||
schema: json
|
||||
state_topic: "home/light/a_cuisine"
|
||||
command_topic: "home/light/a_cuisine/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
|
||||
|
||||
|
||||
- unique_id: "AC/0x011E611E/4"
|
||||
name: "plafond_cuisine"
|
||||
schema: json
|
||||
state_topic: "home/light/p_cuisine"
|
||||
command_topic: "home/light/p_cuisine/set"
|
||||
brightness: true
|
||||
rgb: false
|
||||
brightness_scale: 100
|
||||
|
||||
# state_topic: "home/app_salon/light/status"
|
||||
# command_topic: "home/app_salon/light/switch"
|
||||
# brightness_state_topic: 'home/app_salon/light/brightness'
|
||||
# brightness_command_topic: 'home/app_salon/light/brightness/set'
|
||||
# qos: 0
|
||||
# payload_on: "On"
|
||||
# payload_off: "Off"
|
||||
# optimistic: false
|
||||
10
config/01capteur/mqtt/mqtt.yaml
Normal file
10
config/01capteur/mqtt/mqtt.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
sensor:
|
||||
!include_dir_merge_list sensor/
|
||||
switch:
|
||||
!include_dir_merge_list switch/
|
||||
light:
|
||||
!include_dir_merge_list light/
|
||||
binary_sensor:
|
||||
!include_dir_merge_list binary_sensor/
|
||||
number:
|
||||
!include_dir_merge_list number/
|
||||
8
config/01capteur/mqtt/number/number.yaml
Normal file
8
config/01capteur/mqtt/number/number.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
# - unique_id: mqtt_servo1
|
||||
# name: mqtt_servo
|
||||
# state_topic: arduinomegatest/servo/status
|
||||
# command_topic: arduinomegatest/servo/cmnd
|
||||
# min: 0
|
||||
# max: 100
|
||||
# step: 1
|
||||
# icon: mdi:engine
|
||||
66
config/01capteur/mqtt/sensor/sensor.yaml.old
Normal file
66
config/01capteur/mqtt/sensor/sensor.yaml.old
Normal file
@@ -0,0 +1,66 @@
|
||||
#----------------------------------------
|
||||
#
|
||||
# lux
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
#- unique_id: luminosite_salon_01
|
||||
# state_topic: "sensor/lux"
|
||||
# name: "Luminosité"
|
||||
# device_class: illuminance
|
||||
# unit_of_measurement: "lx"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
|
||||
#- unique_id: courant_t_div_01
|
||||
# state_topic: "arduino/garage/intensite"
|
||||
# name: "Intensité t_divisionnaire"
|
||||
# unit_of_measurement: "A"
|
||||
# device_class: current
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
#- unique_id: power_t_div_01
|
||||
# state_topic: "arduino/garage/puissance"
|
||||
# name: "Puissance t_divisionnaire"
|
||||
# device_class: power
|
||||
# unit_of_measurement: "W"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# chauffage reglage PID
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
- unique_id: "chauff_pid_payload_01"
|
||||
state_topic: "sensor/chauff/pid/payload"
|
||||
name: "payload"
|
||||
- unique_id: "chauff_pid_pv_01"
|
||||
state_topic: "sensor/chauff/pid/pv"
|
||||
name: "pv"
|
||||
value_template: "{{ value | round(3) }}"
|
||||
- unique_id: "chauff_pid_setpoint_01"
|
||||
state_topic: "sensor/chauff/pid/setpoint"
|
||||
name: "setpoint"
|
||||
- unique_id: "chauff_pid_proportional_01"
|
||||
state_topic: "sensor/chauff/pid/proportional"
|
||||
name: "P"
|
||||
value_template: "{{ value | round(3) }}"
|
||||
- unique_id: "chauff_pid_integral_01"
|
||||
state_topic: "sensor/chauff/pid/integral"
|
||||
name: "I"
|
||||
value_template: "{{ value | round(3) }}"
|
||||
- unique_id: "chauff_pid_pderivative_01"
|
||||
state_topic: "sensor/chauff/pid/derivative"
|
||||
name: "D"
|
||||
value_template: "{{ value | round(3) }}"
|
||||
|
||||
|
||||
- unique_id: tempe_pc_domotic
|
||||
state_topic: "domotic/ISAadapter/Package id 0"
|
||||
name: "Temp PC Domotic"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
33
config/01capteur/mqtt/sensor/sensor_arduino_power.yaml.old
Normal file
33
config/01capteur/mqtt/sensor/sensor_arduino_power.yaml.old
Normal file
@@ -0,0 +1,33 @@
|
||||
#arduino mega avec pzem
|
||||
- unique_id: "tab_domo_voltage"
|
||||
state_topic: "comble/pzem/voltage"
|
||||
name: "voltage_tableau_domotique"
|
||||
device_class: voltage
|
||||
unit_of_measurement: "V"
|
||||
state_class: measurement
|
||||
value_template: "{{ value | round(12) }}"
|
||||
|
||||
- unique_id: "tab_domo_current"
|
||||
state_topic: "comble/pzem/courant"
|
||||
name: "courant_tableau_domotique"
|
||||
device_class: current
|
||||
unit_of_measurement: "A"
|
||||
state_class: measurement
|
||||
value_template: "{{ value | round(2) }}"
|
||||
|
||||
- unique_id: "tab_domo_power"
|
||||
state_topic: "comble/pzem/power"
|
||||
name: "Power_tableau_domotique"
|
||||
icon: mdi:solar-power
|
||||
device_class: power
|
||||
unit_of_measurement: "W"
|
||||
state_class: measurement
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
- unique_id: "tab_domo_energy_total"
|
||||
state_topic: "comble/pzem/energy"
|
||||
name: "tableau_domotique_Energy"
|
||||
device_class: energy
|
||||
state_class: total_increasing
|
||||
unit_of_measurement: "Wh"
|
||||
value_template: "{{ value | round(2) }}"
|
||||
97
config/01capteur/mqtt/sensor/sensor_chaudiere.yaml.old
Normal file
97
config/01capteur/mqtt/sensor/sensor_chaudiere.yaml.old
Normal file
@@ -0,0 +1,97 @@
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## actual value - input register
|
||||
# register_type: input
|
||||
## FC=04 de 30001-30272 enlever 1 a register
|
||||
######################################################################
|
||||
|
||||
- unique_id: temp_chaud_01
|
||||
state_topic: "chaudiere/t_chaud"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: temperature
|
||||
name: "T° chaudiere"
|
||||
- unique_id: temp_fumee_01
|
||||
state_topic: "chaudiere/t_fumee"
|
||||
name: "T° fumée"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
- unique_id: temp_board_01
|
||||
state_topic: "chaudiere/t_board"
|
||||
name: "T° board"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
|
||||
- unique_id: temp_ext_N_01
|
||||
state_topic: "chaudiere/t_ext"
|
||||
name: "T°exterieur nord"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
|
||||
|
||||
- unique_id: venti_chaud_01
|
||||
state_topic: "chaudiere/vit_venti"
|
||||
name: "Ventilation"
|
||||
unit_of_measurement: "U/min"
|
||||
|
||||
|
||||
- unique_id: heure_chauff_01
|
||||
state_topic: "chaudiere/h_chauffage"
|
||||
name: "Heure de chauffage"
|
||||
unit_of_measurement: "h"
|
||||
|
||||
|
||||
- unique_id: heure_serv_01
|
||||
state_topic: "chaudiere/h_service"
|
||||
name: "Heure de service"
|
||||
unit_of_measurement: "h"
|
||||
|
||||
|
||||
- unique_id: temp_dep_chauff_01
|
||||
state_topic: "chaudiere/t_dep_chauff"
|
||||
name: "T° départ"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
|
||||
|
||||
- unique_id: charge_tampon_01
|
||||
state_topic: "chaudiere/charge_tampon"
|
||||
name: "Charge du tampon"
|
||||
|
||||
|
||||
- unique_id: tampon_haut_01
|
||||
state_topic: "chaudiere/tampon_haut"
|
||||
name: "tampon haut"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
|
||||
|
||||
- unique_id: tampon_bas_01
|
||||
state_topic: "chaudiere/tampon_bas"
|
||||
name: "tampon bas"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
|
||||
|
||||
- unique_id: temp_cons_fumee_01
|
||||
state_topic: "chaudiere/cons_t_fumee"
|
||||
name: "Consigne T° fumée"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
|
||||
|
||||
- unique_id: etat_chaud_01
|
||||
state_topic: "chaudiere/etat_chaudiere"
|
||||
name: "Etat chaudiere"
|
||||
|
||||
|
||||
- unique_id: O2_resi_01
|
||||
state_topic: "chaudiere/O2_res"
|
||||
name: "O2_residuel"
|
||||
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## parameter - holding registers
|
||||
# register_type: holding
|
||||
## FC=03 de 40001-41094 enlever 1 a register
|
||||
######################################################################
|
||||
|
||||
40
config/01capteur/mqtt/sensor/sensor_portable.yaml.old
Normal file
40
config/01capteur/mqtt/sensor/sensor_portable.yaml.old
Normal file
@@ -0,0 +1,40 @@
|
||||
# pc portable lenovo battery
|
||||
- unique_id: portable_lenovo_battery
|
||||
name: portable_lenovo_battery
|
||||
device_class: battery
|
||||
unit_of_measurement: "%"
|
||||
# payload_on: low
|
||||
# payload_off: normal
|
||||
qos: 1
|
||||
#availability_topic: home/downstairs/living-room/front-windows/availability
|
||||
#payload_available: online
|
||||
#payload_not_available: offline
|
||||
state_topic: computer/lenovo
|
||||
value_template: "{{ value_json.percent }}"
|
||||
|
||||
- unique_id: portable_elitebook_corei5
|
||||
name: portable_elitebook_corei5
|
||||
device_class: battery
|
||||
unit_of_measurement: "%"
|
||||
# payload_on: low
|
||||
# payload_off: normal
|
||||
qos: 1
|
||||
#availability_topic: home/downstairs/living-room/front-windows/availability
|
||||
#payload_available: online
|
||||
#payload_not_available: offline
|
||||
state_topic: computer/corei5
|
||||
value_template: "{{ value_json.percent }}"
|
||||
|
||||
|
||||
- unique_id: portable_elitebook_centrino
|
||||
name: portable_elitebook_centrino
|
||||
device_class: battery
|
||||
unit_of_measurement: "%"
|
||||
# payload_on: low
|
||||
# payload_off: normal
|
||||
qos: 1
|
||||
#availability_topic: home/downstairs/living-room/front-windows/availability
|
||||
#payload_available: online
|
||||
#payload_not_available: offline
|
||||
state_topic: computer/centrino
|
||||
value_template: "{{ value_json.percent }}"
|
||||
244
config/01capteur/mqtt/sensor/sensor_solar.yaml
Normal file
244
config/01capteur/mqtt/sensor/sensor_solar.yaml
Normal file
@@ -0,0 +1,244 @@
|
||||
# # modbus sensors for EPEver
|
||||
# - unique_id: "array_voltage"
|
||||
# ## reg 3100
|
||||
# state_topic: "tracer/sensor/tracer_1_pv_array_voltage"
|
||||
# name: "solar_PV_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(12) }}"
|
||||
|
||||
# - unique_id: "array_current"
|
||||
# ## reg 3101
|
||||
# state_topic: "tracer/sensor/tracer_1_pv_array_current"
|
||||
# name: "solar_PV_Current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "array_power"
|
||||
# ## reg 3102 3103
|
||||
# state_topic: "tracer/sensor/tracer_1_pv_array_power"
|
||||
# name: "solar_PV_Power"
|
||||
# icon: mdi:solar-power
|
||||
# device_class: power
|
||||
# unit_of_measurement: 'W'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "battery_voltage"
|
||||
# ## reg 3104
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_voltage"
|
||||
# name: "solar_Battery_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "battery_charging_current"
|
||||
# ##reg 3105
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_charging_current"
|
||||
# name: "Battery_charging_Current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "max_battery_voltage_today_01"
|
||||
# #reg 3302
|
||||
# state_topic: "tracer/sensor/tracer_1_max_battery_voltage_today"
|
||||
# name: "solar_Battery_Max_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "min_battery_voltage_today_01"
|
||||
# #reg 3303
|
||||
# state_topic: "tracer/sensor/tracer_1_min_battery_voltage_today"
|
||||
# name: "solar_Battery_Min_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "net_battery_current"
|
||||
# ##reg 331B-331C
|
||||
# state_topic: "tracer/sensor/tracer_1_net_battery_current"
|
||||
# name: "net_Battery_Current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "battery_power"
|
||||
# state_topic: "tracer/registers/Charging equipment output power/value"
|
||||
# name: "solar_Battery_Power"
|
||||
# device_class: power
|
||||
# unit_of_measurement: 'W'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "battery_temperature"
|
||||
# #reg 3110
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_temperature"
|
||||
# name: "solar_Battery_Temperature"
|
||||
# icon: mdi:thermometer
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '°C'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "battery_SOC"
|
||||
# #reg 311A
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_soc"
|
||||
# name: "solar_Battery_SOC"
|
||||
# unit_of_measurement: '%'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "device_temperature"
|
||||
# #reg 3111
|
||||
# state_topic: "tracer/sensor/tracer_1_charger_temperature"
|
||||
# name: "solar_device_Temperature"
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '°C'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "solar_PV_status"
|
||||
# ## reg 3201
|
||||
# state_topic: "tracer/sensor/tracer_1_equipment_status"
|
||||
# name: "solar_PV_Status"
|
||||
# # device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# value_template: "{{ value }}"
|
||||
|
||||
# - unique_id: "battery_status"
|
||||
# ## reg 3200
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_status"
|
||||
# name: "solar_battery_Status"
|
||||
# value_template: "{{ value }}"
|
||||
|
||||
# - unique_id: "generated_energy_today"
|
||||
# ## reg 330C-330D
|
||||
# state_topic: "tracer/sensor/tracer_1_generated_energy_today"
|
||||
# name: "generated_Today_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "generated_energy_total"
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_total_generated_energy"
|
||||
# name: "generated_total_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "generated_energy_month"
|
||||
# ## reg 330E-330F
|
||||
# state_topic: "tracer/sensor/tracer_1_generated_energy_this_month"
|
||||
# name: "generated_month_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "generated_energy_year"
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_generated_energy_this_year"
|
||||
# name: "generated_year_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "load power"
|
||||
# ##reg 310E-310F
|
||||
# state_topic: "tracer/sensor/tracer_1_load_power"
|
||||
# name: "DC_Load_Power"
|
||||
# device_class: power
|
||||
# unit_of_measurement: 'W'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "load voltage"
|
||||
# ## reg 310C
|
||||
# state_topic: "tracer/sensor/tracer_1_load_voltage"
|
||||
# name: "DC_Load_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "load current"
|
||||
# ## reg 310D
|
||||
# state_topic: "tracer/sensor/tracer_1_load_current"
|
||||
# name: "DC_Load_Courant"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "tracer_1_day_night"
|
||||
# ## reg 200C
|
||||
# state_topic: "tracer/sensor/tracer_1_day/night"
|
||||
# name: "solar_Day_Night"
|
||||
# #device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# value_template: "{{ value }}"
|
||||
|
||||
# - unique_id: "energy_today"
|
||||
# ## reg 330C-330D
|
||||
# state_topic: "tracer/sensor/tracer_1_consumed_energy_today"
|
||||
# name: "consumed_Today_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "consumed_energy_total"
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_total_consumed_energy"
|
||||
# name: "consumed_Total_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "consumed_energy_month"
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_consumed_energy_this_month"
|
||||
# name: "consumed_Month_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "consumed_energy_year"
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_consumed_energy_this_year"
|
||||
# name: "consumed_Year_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - unique_id: "charging mode"
|
||||
# ## reg 3201
|
||||
# state_topic: "tracer/sensor/tracer_1_charging_mode"
|
||||
# name: "charging mode"
|
||||
# # device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: "servo_pos1"
|
||||
# ## reg 3201
|
||||
# state_topic: "arduinomegatest/servo/status"
|
||||
# name: "servo_pos"
|
||||
# # device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# # value_template: "{{ value }}"
|
||||
49
config/01capteur/mqtt/sensor/sensor_solar_ecu.yaml
Normal file
49
config/01capteur/mqtt/sensor/sensor_solar_ecu.yaml
Normal file
@@ -0,0 +1,49 @@
|
||||
# - unique_id: ecuR_courant
|
||||
# state_topic: "stat/ecu_r/current"
|
||||
# name: "courant ecuR"
|
||||
# device_class: current
|
||||
# unit_of_measurement: "A"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: ecuR_tension
|
||||
# state_topic: "stat/ecu_r/volt"
|
||||
# name: "tension ecuR"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: "V"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: ecuR_puissance
|
||||
# state_topic: "stat/ecu_r/power"
|
||||
# name: "puissance ecuR"
|
||||
# device_class: power
|
||||
# unit_of_measurement: "W"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: ecuR_frequence
|
||||
# state_topic: "stat/ecu_r/frequency"
|
||||
# name: "frequence ecuR"
|
||||
# device_class: frequency
|
||||
# unit_of_measurement: "Hz"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: ecuR_cos_phi
|
||||
# state_topic: "stat/ecu_r/cos_phi"
|
||||
# name: "cos Phi ecuR"
|
||||
# device_class: power_factor
|
||||
# unit_of_measurement: "%"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: ecuR_temperature
|
||||
# state_topic: "stat/ecu_r/temperature"
|
||||
# name: "temperature ecuR"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - unique_id: ecuR_energy_today
|
||||
# state_topic: "stat/ecu_r/energy_today"
|
||||
# name: "energy_today ecuR"
|
||||
# device_class: energy
|
||||
# unit_of_measurement: "Wh"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# state_class: total_increasing
|
||||
62
config/01capteur/mqtt/sensor/sensor_temperature.yaml
Normal file
62
config/01capteur/mqtt/sensor/sensor_temperature.yaml
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
#----------------------------------------
|
||||
#
|
||||
# temperature
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
- unique_id: temp_bureau_01
|
||||
state_topic: "temp/bureau"
|
||||
name: "T Bureau"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
#- unique_id: temp_cave_01
|
||||
# state_topic: "temp/cave"
|
||||
# name: "T Cave"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
#- unique_id: temp_garage_01
|
||||
# state_topic: "temp/garage"
|
||||
# name: "T Garage"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
- unique_id: temp_chambre_01
|
||||
state_topic: "temp/chambre1"
|
||||
name: "T Chambre1"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
- unique_id: temp_chambre_02
|
||||
state_topic: "temp/chambre2"
|
||||
name: "T Chambre2"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: temperature
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
- unique_id: temp_comble_01
|
||||
state_topic: "temp/comble"
|
||||
name: "T Comble"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
- unique_id: hum_sdb_01
|
||||
state_topic: "hum/sdb"
|
||||
name: "H% salle de bain"
|
||||
device_class: humidity
|
||||
unit_of_measurement: "%"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
|
||||
- unique_id: temp_sdb_01
|
||||
state_topic: "temp/sdb"
|
||||
name: "T salle de bain"
|
||||
device_class: temperature
|
||||
unit_of_measurement: "°C"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
17
config/01capteur/mqtt/switch/switch.yaml.old
Normal file
17
config/01capteur/mqtt/switch/switch.yaml.old
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
- unique_id: bedroom_switch
|
||||
name: "Bedroom Switch"
|
||||
state_topic: "home/bedroom/switch1"
|
||||
command_topic: "home/bedroom/switch1/set"
|
||||
availability:
|
||||
- topic: "home/bedroom/switch1/available"
|
||||
payload_not_available: "offline"
|
||||
payload_available: "online"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
state_on: "ON"
|
||||
state_off: "OFF"
|
||||
optimistic: false
|
||||
qos: 0
|
||||
retain: true
|
||||
28
config/01capteur/mqtt/switch/switch2.yaml.old
Normal file
28
config/01capteur/mqtt/switch/switch2.yaml.old
Normal file
@@ -0,0 +1,28 @@
|
||||
#----------------------------------------
|
||||
#
|
||||
# on off konica
|
||||
#
|
||||
#----------------------------------------
|
||||
- unique_id: switch_konica_01
|
||||
name: "switch_konica"
|
||||
command_topic: "cmnd/konica/power"
|
||||
state_topic: "stat/konica/power"
|
||||
payload_on: "on"
|
||||
payload_off: "off"
|
||||
|
||||
|
||||
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# relay chaudiere
|
||||
#
|
||||
#----------------------------------------
|
||||
- unique_id: relay_chaudiere_01
|
||||
name: "relay_chauffage"
|
||||
command_topic: "cmnd/relay/chaudiere"
|
||||
state_topic: "stat/relay/chaudiere"
|
||||
payload_on: "1"
|
||||
payload_off: "0"
|
||||
|
||||
|
||||
647
config/01capteur/openhasp.yaml.old
Normal file
647
config/01capteur/openhasp.yaml.old
Normal file
@@ -0,0 +1,647 @@
|
||||
#openhasp:
|
||||
plate1:
|
||||
objects:
|
||||
- obj: "p0b2"
|
||||
properties:
|
||||
"text": '{{ states("sensor.ecowitt_temp")| float | round(1) }}°C'
|
||||
- obj: "p0b1" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.ecowitt_tempin")| float | round(1)}}°C'
|
||||
#page 1 sensor:
|
||||
- obj: "p1b11" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.temp_fumee")| float | round(1) }}°C'
|
||||
- obj: "p1b13" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.temp_depart_chauffage")| float | round(1) }}°C'
|
||||
|
||||
#page 1 light:
|
||||
|
||||
- obj: "p1b1" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.lumieres_couloir") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.lumieres_couloir", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.lumieres_couloir"
|
||||
|
||||
- obj: "p1b2" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.applique_salon") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.applique_salon", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.applique_salon"
|
||||
|
||||
- obj: "p1b3" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.applique_cuisine") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.applique_cuisine", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.applique_cuisine"
|
||||
|
||||
- obj: "p1b4" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.lumieres_escaliers") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.lumieres_escaliers", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.lumieres_escaliers"
|
||||
|
||||
- obj: "p1b7" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.eclairage_bois") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.eclairage_bois", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.eclairage_bois"
|
||||
- obj: "p1b8" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.yeelight_color4_0x15771126") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.yeelight_color4_0x15771126", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.yeelight_color4_0x15771126"
|
||||
|
||||
- obj: "p1b9" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("switch.kc868_a8_d758d0_d758d0_lumiere_comble_kc") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("switch.kc868_a8_d758d0_d758d0_lumiere_comble_kc", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "switch.kc868_a8_d758d0_d758d0_lumiere_comble_kc"
|
||||
#page 2 light
|
||||
- obj: "p2b21" # Light brightness
|
||||
properties:
|
||||
"val": "{{ state_attr('light.applique_salon', 'brightness') if state_attr('light.applique_salon', 'brightness') != None else 0 }}"
|
||||
event:
|
||||
"changed":
|
||||
- service: light.turn_on
|
||||
data:
|
||||
entity_id: light.applique_salon
|
||||
brightness: "{{ val }}"
|
||||
"up":
|
||||
- service: light.turn_on
|
||||
data:
|
||||
entity_id: light.applique_salon
|
||||
brightness: "{{ val }}"
|
||||
- obj: "p2b23" # Light brightness
|
||||
properties:
|
||||
"val": "{{ state_attr('light.lumieres_plafond', 'brightness') if state_attr('light.lumieres_plafond', 'brightness') != None else 0 }}"
|
||||
event:
|
||||
"changed":
|
||||
- service: light.turn_on
|
||||
data:
|
||||
entity_id: light.lumieres_plafond
|
||||
brightness: "{{ val }}"
|
||||
"up":
|
||||
- service: light.turn_on
|
||||
data:
|
||||
entity_id: light.lumieres_plafond
|
||||
brightness: "{{ val }}"
|
||||
- obj: "p2b25" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("light.eclairage_bois") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("light.eclairage_bois", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "light.eclairage_bois"
|
||||
|
||||
#thermostat
|
||||
- obj: "p3b20" # arc slider
|
||||
properties:
|
||||
"val": >
|
||||
{% if state_attr('climate.salon','temperature') is not none %}
|
||||
{{ state_attr('climate.salon','temperature') | int * 10 }}
|
||||
{%- endif %}
|
||||
"min": >
|
||||
{% if state_attr('climate.salon','min_temp') is not none %}
|
||||
{{ state_attr('climate.salon','min_temp') | int * 10 }}
|
||||
{%- endif %}
|
||||
"max": >
|
||||
{% if state_attr('climate.salon','max_temp') is not none %}
|
||||
{{ state_attr('climate.salon','max_temp') | int * 10 }}
|
||||
{%- endif %}
|
||||
"opacity": "{{ 60 if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 255 }}"
|
||||
"click": "{{ 'false' if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 'true' }}"
|
||||
"line_color1": >
|
||||
{% if is_state('climate.salon', 'cool') %}
|
||||
{{ "#346beb" }}
|
||||
{%-elif is_state('climate.salon', 'heat_cool') %}
|
||||
{{ "#34bdeb" }}
|
||||
{%-elif is_state('climate.salon', 'heat') %}
|
||||
{{ "#eb3434" }}
|
||||
{%-elif is_state('climate.salon', 'dry') %}
|
||||
{{ "#ebeb34" }}
|
||||
{%-elif is_state('climate.salon', 'fan_only') %}
|
||||
{{ "#34eb77" }}
|
||||
{%-else %}
|
||||
{{ "#9f96b0" }}
|
||||
{% endif %}
|
||||
event:
|
||||
"changed":
|
||||
- service: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.salon
|
||||
data:
|
||||
temperature: "{{ val | int / 10 }}"
|
||||
"up":
|
||||
- service: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.salon
|
||||
data:
|
||||
temperature: "{{ val | int / 10 }}"
|
||||
|
||||
- obj: "p3b21" # gauge current temp
|
||||
properties:
|
||||
"val": >
|
||||
{% if not (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) %}
|
||||
{{ states('climate.salon') | float (default=0) * 10 }}
|
||||
{%- endif %}
|
||||
"min": >
|
||||
{% if state_attr('climate.salon','min_temp') is not none %}
|
||||
{{ state_attr('climate.salon','min_temp') | int * 10 }}
|
||||
{%- endif %}
|
||||
"max": >
|
||||
{% if state_attr('climate.salon','max_temp') is not none %}
|
||||
{{ state_attr('climate.salon','max_temp') | int * 10 }}
|
||||
{%- endif %}
|
||||
"critical_value": >
|
||||
{% if state_attr('climate.salon','max_temp') is not none %}
|
||||
{{ state_attr('climate.salon','max_temp') | int * 10 + 1 }}
|
||||
{%- endif %}
|
||||
"label_count": >
|
||||
{% if state_attr('climate.salon','max_temp') is not none %}
|
||||
{{ state_attr('climate.salon','max_temp') | int - state_attr('climate.salon','min_temp') | int + 1 }}
|
||||
{%- endif %}
|
||||
"line_count": >
|
||||
{% if state_attr('climate.salon','max_temp') is not none %}
|
||||
{{ (state_attr('climate.salon','max_temp') | int - state_attr('climate.salon','min_temp') | int) * 2 + 1 }}
|
||||
{%- endif %}
|
||||
"opacity": "{{ 60 if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 255 }}"
|
||||
|
||||
- obj: "p3b23" # label current temp (and +/- with short/long touch)
|
||||
properties:
|
||||
"text": >
|
||||
{% if (is_state('sensor.ecowitt_tempin','unavailable') or is_state('sensor.ecowitt_tempin','unknown')) %}
|
||||
{{ "--.-" }}
|
||||
{%-else %}
|
||||
{{ states('sensor.ecowitt_tempin') | round(1,default=0) }}
|
||||
{%- endif %}
|
||||
"click": "{{ 'false' if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 'true' }}"
|
||||
"opacity": "{{ 60 if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 255 }}"
|
||||
event:
|
||||
"up":
|
||||
- service: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.salon
|
||||
data:
|
||||
temperature: "{{ state_attr('climate.salon','temperature') + state_attr('climate.salon','target_temp_step') | float(default=1)}}"
|
||||
"long":
|
||||
- service: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.salon
|
||||
data:
|
||||
temperature: "{{ state_attr('climate.salon','temperature') - state_attr('climate.salon','target_temp_step') | float(default=1)}}"
|
||||
|
||||
- obj: "p3b25" # label target temp
|
||||
properties:
|
||||
"text": >
|
||||
{% if state_attr('climate.salon','temperature') is not none %}
|
||||
{{ state_attr('climate.salon','temperature') }}
|
||||
{%- endif %}
|
||||
"opacity": "{{ 60 if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 255 }}"
|
||||
|
||||
- obj: "p3b41" # on/off switch
|
||||
properties:
|
||||
"val": "{{ 0 if (is_state('climate.salon', 'off') or is_state('climate.salon', 'unavailable')) else 1 }}"
|
||||
"click": "{{ 'false' if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 'true' }}"
|
||||
"opacity": "{{ 60 if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 255 }}"
|
||||
event:
|
||||
"down":
|
||||
- service_template: >
|
||||
{% if val == 0 -%}
|
||||
climate.turn_on
|
||||
{% else -%}
|
||||
climate.turn_off
|
||||
{% endif -%}
|
||||
entity_id: "climate.salon"
|
||||
|
||||
- obj: "p3b30" # tab dots
|
||||
event:
|
||||
"changed":
|
||||
- service: openhasp.command
|
||||
target:
|
||||
entity_id: openhasp.your_plate
|
||||
data:
|
||||
keyword: p3b26.text
|
||||
parameters: >
|
||||
{% if val == 0 %}
|
||||
{{ "#000000 \u2022# #909090 \u2022# #909090 \u2022#" | e }}
|
||||
{%-elif val == 1 %}
|
||||
{{ "#909090 \u2022# #000000 \u2022# #909090 \u2022#" | e }}
|
||||
{%-elif val == 2 %}
|
||||
{{ "#909090 \u2022# #909090 \u2022# #000000 \u2022#" | e }}
|
||||
{% endif %}
|
||||
|
||||
- obj: "p3b42" # dropdown with fan_modes
|
||||
properties:
|
||||
"options": >
|
||||
{% if state_attr('climate.salon','fan_modes') is not none %}{%for mode in state_attr('climate.salon','fan_modes')%}
|
||||
{%- if mode == 'auto' -%}
|
||||
Automatic{{"\n"|e}}
|
||||
{%- elif mode == 'low' -%}
|
||||
Low{{"\n"|e}}
|
||||
{%- elif mode == 'medium' -%}
|
||||
Medium{{"\n"|e}}
|
||||
{%- elif mode == 'high' -%}
|
||||
High{{"\n"|e}}
|
||||
{%- elif mode == 'turbo' -%}
|
||||
Turbo{{"\n"|e}}
|
||||
{%- endif -%}
|
||||
{%-if not loop.last%}{%-endif%}{%-endfor%}{% endif %}
|
||||
"click": "{{ 'false' if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 'true' }}"
|
||||
"val": >
|
||||
{% if not (is_state('climate.salon','unavailable')) %}{%for mode in state_attr('climate.salon','fan_modes')%}
|
||||
{{loop.index -1 if mode == state_attr('climate.salon','fan_mode') }}
|
||||
{%-endfor%}{% endif %}
|
||||
event:
|
||||
"changed":
|
||||
- service: climate.set_fan_mode
|
||||
target:
|
||||
entity_id: climate.salon
|
||||
data:
|
||||
fan_mode: >
|
||||
{% if text == "Automatic" -%}
|
||||
auto
|
||||
{% elif text == 'Low' -%}
|
||||
low
|
||||
{% elif text == 'Medium' -%}
|
||||
medium
|
||||
{% elif text == 'High' -%}
|
||||
high
|
||||
{% elif text == 'Turbo' -%}
|
||||
turbo
|
||||
{% endif -%}
|
||||
|
||||
- obj: "p3b43" # dropdown with hvac_modes
|
||||
properties:
|
||||
"options": >
|
||||
{% if state_attr('climate.salon','hvac_modes') is not none %}{%for mode in state_attr('climate.salon','hvac_modes')%}
|
||||
{%- if mode == 'off' -%}
|
||||
Off{{"\n"|e}}
|
||||
{%- elif mode == 'heat' -%}
|
||||
Heating{{"\n"|e}}
|
||||
{%- elif mode == 'cool' -%}
|
||||
Cooling{{"\n"|e}}
|
||||
{%- elif mode == 'heat_cool' -%}
|
||||
Heat/Cool{{"\n"|e}}
|
||||
{%- elif mode == 'dry' -%}
|
||||
Drying{{"\n"|e}}
|
||||
{%- elif mode == 'fan_only' -%}
|
||||
Fan only{{"\n"|e}}
|
||||
{%- else -%}
|
||||
On{{"\n"|e}}
|
||||
{%- endif -%}
|
||||
{%-if not loop.last%}{%-endif%}{%-endfor%}{% endif %}
|
||||
"click": "{{ 'false' if (is_state('climate.salon','unavailable') or is_state('climate.salon','unknown')) else 'true' }}"
|
||||
"val": >
|
||||
{% if not (is_state('climate.salon','unavailable')) %}{%for mode in state_attr('climate.salon','hvac_modes')%}
|
||||
{{loop.index -1 if mode == states('climate.salon') }}
|
||||
{%-endfor%}{% endif %}
|
||||
event:
|
||||
"changed":
|
||||
- service: climate.set_hvac_mode
|
||||
target:
|
||||
entity_id: climate.salon
|
||||
data:
|
||||
hvac_mode: >
|
||||
{% if text == "Off" -%}
|
||||
off
|
||||
{% elif text == 'Heating' -%}
|
||||
heat
|
||||
{% elif text == 'Cooling' -%}
|
||||
cool
|
||||
{% elif text == 'Heat/Cool' -%}
|
||||
heat_cool
|
||||
{% elif text == 'Drying' -%}
|
||||
dry
|
||||
{% elif text == 'Fan only' -%}
|
||||
fan_only
|
||||
{% endif -%}
|
||||
# solar page4
|
||||
- obj: "p4b41" # light-switch toggle button
|
||||
properties:
|
||||
"val": '{{ 1 if states("switch.relay_inverter_1") == "on" else 0 }}'
|
||||
"text": '{{ "\uE6E8" if is_state("switch.relay_inverter_1", "on") else "\uE335" | e }}'
|
||||
event:
|
||||
"up":
|
||||
- service: homeassistant.toggle
|
||||
entity_id: "switch.relay_inverter_1"
|
||||
|
||||
- obj: "p4b43" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.pv_power_3") }}W'
|
||||
- obj: "p4b45" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.tacsolar_power") }}W'
|
||||
- obj: "p4b47" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.power_compteur") }}W'
|
||||
- obj: "p4b49" # temperature label on all pages
|
||||
properties:
|
||||
"text": '{{ states("sensor.battery_state_of_charge_2") }}%'
|
||||
|
||||
# weather section
|
||||
- obj: "p5b14" # Icon
|
||||
properties:
|
||||
"src": "{{ 'L:/w-128-' + states('weather.openweathermap') + '.png' if not is_state('weather.openweathermap','unavailable') }}"
|
||||
|
||||
- obj: "p5b15" # Current date (adjust format to your needs)
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
{%- set day = (states.weather.openweathermap.last_changed).strftime('%w') %}
|
||||
{%- set days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] %}
|
||||
{{- days[ day | int -1 ] }} {{ (states.weather.openweathermap.last_changed).strftime('%m. %d. ') }}
|
||||
{% endif -%}
|
||||
|
||||
- obj: "p5b16" # Current temp (you can use your own outdoor temp sensor if you have one)
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.openweathermap','temperature') |string + '°C' if not is_state('weather.openweathermap','unavailable') }}" # or "{{ states('sensor.your_own_temp_sensor') if not is_state('sensor.your_own_temp_sensor','unavailable') else '--' }}°C"
|
||||
|
||||
- obj: "p5b17" # Current weather condition
|
||||
properties:
|
||||
"text": >
|
||||
{% if is_state('weather.openweathermap','clear-night') -%}
|
||||
Clear night
|
||||
{% elif is_state('weather.openweathermap','cloudy') -%}
|
||||
Cloudy
|
||||
{% elif is_state('weather.openweathermap','fog') -%}
|
||||
Fog
|
||||
{% elif is_state('weather.openweathermap','hail') -%}
|
||||
Hail
|
||||
{% elif is_state('weather.openweathermap','lightning') -%}
|
||||
Lightning
|
||||
{% elif is_state('weather.openweathermap','lightning-rainy') -%}
|
||||
Thunderstorms
|
||||
{% elif is_state('weather.openweathermap','partlycloudy') -%}
|
||||
Partly cloudy
|
||||
{% elif is_state('weather.openweathermap','pouring') -%}
|
||||
Pouring rain
|
||||
{% elif is_state('weather.openweathermap','rainy') -%}
|
||||
Rainy
|
||||
{% elif is_state('weather.openweathermap','snowy') -%}
|
||||
Snowy
|
||||
{% elif is_state('weather.openweathermap','snowy-rainy') -%}
|
||||
Snowy-rainy
|
||||
{% elif is_state('weather.openweathermap','sunny') -%}
|
||||
Sunny
|
||||
{% elif is_state('weather.openweathermap','windy') -%}
|
||||
Windy
|
||||
{% elif is_state('weather.openweathermap','windy-variant') -%}
|
||||
Windy
|
||||
{% elif is_state('weather.openweathermap','exceptional') -%}
|
||||
Exceptional
|
||||
{% elif is_state('weather.openweathermap','unavailable') -%}
|
||||
(not available)
|
||||
{% else -%}
|
||||
{{ states('weather.openweathermap') }}
|
||||
{% endif -%}
|
||||
|
||||
- obj: "p5b10" # tab dots - MAKE SURE YOU UPDATE THIS ONE!!
|
||||
event:
|
||||
"changed":
|
||||
- service: openhasp.command
|
||||
target:
|
||||
entity_id: openhasp.your_plate
|
||||
data:
|
||||
keyword: p5b19.text
|
||||
parameters: >
|
||||
{% if val == 0 %}
|
||||
{{ "#000000 \u2022# #909090 \u2022#" | e }}
|
||||
{%-elif val == 1 %}
|
||||
{{ "#909090 \u2022# #000000 \u2022#" | e }}
|
||||
{% endif %}
|
||||
|
||||
- obj: "p5b21" # Forecast time +1h
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
{%- set update = states('sensor.date') %}
|
||||
{%- set midnight = now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp() %}
|
||||
{%- set event = as_timestamp(strptime(state_attr('weather.openweathermap','forecast')[1]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set delta = ((event - midnight) // 86400) | int %}
|
||||
{%- if delta == 0 %}
|
||||
Today
|
||||
{%- elif delta == 1 %}
|
||||
Tomorrow
|
||||
{%- endif %}
|
||||
{{- event | timestamp_custom(" %-I %p") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b22" # Forecast temp +1h
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.openweathermap','forecast')[1]['temperature'] if not is_state('weather.openweathermap','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b23" # Forecast condition +1h
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.openweathermap','forecast')[1]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b31" # Forecast time +2h (using Dawn/Morn etc instead of Today/Tomorrow)
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
{%- set hour = as_timestamp(strptime(state_attr('weather.openweathermap','forecast')[3]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) | timestamp_custom("%-H") | int %}
|
||||
{%- if 4 <= hour < 6 %}
|
||||
Dawning
|
||||
{%- elif 6 <= hour < 9 %}
|
||||
Morning
|
||||
{%- elif 9 <= hour < 12 %}
|
||||
Forenoon
|
||||
{%- elif 12 <= hour < 18 %}
|
||||
Afternoon
|
||||
{%- elif 18 <= hour < 23 %}
|
||||
Evening
|
||||
{%- elif 23 <= hour or hour < 4 %}
|
||||
Night
|
||||
{%- endif %}
|
||||
{{- " " + hour |string + " o'clock" }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b32" # Forecast temp +2h
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.openweathermap','forecast')[3]['temperature'] if not is_state('weather.openweathermap','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b33" # Forecast condition +2h
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.openweathermap','forecast')[3]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b41" # Forecast time +4h
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
{%- set update = states('sensor.date') %}
|
||||
{%- set midnight = now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp() %}
|
||||
{%- set event = as_timestamp(strptime(state_attr('weather.openweathermap','forecast')[6]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set delta = ((event - midnight) // 86400) | int %}
|
||||
{%- if delta == 0 %}
|
||||
Today
|
||||
{%- elif delta == 1 %}
|
||||
Tomorrow
|
||||
{%- endif %}
|
||||
{{- event | timestamp_custom(" %-I %p") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b42" # Forecast temp +4h
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.openweathermap','forecast')[6]['temperature'] if not is_state('weather.openweathermap','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b43" # Forecast condition +4h
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.openweathermap','forecast')[6]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b51" # Forecast time +8h
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
{%- set update = states('sensor.date') %}
|
||||
{%- set midnight = now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp() %}
|
||||
{%- set event = as_timestamp(strptime(state_attr('weather.openweathermap','forecast')[12]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set delta = ((event - midnight) // 86400) | int %}
|
||||
{%- if delta == 0 %}
|
||||
Today
|
||||
{%- elif delta == 1 %}
|
||||
Tomorrow
|
||||
{%- endif %}
|
||||
{{- event | timestamp_custom(" %-I %p") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b52" # Forecast temp +8h
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.openweathermap','forecast')[12]['temperature'] if not is_state('weather.openweathermap','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b53" # Forecast condition +8h
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.openweathermap','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.openweathermap','forecast')[12]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b61" # Forecast date +1d
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
{%- set now = as_timestamp(strptime(state_attr('weather.bessamorel','forecast')[0]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set day = now | timestamp_custom("%w") %}
|
||||
{%- set days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] %}
|
||||
{{ days[ day | int -1 ] }}{{- now | timestamp_custom(" %d") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b62" # Forecast temp min +1d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[0]['templow'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b63" # Forecast temp max +1d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[0]['temperature'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b64" # Forecast condition +1d
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.bessamorel','forecast')[0]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b71" # Forecast date +2d
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
{%- set now = as_timestamp(strptime(state_attr('weather.bessamorel','forecast')[1]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set day = now | timestamp_custom("%w") %}
|
||||
{%- set days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] %}
|
||||
{{ days[ day | int -1 ] }}{{- now | timestamp_custom(" %d") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b72" # Forecast temp min +2d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[1]['templow'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b73" # Forecast temp max +2d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[1]['temperature'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b74" # Forecast condition +2d
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.bessamorel','forecast')[1]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b81" # Forecast date +3d
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
{%- set now = as_timestamp(strptime(state_attr('weather.bessamorel','forecast')[2]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set day = now | timestamp_custom("%w") %}
|
||||
{%- set days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] %}
|
||||
{{ days[ day | int -1 ] }}{{- now | timestamp_custom(" %d") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b82" # Forecast temp min +3d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[2]['templow'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b83" # Forecast temp max +3d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[2]['temperature'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b84" # Forecast condition +3d
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.bessamorel','forecast')[2]['condition'] }}.png
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b91" # Forecast date +4d
|
||||
properties:
|
||||
"text": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
{%- set now = as_timestamp(strptime(state_attr('weather.bessamorel','forecast')[3]['datetime'], '%Y-%m-%dT%H:%M:%S%z', default='2020-01-00T00:00:00+00:00')) %}
|
||||
{%- set day = now | timestamp_custom("%w") %}
|
||||
{%- set days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] %}
|
||||
{{ days[ day | int -1 ] }}{{- now | timestamp_custom(" %d") }}
|
||||
{%- endif %}
|
||||
|
||||
- obj: "p5b92" # Forecast temp min +4d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[3]['templow'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b93" # Forecast temp max +4d
|
||||
properties:
|
||||
"text": "{{ state_attr('weather.bessamorel','forecast')[3]['temperature'] if not is_state('weather.bessamorel','unavailable') else '-' }}"
|
||||
|
||||
- obj: "p5b94" # Forecast condition +4d
|
||||
properties:
|
||||
"src": >
|
||||
{%- if not is_state('weather.bessamorel','unavailable') %}
|
||||
L:/w-32-{{ state_attr('weather.bessamorel','forecast')[3]['condition'] }}.png
|
||||
{%- endif %}
|
||||
42
config/01capteur/recorder/recorder.yaml.old
Normal file
42
config/01capteur/recorder/recorder.yaml.old
Normal file
@@ -0,0 +1,42 @@
|
||||
db_url: mysql://homeassistant:homeassistant@core-mariadb/homeassistant?charset=utf8mb4
|
||||
purge_keep_days: 30
|
||||
auto_purge: true
|
||||
include:
|
||||
domains:
|
||||
- climate
|
||||
- binary_sensor
|
||||
- input_boolean
|
||||
- input_datetime
|
||||
- input_number
|
||||
- input_select
|
||||
- sensor
|
||||
- switch
|
||||
- person
|
||||
- device_tracker
|
||||
- light
|
||||
exclude:
|
||||
domains:
|
||||
- camera
|
||||
- zone
|
||||
- automation
|
||||
- sun
|
||||
- weather
|
||||
- cover
|
||||
- group
|
||||
- script
|
||||
- pool_pump
|
||||
entity_globs:
|
||||
- sensor.clock*
|
||||
- sensor.date*
|
||||
- sensor.glances*
|
||||
- sensor.load_*m
|
||||
- sensor.time*
|
||||
- sensor.uptime*
|
||||
- device_tracker.nmap_tracker*
|
||||
entities:
|
||||
- camera.front_door
|
||||
- sensor.memory_free
|
||||
- sensor.memory_use
|
||||
- sensor.memory_use_percent
|
||||
- sensor.processor_use
|
||||
- weather.openweathermap
|
||||
5
config/01capteur/sensor/.vscode/settings.json
vendored
Normal file
5
config/01capteur/sensor/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.yaml": "home-assistant"
|
||||
}
|
||||
}
|
||||
43
config/01capteur/sensor/battery.yaml
Normal file
43
config/01capteur/sensor/battery.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
# ## pc portable lenovo battery
|
||||
# - platform: mqtt
|
||||
# unique_id: portable_lenovo_battery
|
||||
# name: portable_lenovo_battery
|
||||
# device_class: battery
|
||||
# unit_of_measurement: "%"
|
||||
# # payload_on: low
|
||||
# # payload_off: normal
|
||||
# qos: 1
|
||||
# #availability_topic: home/downstairs/living-room/front-windows/availability
|
||||
# #payload_available: online
|
||||
# #payload_not_available: offline
|
||||
# state_topic: computer/lenovo
|
||||
# value_template: "{{ value_json.percent }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# unique_id: portable_elitebook_corei5
|
||||
# name: portable_elitebook_corei5
|
||||
# device_class: battery
|
||||
# unit_of_measurement: "%"
|
||||
# # payload_on: low
|
||||
# # payload_off: normal
|
||||
# qos: 1
|
||||
# #availability_topic: home/downstairs/living-room/front-windows/availability
|
||||
# #payload_available: online
|
||||
# #payload_not_available: offline
|
||||
# state_topic: computer/corei5
|
||||
# value_template: "{{ value_json.percent }}"
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# unique_id: portable_elitebook_centrino
|
||||
# name: portable_elitebook_centrino
|
||||
# device_class: battery
|
||||
# unit_of_measurement: "%"
|
||||
# # payload_on: low
|
||||
# # payload_off: normal
|
||||
# qos: 1
|
||||
# #availability_topic: home/downstairs/living-room/front-windows/availability
|
||||
# #payload_available: online
|
||||
# #payload_not_available: offline
|
||||
# state_topic: computer/centrino
|
||||
# value_template: "{{ value_json.percent }}"
|
||||
27
config/01capteur/sensor/beacons.yaml
Normal file
27
config/01capteur/sensor/beacons.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
- platform: mqtt_room
|
||||
device_id: "iphone X"
|
||||
name: "iphone X espresence"
|
||||
state_topic: "espresense/devices/iphone_x"
|
||||
timeout: 10
|
||||
away_timeout: 60
|
||||
|
||||
- platform: mqtt_room
|
||||
device_id: "xiaomi"
|
||||
name: "xiaomi espresence"
|
||||
state_topic: "espresense/devices/xiaomi"
|
||||
timeout: 10
|
||||
away_timeout: 60
|
||||
|
||||
- platform: mqtt_room
|
||||
device_id: "ipad"
|
||||
name: "ipad espresence"
|
||||
state_topic: "espresense/devices/ipad"
|
||||
timeout: 10
|
||||
away_timeout: 60
|
||||
|
||||
- platform: mqtt_room
|
||||
device_id: "known:ed317301e564"
|
||||
name: "clef espresence"
|
||||
state_topic: "espresense/devices/known:ed317301e564"
|
||||
timeout: 10
|
||||
away_timeout: 60
|
||||
198
config/01capteur/sensor/chaudiere.yaml.old
Normal file
198
config/01capteur/sensor/chaudiere.yaml.old
Normal file
@@ -0,0 +1,198 @@
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## actual value - input register
|
||||
# register_type: input
|
||||
## FC=04 de 30001-30272 enlever 1 a register
|
||||
######################################################################
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
registers:
|
||||
- name: T° chaudiere
|
||||
hub: pimodbus
|
||||
register: 0
|
||||
register_type: input
|
||||
device_class: temperature
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.5
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
registers:
|
||||
- name: T° fumée
|
||||
hub: pimodbus
|
||||
register: 1
|
||||
register_type: input
|
||||
device_class: temperature
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: T° board
|
||||
hub: pimodbus
|
||||
register: 2
|
||||
register_type: input
|
||||
device_class: temperature
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.5
|
||||
offset: 0
|
||||
precision: 0
|
||||
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: T°exterieur nord
|
||||
device_class: temperature
|
||||
hub: pimodbus
|
||||
register: 4
|
||||
register_type: input
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.5
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: Ventilation
|
||||
hub: pimodbus
|
||||
register: 7
|
||||
register_type: input
|
||||
unit_of_measurement: U/min
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: Heure de chauffage
|
||||
hub: pimodbus
|
||||
register: 221
|
||||
register_type: input
|
||||
unit_of_measurement: h
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: Heure de service
|
||||
hub: pimodbus
|
||||
register: 98
|
||||
register_type: input
|
||||
unit_of_measurement: h
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
registers:
|
||||
- name: T° départ
|
||||
hub: pimodbus
|
||||
register: 21
|
||||
register_type: input
|
||||
device_class: temperature
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.5
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
registers:
|
||||
- name: Charge du tampon
|
||||
hub: pimodbus
|
||||
register: 225
|
||||
register_type: input
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
registers:
|
||||
- name: tampon haut
|
||||
hub: pimodbus
|
||||
register: 118
|
||||
register_type: input
|
||||
device_class: temperature
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.5
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 10
|
||||
registers:
|
||||
- name: tampon bas
|
||||
hub: pimodbus
|
||||
register: 120
|
||||
register_type: input
|
||||
device_class: temperature
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.5
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: Consigne T° fumée
|
||||
device_class: temperature
|
||||
hub: pimodbus
|
||||
register: 19
|
||||
register_type: input
|
||||
unit_of_measurement: °C
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
offset: 0
|
||||
precision: 0
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: Etat chaudiere
|
||||
hub: pimodbus
|
||||
register: 4001
|
||||
register_type: input
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 1
|
||||
- platform: modbus
|
||||
scan_interval: 60
|
||||
registers:
|
||||
- name: O2_residuel
|
||||
hub: pimodbus
|
||||
register: 3
|
||||
register_type: input
|
||||
slave: 2
|
||||
count: 1
|
||||
scale: 0.1
|
||||
offset: 0
|
||||
precision: 0
|
||||
######################################################################
|
||||
## chaudiere
|
||||
## parameter - holding registers
|
||||
# register_type: holding
|
||||
## FC=03 de 40001-41094 enlever 1 a register
|
||||
######################################################################
|
||||
101
config/01capteur/sensor/chaudiere_mqtt.yaml
Normal file
101
config/01capteur/sensor/chaudiere_mqtt.yaml
Normal file
@@ -0,0 +1,101 @@
|
||||
# ######################################################################
|
||||
# ## chaudiere
|
||||
# ## actual value - input register
|
||||
# # register_type: input
|
||||
# ## FC=04 de 30001-30272 enlever 1 a register
|
||||
# ######################################################################
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/t_chaud"
|
||||
# unit_of_measurement: "°C"
|
||||
# device_class: temperature
|
||||
# name: "T° chaudiere"
|
||||
# unique_id: temp_chaud_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/t_fumee"
|
||||
# name: "T° fumée"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: temp_fumee_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/t_board"
|
||||
# name: "T° board"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: temp_board_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/t_ext"
|
||||
# name: "T°exterieur nord"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: temp_ext_N_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/vit_venti"
|
||||
# name: "Ventilation"
|
||||
# unit_of_measurement: "U/min"
|
||||
# unique_id: venti_chaud_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/h_chauffage"
|
||||
# name: "Heure de chauffage"
|
||||
# unit_of_measurement: "h"
|
||||
# unique_id: heure_chauff_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/h_service"
|
||||
# name: "Heure de service"
|
||||
# unit_of_measurement: "h"
|
||||
# unique_id: heure_serv_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/t_dep_chauff"
|
||||
# name: "T° départ"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: temp_dep_chauff_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/charge_tampon"
|
||||
# name: "Charge du tampon"
|
||||
# unique_id: charge_tampon_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/tampon_haut"
|
||||
# name: "tampon haut"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: tampon_haut_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/tampon_bas"
|
||||
# name: "tampon bas"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: tampon_bas_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/cons_t_fumee"
|
||||
# name: "Consigne T° fumée"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# unique_id: temp_cons_fumee_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/etat_chaudiere"
|
||||
# name: "Etat chaudiere"
|
||||
# unique_id: etat_chaud_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "chaudiere/O2_res"
|
||||
# name: "O2_residuel"
|
||||
# unique_id: O2_resi_01
|
||||
# ######################################################################
|
||||
# ## chaudiere
|
||||
# ## parameter - holding registers
|
||||
# # register_type: holding
|
||||
# ## FC=03 de 40001-41094 enlever 1 a register
|
||||
# ######################################################################
|
||||
|
||||
4
config/01capteur/sensor/domoticz.yaml.test
Normal file
4
config/01capteur/sensor/domoticz.yaml.test
Normal file
@@ -0,0 +1,4 @@
|
||||
- platform: mqtt
|
||||
state_topic: 'home/sensor/1456/temp'
|
||||
name: 'chaudiere'
|
||||
unit_of_measurement: '°C'
|
||||
15
config/01capteur/sensor/energy.yaml.test
Normal file
15
config/01capteur/sensor/energy.yaml.test
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
- platform: integration
|
||||
source: sensor.puissance_compteur
|
||||
name: total_energy_elec
|
||||
unit_prefix: k
|
||||
unit: kWh
|
||||
unit_time: h
|
||||
round: 2
|
||||
- platform: integration
|
||||
source: sensor.solar_pv_power
|
||||
name: total_energy_solar
|
||||
unit_prefix: k
|
||||
unit: kWh
|
||||
unit_time: h
|
||||
round: 2
|
||||
0
config/01capteur/sensor/ipx800.yaml
Normal file
0
config/01capteur/sensor/ipx800.yaml
Normal file
0
config/01capteur/sensor/modbusTAC2100.yaml
Normal file
0
config/01capteur/sensor/modbusTAC2100.yaml
Normal file
162
config/01capteur/sensor/sensors.yaml
Normal file
162
config/01capteur/sensor/sensors.yaml
Normal file
@@ -0,0 +1,162 @@
|
||||
#- platform: uptime
|
||||
#- platform: moon
|
||||
#- platform: season
|
||||
- platform: time_date
|
||||
display_options:
|
||||
- "time"
|
||||
- "date"
|
||||
|
||||
# #----------------------------------------
|
||||
# #
|
||||
# # lux
|
||||
# #
|
||||
# #----------------------------------------
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/lux"
|
||||
# name: "Luminosité"
|
||||
# device_class: illuminance
|
||||
# unit_of_measurement: "lx"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: luminosite_salon_01
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "arduino/garage/intensite"
|
||||
# name: "Intensité t_divisionnaire"
|
||||
# unit_of_measurement: "A"
|
||||
# device_class: current
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: courant_t_div_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "arduino/garage/puissance"
|
||||
# name: "Puissance t_divisionnaire"
|
||||
# device_class: power
|
||||
# unit_of_measurement: "W"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: power_t_div_01
|
||||
|
||||
# #----------------------------------------
|
||||
# #
|
||||
# # chauffage reglage PID
|
||||
# #
|
||||
# #----------------------------------------
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/chauff/pid/payload"
|
||||
# name: "payload"
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/chauff/pid/pv"
|
||||
# name: "pv"
|
||||
# value_template: "{{ value | round(3) }}"
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/chauff/pid/setpoint"
|
||||
# name: "setpoint"
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/chauff/pid/proportional"
|
||||
# name: "P"
|
||||
# value_template: "{{ value | round(3) }}"
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/chauff/pid/integral"
|
||||
# name: "I"
|
||||
# value_template: "{{ value | round(3) }}"
|
||||
# - platform: mqtt
|
||||
# state_topic: "sensor/chauff/pid/derivative"
|
||||
# name: "D"
|
||||
# value_template: "{{ value | round(3) }}"
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# stat divers: lumiere , detection
|
||||
#
|
||||
#----------------------------------------
|
||||
# - platform: history_stats
|
||||
# name: Lampes couloir
|
||||
# entity_id: light.couloir
|
||||
# state: "on"
|
||||
# type: time
|
||||
# start: "{{ now().replace(hour=0, minute=0, second=0) }}"
|
||||
# end: "{{ now() }}"
|
||||
|
||||
# - platform: history_stats
|
||||
# name: Lampes escalier
|
||||
# entity_id: light.escalier
|
||||
# state: "on"
|
||||
# type: time
|
||||
# start: "{{ now().replace(hour=0, minute=0, second=0) }}"
|
||||
# end: "{{ now() }}"
|
||||
|
||||
# - platform: history_stats
|
||||
# name: Lampes cuisine
|
||||
# entity_id: light.plafond_cuisine
|
||||
# state: "on"
|
||||
# type: time
|
||||
# start: "{{ now().replace(hour=0, minute=0, second=0) }}"
|
||||
# end: "{{ now() }}"
|
||||
|
||||
# - platform: history_stats
|
||||
# name: Ouverture portes garages
|
||||
# entity_id: binary_sensor.porte_garage
|
||||
# state: "on"
|
||||
# type: count
|
||||
# start: "{{ now().replace(hour=0, minute=0, second=0) }}"
|
||||
# end: "{{ now() }}"
|
||||
|
||||
# - platform: history_stats
|
||||
# name: Ouverture portes escalier
|
||||
# entity_id: binary_sensor.porte_escalier
|
||||
# state: "on"
|
||||
# type: count
|
||||
# start: "{{ now().replace(hour=0, minute=0, second=0) }}"
|
||||
# end: "{{ now() }}"
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# calcul humidité bien-etre
|
||||
#sensor/tension/compteur
|
||||
#----------------------------------------
|
||||
- platform: mold_indicator
|
||||
indoor_temp_sensor: sensor.ecowitt_tempin
|
||||
indoor_humidity_sensor: sensor.ecowitt_humidityin
|
||||
outdoor_temp_sensor: sensor.ecowitt_temp
|
||||
calibration_factor: 2.0
|
||||
|
||||
#----------------------------------------
|
||||
#
|
||||
# adresse IP internet
|
||||
#
|
||||
#----------------------------------------
|
||||
|
||||
#- platform: dnsip
|
||||
# name: ip_WAN
|
||||
|
||||
#- platform: seventeentrack
|
||||
# username: gil.soulier@gmail.com
|
||||
# password: Miss*17track
|
||||
# show_archived: false
|
||||
# show_delivered: true
|
||||
- platform: sql
|
||||
db_url: mysql://homeassistant:homeassistant@core-mariadb/homeassistant?charset=utf8
|
||||
scan_interval: 60
|
||||
queries:
|
||||
- name: "MariaDB DataBase size"
|
||||
query: 'SELECT table_schema "database", Round(Sum(data_length + index_length) / 1024, 1) "value" FROM information_schema.tables WHERE table_schema="homeassistant" GROUP BY table_schema;'
|
||||
column: "value"
|
||||
unit_of_measurement: MB
|
||||
|
||||
- platform: sql
|
||||
db_url: mysql://homeassistant:homeassistant@core-mariadb/homeassistant?charset=utf8mb4
|
||||
scan_interval: 3600
|
||||
queries:
|
||||
- name: db_size
|
||||
query: 'SELECT table_schema "database", Round(Sum(data_length + index_length) / 1048576, 2) "value" FROM information_schema.tables WHERE #table_schema="homeassistant" GROUP BY table_schema;'
|
||||
column: "value"
|
||||
unit_of_measurement: MB
|
||||
device_class: data_size
|
||||
# - platform: mqtt
|
||||
# state_topic: "domotic/ISAadapter/Package id 0"
|
||||
# name: "Temp PC Domotic"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: tempe_pc_domotic
|
||||
|
||||
274
config/01capteur/sensor/solar mqtt.yaml
Normal file
274
config/01capteur/sensor/solar mqtt.yaml
Normal file
@@ -0,0 +1,274 @@
|
||||
# # modbus sensors for EPEver
|
||||
# - platform: mqtt
|
||||
# ## reg 3100
|
||||
# state_topic: "tracer/sensor/tracer_1_pv_array_voltage"
|
||||
# unique_id: "array_voltage"
|
||||
# name: "solar_PV_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(12) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3101
|
||||
# state_topic: "tracer/sensor/tracer_1_pv_array_current"
|
||||
# unique_id: "array_current"
|
||||
# name: "solar_PV_Current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3102 3103
|
||||
# state_topic: "tracer/sensor/tracer_1_pv_array_power"
|
||||
# unique_id: "array_power"
|
||||
# name: "solar_PV_Power"
|
||||
# icon: mdi:solar-power
|
||||
# device_class: power
|
||||
# unit_of_measurement: 'W'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3104
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_voltage"
|
||||
# unique_id: "battery_voltage"
|
||||
# name: "solar_Battery_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# - platform: mqtt
|
||||
# ##reg 3105
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_charging_current"
|
||||
# name: "Battery_charging_Current"
|
||||
# unique_id: "battery_charging_current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# #reg 3302
|
||||
# state_topic: "tracer/sensor/tracer_1_max_battery_voltage_today"
|
||||
# name: "solar_Battery_Max_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# #reg 3303
|
||||
# state_topic: "tracer/sensor/tracer_1_min_battery_voltage_today"
|
||||
# name: "solar_Battery_Min_Voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 331B-331C
|
||||
# state_topic: "tracer/sensor/tracer_1_net_battery_current"
|
||||
# name: "net_Battery_Current"
|
||||
# unique_id: "net_battery_current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "tracer/registers/Charging equipment output power/value"
|
||||
# unique_id: "battery_power"
|
||||
# name: "solar_Battery_Power"
|
||||
# device_class: power
|
||||
# unit_of_measurement: 'W'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# #reg 3110
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_temperature"
|
||||
# name: "solar_Battery_Temperature"
|
||||
# unique_id: "battery_temperature"
|
||||
# icon: mdi:thermometer
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '°C'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# #reg 311A
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_soc"
|
||||
# name: "solar_Battery_SOC"
|
||||
# unique_id: "battery_SOC"
|
||||
# unit_of_measurement: '%'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# #reg 3111
|
||||
# state_topic: "tracer/sensor/tracer_1_charger_temperature"
|
||||
# unique_id: "device_temperature"
|
||||
# name: "solar_device_Temperature"
|
||||
# device_class: temperature
|
||||
# state_class: measurement
|
||||
# unit_of_measurement: '°C'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3201
|
||||
# state_topic: "tracer/sensor/tracer_1_equipment_status"
|
||||
# name: "solar_PV_Status"
|
||||
# unique_id: "solar_PV_status"
|
||||
# # device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# value_template: "{{ value }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3200
|
||||
# state_topic: "tracer/sensor/tracer_1_battery_status"
|
||||
# name: "solar_battery_Status"
|
||||
# unique_id: "battery_status"
|
||||
# value_template: "{{ value }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 330C-330D
|
||||
# state_topic: "tracer/sensor/tracer_1_generated_energy_today"
|
||||
# name: "generated_Today_Energy"
|
||||
# unique_id: "generated_energy_today"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_total_generated_energy"
|
||||
# unique_id: "generated_energy_total"
|
||||
# name: "generated_total_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 330E-330F
|
||||
# state_topic: "tracer/sensor/tracer_1_generated_energy_this_month"
|
||||
# name: "generated_month_Energy"
|
||||
# unique_id: "generated_energy_month"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_generated_energy_this_year"
|
||||
# unique_id: "generated_energy_year"
|
||||
# name: "generated_year_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 310E-310F
|
||||
# state_topic: "tracer/sensor/tracer_1_load_power"
|
||||
# unique_id: "load power"
|
||||
# name: "DC_Load_Power"
|
||||
# device_class: power
|
||||
# unit_of_measurement: 'W'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 310C
|
||||
# state_topic: "tracer/sensor/tracer_1_load_voltage"
|
||||
# name: "DC_Load_Voltage"
|
||||
# unique_id: "load voltage"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: 'V'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 310D
|
||||
# state_topic: "tracer/sensor/tracer_1_load_current"
|
||||
# name: "DC_Load_Courant"
|
||||
# unique_id: "load current"
|
||||
# device_class: current
|
||||
# unit_of_measurement: 'A'
|
||||
# state_class: measurement
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 200C
|
||||
# state_topic: "tracer/sensor/tracer_1_day/night"
|
||||
# name: "solar_Day_Night"
|
||||
# #device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# value_template: "{{ value }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 330C-330D
|
||||
# state_topic: "tracer/sensor/tracer_1_consumed_energy_today"
|
||||
# name: "consumed_Today_Energy"
|
||||
# unique_id: "energy_today"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_total_consumed_energy"
|
||||
# unique_id: "consumed_energy_total"
|
||||
# name: "consumed_Total_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_consumed_energy_this_month"
|
||||
# unique_id: "consumed_energy_month"
|
||||
# name: "consumed_Month_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ##reg 330A-330B
|
||||
# state_topic: "tracer/sensor/tracer_1_consumed_energy_this_year"
|
||||
# unique_id: "consumed_energy_year"
|
||||
# name: "consumed_Year_Energy"
|
||||
# device_class: energy
|
||||
# state_class: total_increasing
|
||||
# unit_of_measurement: 'kWh'
|
||||
# value_template: "{{ value | round(2) }}"
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3201
|
||||
# state_topic: "tracer/sensor/tracer_1_charging_mode"
|
||||
# name: "charging mode"
|
||||
# unique_id: "charging mode"
|
||||
# # device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
|
||||
|
||||
# - platform: mqtt
|
||||
# ## reg 3201
|
||||
# state_topic: "arduinomegatest/servo/status"
|
||||
# name: "servo_pos"
|
||||
# unique_id: "servo_pos1"
|
||||
# # device_class: energy
|
||||
# #unit_of_measurement: 'kW'
|
||||
# # value_template: "{{ value }}"
|
||||
63
config/01capteur/sensor/solar-ecu-r.yaml
Normal file
63
config/01capteur/sensor/solar-ecu-r.yaml
Normal file
@@ -0,0 +1,63 @@
|
||||
# ecu-r apsystem
|
||||
#- platform: apsystems
|
||||
# authId: 2c9f95c781d7527d0181e27daf25252a
|
||||
# systemId: 2c9f95c781d7527d0181dedde94c1f7c
|
||||
# ecuId: 216200068509
|
||||
# sunset: off
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/current"
|
||||
# name: "courant ecuR"
|
||||
# device_class: current
|
||||
# unit_of_measurement: "A"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_courant
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/volt"
|
||||
# name: "tension ecuR"
|
||||
# device_class: voltage
|
||||
# unit_of_measurement: "V"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_tension
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/power"
|
||||
# name: "puissance ecuR"
|
||||
# device_class: power
|
||||
# unit_of_measurement: "W"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_puissance
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/frequency"
|
||||
# name: "frequence ecuR"
|
||||
# device_class: frequency
|
||||
# unit_of_measurement: "Hz"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_frequence
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/cos_phi"
|
||||
# name: "cos Phi ecuR"
|
||||
# device_class: power_factor
|
||||
# unit_of_measurement: "%"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_cos_phi
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/temperature"
|
||||
# name: "temperature ecuR"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_temperature
|
||||
# - platform: mqtt
|
||||
# state_topic: "stat/ecu_r/energy_today"
|
||||
# name: "energy_today ecuR"
|
||||
# device_class: energy
|
||||
# unit_of_measurement: "Wh"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: ecuR_energy_today
|
||||
# state_class: total_increasing
|
||||
|
||||
#- platform: integration
|
||||
# source: sensor.puissance_compteur
|
||||
# name: total_energy_elec
|
||||
# unit_time: h
|
||||
# round: 2
|
||||
278
config/01capteur/sensor/solar-ecu-r.yaml.bak
Normal file
278
config/01capteur/sensor/solar-ecu-r.yaml.bak
Normal file
@@ -0,0 +1,278 @@
|
||||
# modbus sensors for EPEver
|
||||
- platform: modbus
|
||||
scan_interval: 30
|
||||
registers:
|
||||
- name: EPEver_Battery_Voltage #0x00331A
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 01
|
||||
register: 13082
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: Epever_Battery Current #0x00331B & 1C
|
||||
hub: hub1
|
||||
unit_of_measurement: A
|
||||
slave: 1
|
||||
register: 13083
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- name: Epever_Battery Temperature #0x003110
|
||||
hub: hub1
|
||||
unit_of_measurement: °C
|
||||
slave: 1
|
||||
register: 12560
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: EPEver_Battery_SOC
|
||||
hub: hub1
|
||||
unit_of_measurement: '%'
|
||||
slave: 01
|
||||
register: 12570
|
||||
register_type: input
|
||||
- name: Epever_Battery Status #0x003200
|
||||
hub: hub1
|
||||
slave: 1
|
||||
register: 12800
|
||||
register_type: input
|
||||
scale: 1
|
||||
precision: 0
|
||||
#######################################################################
|
||||
#D15: 1-Wrong identification for rated voltage
|
||||
#D8: Battery inner resistance, abnormal 1, normal 0
|
||||
#D7-D4: 00H Normal, 01H Over, Temp.(Higher than the warning settings) 02H Low Temp.(Lower than the warning settings),
|
||||
#D3-D0: 00H Normal ,01H Over Voltage. , 02H Under Voltage, 03H Over discharge, 04H Fault
|
||||
#Status analysis
|
||||
#Array status:address 3201 bits D15-D10
|
||||
#Charging status:address 3201 bits D3-D2
|
||||
#Battery status: address 3200 bits D7-D0
|
||||
#Load status: address 3201 bits D9-D7,
|
||||
#Device status: address 3200 bit D15 address 3202 bits D13-D8,D6-D4 address 3201 bits D6 address 2000
|
||||
############################################################################################
|
||||
- name: Epever_Device Temperature #0x003111
|
||||
hub: hub1
|
||||
unit_of_measurement: °C
|
||||
slave: 1
|
||||
register: 12561
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
|
||||
- name: Solar Charging Equipment Status #0x003201
|
||||
hub: hub1
|
||||
slave: 1
|
||||
register: 12801
|
||||
register_type: input
|
||||
scale: 1
|
||||
precision: 0
|
||||
#######################################################################
|
||||
#D15-D14: Input voltage status. 00H normal, 01H No input power connected, 02H Higher input voltage , 03H Input voltage error.
|
||||
#D13: Charging MOSFET is short circuit.
|
||||
#D12: Charging or Anti-reverse MOSFET is open circuit.
|
||||
#D11: Anti-reverse MOSFET is short circuit.
|
||||
#D10: Input is over current.
|
||||
#D9: The load is over current.
|
||||
#D8: The load is short circuit.
|
||||
#D7: Load MOSFET is short circuit.
|
||||
#D6:Disequilibrium in three circuits.A17
|
||||
#D4: PV input is short circuit.
|
||||
#D3-D2: Charging status. 00H No charging,01H Float,02H Boost, 03H Equalization.
|
||||
#D1: 0 Normal, 1 Fault.
|
||||
#D0: 1 Running, 0 Standby.
|
||||
#Status analysis
|
||||
#Array status:address 3201 bits D15-D10
|
||||
#Charging status:address 3201 bits D3-D2
|
||||
#Battery status: address 3200 bits D7-D0
|
||||
#Load status: address 3201 bits D9-D7,
|
||||
#Device status: address 3200 bit D15 address 3202 bits D13-D8,D6-D4 address 3201 bits D6 address 2000
|
||||
############################################################################################
|
||||
- name: Solar Consumed Energy Today #0x003304 and 0x003305
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13060
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
- name: EPEver_Load_Current # 310D
|
||||
hub: hub1
|
||||
unit_of_measurement: A
|
||||
slave: 01
|
||||
register: 12557
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: EPEver_Load_voltage #310C
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 12556
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
- name: EPEver_Load_Power #0x00310E and 0x00310F
|
||||
hub: hub1
|
||||
unit_of_measurement: W
|
||||
slave: 1
|
||||
register: 12558
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: EPEver_Load_Status #0x003202
|
||||
hub: hub1
|
||||
slave: 1
|
||||
register: 12802
|
||||
register_type: input
|
||||
scale: 1
|
||||
precision: 0
|
||||
|
||||
|
||||
- name: EPEver_Solar_voltage #3100
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 12544
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
- name: EPEver_Solar_Current # 3101
|
||||
hub: hub1
|
||||
unit_of_measurement: A
|
||||
slave: 01
|
||||
register: 12545
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: EPEver_Solar_Power #0x003102 and 0x003103
|
||||
hub: hub1
|
||||
unit_of_measurement: W
|
||||
slave: 1
|
||||
register: 12546
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
# modbus sensors for EPEver
|
||||
- platform: modbus
|
||||
scan_interval: 600
|
||||
registers:
|
||||
|
||||
- name: Epever_Maximum Battery Voltage Today #0x003302
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 13058
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: Epever_Minimum Battery Voltage Today #0x003303
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 13059
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
|
||||
- name: Epever Consumed Energy Today #0x003304 and 0x003305
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13060
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
- name: Epever Consumed Energy This Month #0x003306 and 07
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13062
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: Epever Consumed Energy This Year #0x003308 & 09
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13064
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
- name: Solar Total Consumed Energy #0x00330A & 0B
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13066
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
- name: Solar Generated Energy This Month #0x00330E & 0F
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13070
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: Solar Generated Energy This Year #0x003310 & 11
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13072
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: Solar Total Generated Energy #0x003312 & 13
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13074
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
- name: Solar Consumed Energy Today #0x003304 and 0x003305
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13060
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
|
||||
278
config/01capteur/sensor/solar.yaml.old
Normal file
278
config/01capteur/sensor/solar.yaml.old
Normal file
@@ -0,0 +1,278 @@
|
||||
# modbus sensors for EPEver
|
||||
- platform: modbus
|
||||
scan_interval: 30
|
||||
registers:
|
||||
- name: EPEver_Battery_Voltage #0x00331A
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 01
|
||||
register: 13082
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: Epever_Battery Current #0x00331B & 1C
|
||||
hub: hub1
|
||||
unit_of_measurement: A
|
||||
slave: 1
|
||||
register: 13083
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- name: Epever_Battery Temperature #0x003110
|
||||
hub: hub1
|
||||
unit_of_measurement: °C
|
||||
slave: 1
|
||||
register: 12560
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: EPEver_Battery_SOC
|
||||
hub: hub1
|
||||
unit_of_measurement: '%'
|
||||
slave: 01
|
||||
register: 12570
|
||||
register_type: input
|
||||
- name: Epever_Battery Status #0x003200
|
||||
hub: hub1
|
||||
slave: 1
|
||||
register: 12800
|
||||
register_type: input
|
||||
scale: 1
|
||||
precision: 0
|
||||
#######################################################################
|
||||
#D15: 1-Wrong identification for rated voltage
|
||||
#D8: Battery inner resistance, abnormal 1, normal 0
|
||||
#D7-D4: 00H Normal, 01H Over, Temp.(Higher than the warning settings) 02H Low Temp.(Lower than the warning settings),
|
||||
#D3-D0: 00H Normal ,01H Over Voltage. , 02H Under Voltage, 03H Over discharge, 04H Fault
|
||||
#Status analysis
|
||||
#Array status:address 3201 bits D15-D10
|
||||
#Charging status:address 3201 bits D3-D2
|
||||
#Battery status: address 3200 bits D7-D0
|
||||
#Load status: address 3201 bits D9-D7,
|
||||
#Device status: address 3200 bit D15 address 3202 bits D13-D8,D6-D4 address 3201 bits D6 address 2000
|
||||
############################################################################################
|
||||
- name: Epever_Device Temperature #0x003111
|
||||
hub: hub1
|
||||
unit_of_measurement: °C
|
||||
slave: 1
|
||||
register: 12561
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
|
||||
- name: Solar Charging Equipment Status #0x003201
|
||||
hub: hub1
|
||||
slave: 1
|
||||
register: 12801
|
||||
register_type: input
|
||||
scale: 1
|
||||
precision: 0
|
||||
#######################################################################
|
||||
#D15-D14: Input voltage status. 00H normal, 01H No input power connected, 02H Higher input voltage , 03H Input voltage error.
|
||||
#D13: Charging MOSFET is short circuit.
|
||||
#D12: Charging or Anti-reverse MOSFET is open circuit.
|
||||
#D11: Anti-reverse MOSFET is short circuit.
|
||||
#D10: Input is over current.
|
||||
#D9: The load is over current.
|
||||
#D8: The load is short circuit.
|
||||
#D7: Load MOSFET is short circuit.
|
||||
#D6:Disequilibrium in three circuits.A17
|
||||
#D4: PV input is short circuit.
|
||||
#D3-D2: Charging status. 00H No charging,01H Float,02H Boost, 03H Equalization.
|
||||
#D1: 0 Normal, 1 Fault.
|
||||
#D0: 1 Running, 0 Standby.
|
||||
#Status analysis
|
||||
#Array status:address 3201 bits D15-D10
|
||||
#Charging status:address 3201 bits D3-D2
|
||||
#Battery status: address 3200 bits D7-D0
|
||||
#Load status: address 3201 bits D9-D7,
|
||||
#Device status: address 3200 bit D15 address 3202 bits D13-D8,D6-D4 address 3201 bits D6 address 2000
|
||||
############################################################################################
|
||||
- name: Solar Consumed Energy Today #0x003304 and 0x003305
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13060
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
- name: EPEver_Load_Current # 310D
|
||||
hub: hub1
|
||||
unit_of_measurement: A
|
||||
slave: 01
|
||||
register: 12557
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: EPEver_Load_voltage #310C
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 12556
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
- name: EPEver_Load_Power #0x00310E and 0x00310F
|
||||
hub: hub1
|
||||
unit_of_measurement: W
|
||||
slave: 1
|
||||
register: 12558
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: EPEver_Load_Status #0x003202
|
||||
hub: hub1
|
||||
slave: 1
|
||||
register: 12802
|
||||
register_type: input
|
||||
scale: 1
|
||||
precision: 0
|
||||
|
||||
|
||||
- name: EPEver_Solar_voltage #3100
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 12544
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
- name: EPEver_Solar_Current # 3101
|
||||
hub: hub1
|
||||
unit_of_measurement: A
|
||||
slave: 01
|
||||
register: 12545
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: EPEver_Solar_Power #0x003102 and 0x003103
|
||||
hub: hub1
|
||||
unit_of_measurement: W
|
||||
slave: 1
|
||||
register: 12546
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
# modbus sensors for EPEver
|
||||
- platform: modbus
|
||||
scan_interval: 600
|
||||
registers:
|
||||
|
||||
- name: Epever_Maximum Battery Voltage Today #0x003302
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 13058
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
- name: Epever_Minimum Battery Voltage Today #0x003303
|
||||
hub: hub1
|
||||
unit_of_measurement: V
|
||||
slave: 1
|
||||
register: 13059
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
|
||||
- name: Epever Consumed Energy Today #0x003304 and 0x003305
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13060
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
- name: Epever Consumed Energy This Month #0x003306 and 07
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13062
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: Epever Consumed Energy This Year #0x003308 & 09
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13064
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
- name: Solar Total Consumed Energy #0x00330A & 0B
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13066
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
- name: Solar Generated Energy This Month #0x00330E & 0F
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13070
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: Solar Generated Energy This Year #0x003310 & 11
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13072
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
- name: Solar Total Generated Energy #0x003312 & 13
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13074
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
- name: Solar Consumed Energy Today #0x003304 and 0x003305
|
||||
hub: hub1
|
||||
unit_of_measurement: KWh
|
||||
slave: 1
|
||||
register: 13060
|
||||
register_type: input
|
||||
scale: 0.01
|
||||
precision: 2
|
||||
count: 2
|
||||
reverse_order: true
|
||||
|
||||
|
||||
|
||||
36
config/01capteur/sensor/stat.yaml
Normal file
36
config/01capteur/sensor/stat.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
- platform: average
|
||||
name: "moy-current-cpt"
|
||||
duration:
|
||||
hours: 1
|
||||
entities:
|
||||
- sensor.tac2100_compteur_courant
|
||||
- platform: average
|
||||
name: "moy-couranta-cpt2"
|
||||
duration:
|
||||
hours: 1
|
||||
entities:
|
||||
- sensor.pj1203_zb_compteur_current_a
|
||||
- platform: average
|
||||
name: "moy-courantb-cpt2"
|
||||
duration:
|
||||
hours: 1
|
||||
entities:
|
||||
- sensor.pj1203_zb_compteur_current_b
|
||||
- platform: average
|
||||
name: "moy-power-cpt"
|
||||
duration:
|
||||
hours: 1
|
||||
entities:
|
||||
- sensor.tac2100_compteur_puissance_active
|
||||
- platform: average
|
||||
name: "moy-powera-cpt2"
|
||||
duration:
|
||||
hours: 1
|
||||
entities:
|
||||
- sensor.pj1203_zb_compteur_power_a
|
||||
- platform: average
|
||||
name: "moy-powerb-cpt2"
|
||||
duration:
|
||||
hours: 1
|
||||
entities:
|
||||
- sensor.pj1203_zb_compteur_power_b
|
||||
10
config/01capteur/sensor/systemmonitor.yaml
Normal file
10
config/01capteur/sensor/systemmonitor.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
- platform: systemmonitor
|
||||
resources:
|
||||
- type: processor_use
|
||||
# - type: processor_temperature
|
||||
- type: memory_free
|
||||
- type: disk_use_percent
|
||||
- type: disk_use
|
||||
- type: disk_free
|
||||
- type: load_5m
|
||||
|
||||
78
config/01capteur/sensor/temperature.yaml
Normal file
78
config/01capteur/sensor/temperature.yaml
Normal file
@@ -0,0 +1,78 @@
|
||||
# ---
|
||||
# #----------------------------------------
|
||||
# #
|
||||
# # temperature
|
||||
# #
|
||||
# #----------------------------------------
|
||||
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/bureau"
|
||||
# name: "T Bureau"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_bureau_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/cave"
|
||||
# name: "T Cave"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_cave_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/garage"
|
||||
# name: "T Garage"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_garage_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/chambre1"
|
||||
# name: "T Chambre1"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_chambre_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/chambre2"
|
||||
# name: "T Chambre2"
|
||||
# unit_of_measurement: "°C"
|
||||
# device_class: temperature
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_chambre_02
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/comble"
|
||||
# name: "T Comble"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_comble_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "hum/sdb"
|
||||
# name: "H% salle de bain"
|
||||
# device_class: humidity
|
||||
# unit_of_measurement: "%"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: hum_sdb_01
|
||||
# - platform: mqtt
|
||||
# state_topic: "temp/sdb"
|
||||
# name: "T salle de bain"
|
||||
# device_class: temperature
|
||||
# unit_of_measurement: "°C"
|
||||
# value_template: "{{ value | round(1) }}"
|
||||
# unique_id: temp_sdb_01
|
||||
#----------------------------------------
|
||||
#
|
||||
# temperature
|
||||
#
|
||||
#----------------------------------------
|
||||
# - platform: min_max
|
||||
# entity_ids:
|
||||
# - sensor.temp
|
||||
# name: "min_exterieur"
|
||||
# type: min
|
||||
# - platform: min_max
|
||||
# entity_ids:
|
||||
# - sensor.temp
|
||||
# name: "max_exterieur"
|
||||
# type: max
|
||||
0
config/01capteur/sensor/template_sensor.yaml
Normal file
0
config/01capteur/sensor/template_sensor.yaml
Normal file
12
config/01capteur/sensor/unraid.yaml.old
Normal file
12
config/01capteur/sensor/unraid.yaml.old
Normal file
@@ -0,0 +1,12 @@
|
||||
- platform: template
|
||||
sensors:
|
||||
unraid_array_status:
|
||||
friendly_name: UnRAID Array Status
|
||||
value_template: >
|
||||
{{state_attr("binary_sensor.tower_server", "arrayStatus")}}
|
||||
unraid_array_space:
|
||||
friendly_name: UnRAID Array Space
|
||||
value_template: >
|
||||
{% set state = state_attr("switch.tower_server", "diskSpace") %}
|
||||
{{ Offline if state == None else state | regex_findall_index(".*\((\d+.?\d+) %\)") | float }}
|
||||
unit_of_measurement: '%'
|
||||
13
config/01capteur/shell_commands.yaml
Normal file
13
config/01capteur/shell_commands.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
turn_off_m83lenovo_pc: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' root@10.0.0.178 sudo shutdown -h now"
|
||||
turn_off_pc_aorus: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' gilles@10.0.0.128 sudo shutdown -h now"
|
||||
turn_off_unraid_pc: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' root@10.0.0.240 sudo shutdown -h now"
|
||||
turn_off_lenovom91_bureau_pc: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' gilles@10.0.0.113 sudo shutdown -h now"
|
||||
turn_off_hp3300_pc: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' root@10.0.1.208 sudo shutdown -h now"
|
||||
turn_off_atermitter_pc: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' root@10.0.1.73 sudo shutdown -h now"
|
||||
|
||||
|
||||
turn_off_hp_debnas_pc: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' gilles@10.0.0.16 sudo shutdown -h now"
|
||||
|
||||
screen_off_pc_yoga: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' gilles@10.0.0.24 busctl --user set-property org.gnome.Mutter.DisplayConfig /org/gnome/Mutter/DisplayConfig org.gnome.Mutter.DisplayConfig PowerSaveMode i 1"
|
||||
screen_on_pc_yoga: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' gilles@10.0.0.24 busctl --user set-property org.gnome.Mutter.DisplayConfig /org/gnome/Mutter/DisplayConfig org.gnome.Mutter.DisplayConfig PowerSaveMode i 0"
|
||||
turn_off_pc_yoga: "ssh -i /config/ssh_keys/id_rsa_homeassistant -o 'StrictHostKeyChecking=no' gilles@10.0.0.24 sudo shutdown -h now"
|
||||
17
config/01capteur/solar/solar_optimizer.yaml
Normal file
17
config/01capteur/solar/solar_optimizer.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
# http://10.0.0.2:8123/hacs/repository/643579135
|
||||
|
||||
algorithm:
|
||||
initial_temp: 1000
|
||||
min_temp: 0.1
|
||||
cooling_factor: 0.95
|
||||
max_iteration_number: 1000
|
||||
devices:
|
||||
- name: "prise_ecran"
|
||||
entity_id: "switch.prise_ecran"
|
||||
power_max: 400
|
||||
check_usable_template: "{{%if states('sensor.energy_pj1203_energy_flow_b') == 'producing' %}}"
|
||||
duration_min: 6
|
||||
duration_stop_min: 3
|
||||
action_mode: "service_call"
|
||||
service_activation: switch/turn_on"
|
||||
deactivation_service: "switch/turn_off"
|
||||
50
config/01capteur/switch/ipx800.yaml.old
Normal file
50
config/01capteur/switch/ipx800.yaml.old
Normal file
@@ -0,0 +1,50 @@
|
||||
- platform: command_line
|
||||
switches:
|
||||
ipx800_out1:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led1=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led1=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led0>(.*)</led0>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 1'
|
||||
ipx800_out2:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led2=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led2=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led1>(.*)</led1>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 2'
|
||||
ipx800_3:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led3=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led3=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led2>(.*)</led2>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 3'
|
||||
ipx800_out4:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led4=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led4=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led3>(.*)</led3>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 4'
|
||||
ipx800_out5:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led5=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led5=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led4>(.*)</led4>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 5'
|
||||
ipx800_out6:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led6=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led6=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led5>(.*)</led5>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 6'
|
||||
ipx800_out7:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led7=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led7=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led6>(.*)</led6>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 7'
|
||||
ipx800_out8:
|
||||
command_on: 'curl http://10.0.0.9/preset.htm?led8=1 >/dev/null'
|
||||
command_off: 'curl http://10.0.0.9/preset.htm?led8=0 >/dev/null'
|
||||
command_state: 'curl http://10.0.0.9/status.xml'
|
||||
value_template: '{% set status = value | regex_findall_index("<led7>(.*)</led7>") %} {% if status == "1" %} true {%- endif -%}'
|
||||
friendly_name: 'IPX800 Out 8'
|
||||
9
config/01capteur/switch/moonraker.yaml.old2
Normal file
9
config/01capteur/switch/moonraker.yaml.old2
Normal file
@@ -0,0 +1,9 @@
|
||||
- platform: rest
|
||||
name: u20_V0_power
|
||||
resource: "http://10.0.0.194:7125/machine/device_power/device?device=Printer"
|
||||
body_on: '{"action": "on"}'
|
||||
body_off: '{"action": "off"}'
|
||||
headers:
|
||||
Content-Type: 'application/json'
|
||||
is_on_template: >-
|
||||
{{ 'result' in value_json and (value_json.result.values() | list | first == "on") }}
|
||||
85
config/01capteur/switch/remote.yaml.old
Normal file
85
config/01capteur/switch/remote.yaml.old
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
- platform: broadlink
|
||||
#host: 10.0.0.106
|
||||
mac: 78:0F:77:FD:46:6C
|
||||
timeout: 60
|
||||
#type: rm2_pro_plus
|
||||
switches:
|
||||
# TV
|
||||
tv_onoff:
|
||||
friendly_name: "TV"
|
||||
command_on: 'JgBYAAABIJISExETETcSEhISEhQQFBETETcROBESEjcRNhM1EjcTNRMTERISNxEUERMSExE2EjYSNhM2EhIROBE3ETcREhITEgAFGwABH0oSAAwzAAEfShEADQU='
|
||||
command_off: 'JgBYAAABHpISEhMSETYTEhATEhQREhMSEDgRNxISEjcRNxE1EjcSNhM1EhISNhEUERETEhI1EjcSEhE4ExARNxI3ETYTERMSEQAFGAABIEgTAAwpAAEfSRIADQU='
|
||||
tv_tv:
|
||||
friendly_name: "Mode_Télé"
|
||||
command_on: 'JgBYAAABKJQSExEUEjcTEhITExISExITEjcSOBEUETgSOBE5ETgTNxEUEhMSEhMSEjgROBI4ETkSNxM3ETkTNhITERQSExETEgAFJwABJ0sSAAxXAAEmSxMADQU='
|
||||
command_off: 'JgBYAAABKJQSExEUEjcTEhITExISExITEjcSOBEUETgSOBE5ETgTNxEUEhMSEhMSEjgROBI4ETkSNxM3ETkTNhITERQSExETEgAFJwABJ0sSAAxXAAEmSxMADQU='
|
||||
tv_source:
|
||||
friendly_name: "Source"
|
||||
command_on: 'JgBYAAABJ5UTERITEjgRFRATExITEhMSETgTNxEUEjcTNxM3ETgSOBI4EjcTEhM3ERQSEhITEhMSExEUEjcUERI4ETgTNxE4EwAFJgABJ0sSAAxWAAEnSxIADQU='
|
||||
command_off: 'JgBYAAABJ5UTERITEjgRFRATExITEhMSETgTNxEUEjcTNxM3ETgSOBI4EjcTEhM3ERQSEhITEhMSExEUEjcUERI4ETgTNxE4EwAFJgABJ0sSAAxWAAEnSxIADQU='
|
||||
tv_vol_up:
|
||||
friendly_name: "Vol+"
|
||||
command_on: 'JgBYAAABKZMRFBEVETcSExEVEBUQFBMSETgSOBITEjcRORE4EjkRNhMUETgRFBITERQQFBIUEBQRORITETgSOBE4EjgRORI3EwAFJgABJ0sRAAxXAAEnSxEADQU='
|
||||
command_off: 'JgBYAAABKZMRFBEVETcSExEVEBUQFBMSETgSOBITEjcRORE4EjkRNhMUETgRFBITERQQFBIUEBQRORITETgSOBE4EjgRORI3EwAFJgABJ0sRAAxXAAEnSxEADQU='
|
||||
tv_vol_down:
|
||||
friendly_name: "Vol-"
|
||||
command_on: 'JgBYAAABKJQTEhISEjgRFBEUEhITEhIUEDkSNxMSEjgSNxM3EjgSNxI4ETkRFBMREhMRFRETERQRExITEzcSNxM3EjgSNxM3EgAFJwABJkwRAAxXAAEoShMADQU='
|
||||
command_off: 'JgBYAAABKJQTEhISEjgRFBEUEhITEhIUEDkSNxMSEjgSNxM3EjgSNxI4ETkRFBMREhMRFRETERQRExITEzcSNxM3EjgSNxM3EgAFJwABJkwRAAxXAAEoShMADQU='
|
||||
tv_prog_up:
|
||||
friendly_name: "Prog+"
|
||||
command_on: 'JgBYAAABJ5QTEhITETkSExETEhMSExMSEjcTNxEUEjcUNhI4EjcSOBITERQSEhITExISExEUERQROBI4EjcSOBE5ETgTNxE5EgAFJgABJ0sRAAxYAAEmTBEADQU='
|
||||
command_off: 'JgBYAAABJ5QTEhITETkSExETEhMSExMSEjcTNxEUEjcUNhI4EjcSOBITERQSEhITExISExEUERQROBI4EjcSOBE5ETgTNxE5EgAFJgABJ0sRAAxYAAEmTBEADQU='
|
||||
tv_prog_down:
|
||||
friendly_name: "Prog-"
|
||||
command_on: 'JgBQAAABJ5QTEhMSETkRExITEhMTEhEUETgTNxITETgTNxI4EjcTNxI4ERMTEhMTERMRFBITERMTEhI4ETgTNxI4EjcTNxI4EQAFJwABJ0sSAA0FAAAAAAAAAAA='
|
||||
command_off: 'JgBQAAABJ5QTEhMSETkRExITEhMTEhEUETgTNxITETgTNxI4EjcTNxI4ERMTEhMTERMRFBITERMTEhI4ETgTNxI4EjcTNxI4EQAFJwABJ0sSAA0FAAAAAAAAAAA='
|
||||
tv_mute:
|
||||
friendly_name: "Mute"
|
||||
command_on: 'JgBYAAABKJQSExEUETgSExITEhMRFBITEDkSNxIUETgROBM3EjgROBI4EhMRFBA5EhMRFBEUERQRExM3ETkSExI3ETkSNxI4EgAFJgABJ0sTAAxWAAEoShIADQU='
|
||||
command_off: 'JgBYAAABKJQSExEUETgSExITEhMRFBITEDkSNxIUETgROBM3EjgROBI4EhMRFBA5EhMRFBEUERQRExM3ETkSExI3ETkSNxI4EgAFJgABJ0sTAAxWAAEoShIADQU='
|
||||
tv_1:
|
||||
friendly_name: "1"
|
||||
command_on: 'JgBgAAABJ5URExMTETgRFBEUERQRExIUEDkSNxYPEjgROBI4ETkROBM3EhQRExETETgTExEUERQRFBE4EjcTOBETEjgSNxM3EQAFJwABKEoSAAxXAAEnSxIADFYAASdKEwANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5URExMTETgRFBEUERQRExIUEDkSNxYPEjgROBI4ETkROBM3EhQRExETETgTExEUERQRFBE4EjcTOBETEjgSNxM3EQAFJwABKEoSAAxXAAEnSxIADFYAASdKEwANBQAAAAAAAAAA'
|
||||
tv_2:
|
||||
friendly_name: "2"
|
||||
command_on: 'JgBQAAABJ5USExETETkRFBEUERQQFRAVEDkROBEVEDkROBE5ETgSOBIUEDkRExIUEDkSExETEhQQOREUEjcSOBEUEjcRORI4EQAFKAABJUwRAA0FAAAAAAAAAAA='
|
||||
command_off: 'JgBQAAABJ5USExETETkRFBEUERQQFRAVEDkROBEVEDkROBE5ETgSOBIUEDkRExIUEDkSExETEhQQOREUEjcSOBEUEjcRORI4EQAFKAABJUwRAA0FAAAAAAAAAAA='
|
||||
tv_3:
|
||||
friendly_name: "3"
|
||||
command_on: 'JgBgAAABJ5QSExEVEjYSFBETEhMSExEUETgSOBITEjcSOBI3EzcRORI3EjgRFRAVETcSFBETERUQExMSEzcRORETEjgRORI3EgAFJgABKEoSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5QSExEVEjYSFBETEhMSExEUETgSOBITEjcSOBI3EzcRORI3EjgRFRAVETcSFBETERUQExMSEzcRORETEjgRORI3EgAFJgABKEoSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
tv_4:
|
||||
friendly_name: "4"
|
||||
command_on: 'JgBYAAABJ5QUEhETETkRFBAUExMQFQ8WETcSOBEUETgTNxI4ETgSOBEVEBQROBEUETkSExETExIRORE4ExMROBEUETgTNxE4EgAFJgABKEoTAAxWAAEnTBEADQU='
|
||||
command_off: 'JgBYAAABJ5QUEhETETkRFBAUExMQFQ8WETcSOBEUETgTNxI4ETgSOBEVEBQROBEUETkSExETExIRORE4ExMROBEUETgTNxE4EgAFJgABKEoTAAxWAAEnTBEADQU='
|
||||
tv_5:
|
||||
friendly_name: "5"
|
||||
command_on: 'JgBQAAABKJQRFRAVDzkSFBEUERQQFBEUETkQOREUEjcRORA5EjgRORI4ERMROREUETkQFRAVEBMSFBE4EhQQOREUETgSNxI4EwAFKAABJksRAA0FAAAAAAAAAAA='
|
||||
command_off: 'JgBQAAABKJQRFRAVDzkSFBEUERQQFBEUETkQOREUEjcRORA5EjgRORI4ERMROREUETkQFRAVEBMSFBE4EhQQOREUETgSNxI4EwAFKAABJksRAA0FAAAAAAAAAAA='
|
||||
tv_6:
|
||||
friendly_name: "6"
|
||||
command_on: 'JgBgAAABJpUTEhITETkSEhMTEhIRFBITEjcTNxEVEDgSOBI4ETgSOBEUEjcSOBEUETgSExEUERUQOBITEhMSOBEUETgRORE4EgAFJgABKEoSAAxWAAEnSxIADFYAASdLEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJpUTEhITETkSEhMTEhIRFBITEjcTNxEVEDgSOBI4ETgSOBEUEjcSOBEUETgSExEUERUQOBITEhMSOBEUETgRORE4EgAFJgABKEoSAAxWAAEnSxIADFYAASdLEQANBQAAAAAAAAAA'
|
||||
tv_7:
|
||||
friendly_name: "7"
|
||||
command_on: 'JgBgAAABJ5USEhITEjkQFBEUEhITEhIUEDkROBIUEDgSORE4ETgTNxE5ETgSOBIUEDgSExITERUQFBETEhQROBIUEDgSOBE5EQAFJwABJ0sSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5USEhITEjkQFBEUEhITEhIUEDkROBIUEDgSORE4ETgTNxE5ETgSOBIUEDgSExITERUQFBETEhQROBIUEDgSOBE5EQAFJwABJ0sSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
tv_8:
|
||||
friendly_name: "8"
|
||||
command_on: 'JgBgAAABKJQRFBEUETgSExIUEBQRFBETEjgSOBITETgSOBE4EjgSOBITERMTExE4ETgSFBETERQRORM2EjkTERMSEjcRORI3EwAFJgABJ0sSAAxXAAEoShEADFgAASZMEgANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABKJQRFBEUETgSExIUEBQRFBETEjgSOBITETgSOBE4EjgSOBITERMTExE4ETgSFBETERQRORM2EjkTERMSEjcRORI3EwAFJgABJ0sSAAxXAAEoShEADFgAASZMEgANBQAAAAAAAAAA'
|
||||
tv_9:
|
||||
friendly_name: "9"
|
||||
command_on: 'JgBgAAABJ5URFBEUETgSExITERUQFBETEjgRORMREjgRORI3EjgROBI4ERQRFRE3EzcTExAUEhISFBE4ETkRFBITETgSNxM3EgAFJwABKEkTAAxWAAEmTBIADFYAASdLEgANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5URFBEUETgSExITERUQFBETEjgRORMREjgRORI3EjgROBI4ERQRFRE3EzcTExAUEhISFBE4ETkRFBITETgSNxM3EgAFJwABKEkTAAxWAAEmTBIADFYAASdLEgANBQAAAAAAAAAA'
|
||||
tv_0:
|
||||
friendly_name: "0"
|
||||
command_on: 'JgBgAAABJ5USExITETgSFBETERQRFBETEjkQOBMSEjgSNxI4EjgSNxMSEhMRFBEUEjcTEhEVERMROBI4ETgSOBEUETgTNxI4EQAFJwABJkwRAAxXAAEnSxEADFcAAShKEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5USExITETgSFBETERQRFBETEjkQOBMSEjgSNxI4EjgSNxMSEhMRFBEUEjcTEhEVERMROBI4ETgSOBEUETgTNxI4EQAFJwABJkwRAAxXAAEnSxEADFcAAShKEQANBQAAAAAAAAAA'
|
||||
# VideoProjecteur
|
||||
vp_onoff:
|
||||
friendly_name: "VideoProjecteur"
|
||||
command_on: 'JgBYAAABKJQVEBMTEhITNxMSExMREhMSEjgSOBITFBESOBITEhITEhI4FDYTNxMTERMSExITEDoUERMRExISOBQ2EzcTNxMSEgAF0gABKEoTAAxsAAEoShMADQU='
|
||||
command_off: 'JgDKAJCREjUUERI2EjYRExETEDcSEhETETcRExETETcRNxETETcQFBE2ETcSNhE2ExERNxI2EjYSEhETERMRExE3EhIRExE2ETcSNhETEhIRExETEhISEhISExESNhE2EjYSNhI2EK6QkRE2EhISNhI2EhISEhI2ERMRExI2ERMRExA3EjYRExI2EhIRNxE2EjYSNhISEjYRNhI2ERMSEhISEhIRNxETERMSNhE3EDcSEhETERMSEhISERMSEhETEzUSNhI1EjYSNhEADQUAAAAAAAAAAAAAAAAAAA=='
|
||||
91
config/01capteur/switch/remote.yaml.old2
Normal file
91
config/01capteur/switch/remote.yaml.old2
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
- platform: broadlink
|
||||
#host: 10.0.0.106
|
||||
mac: 78:0F:77:FD:46:6C
|
||||
#timeout: 60
|
||||
#type: rm2_pro_plus
|
||||
switches:
|
||||
# TV
|
||||
tv_onoff:
|
||||
friendly_name: "TV"
|
||||
command_on: 'JgBYAAABIJISExETETcSEhISEhQQFBETETcROBESEjcRNhM1EjcTNRMTERISNxEUERMSExE2EjYSNhM2EhIROBE3ETcREhITEgAFGwABH0oSAAwzAAEfShEADQU='
|
||||
command_off: 'JgBYAAABHpISEhMSETYTEhATEhQREhMSEDgRNxISEjcRNxE1EjcSNhM1EhISNhEUERETEhI1EjcSEhE4ExARNxI3ETYTERMSEQAFGAABIEgTAAwpAAEfSRIADQU='
|
||||
tv_tv:
|
||||
friendly_name: "Mode_Télé"
|
||||
command_on: 'JgBYAAABKJQSExEUEjcTEhITExISExITEjcSOBEUETgSOBE5ETgTNxEUEhMSEhMSEjgROBI4ETkSNxM3ETkTNhITERQSExETEgAFJwABJ0sSAAxXAAEmSxMADQU='
|
||||
command_off: 'JgBYAAABKJQSExEUEjcTEhITExISExITEjcSOBEUETgSOBE5ETgTNxEUEhMSEhMSEjgROBI4ETkSNxM3ETkTNhITERQSExETEgAFJwABJ0sSAAxXAAEmSxMADQU='
|
||||
tv_source:
|
||||
friendly_name: "Source"
|
||||
command_on: 'JgBYAAABJ5UTERITEjgRFRATExITEhMSETgTNxEUEjcTNxM3ETgSOBI4EjcTEhM3ERQSEhITEhMSExEUEjcUERI4ETgTNxE4EwAFJgABJ0sSAAxWAAEnSxIADQU='
|
||||
command_off: 'JgBYAAABJ5UTERITEjgRFRATExITEhMSETgTNxEUEjcTNxM3ETgSOBI4EjcTEhM3ERQSEhITEhMSExEUEjcUERI4ETgTNxE4EwAFJgABJ0sSAAxWAAEnSxIADQU='
|
||||
tv_vol_up:
|
||||
friendly_name: "Vol+"
|
||||
command_on: 'JgBYAAABKZMRFBEVETcSExEVEBUQFBMSETgSOBITEjcRORE4EjkRNhMUETgRFBITERQQFBIUEBQRORITETgSOBE4EjgRORI3EwAFJgABJ0sRAAxXAAEnSxEADQU='
|
||||
command_off: 'JgBYAAABKZMRFBEVETcSExEVEBUQFBMSETgSOBITEjcRORE4EjkRNhMUETgRFBITERQQFBIUEBQRORITETgSOBE4EjgRORI3EwAFJgABJ0sRAAxXAAEnSxEADQU='
|
||||
tv_vol_down:
|
||||
friendly_name: "Vol-"
|
||||
command_on: 'JgBYAAABKJQTEhISEjgRFBEUEhITEhIUEDkSNxMSEjgSNxM3EjgSNxI4ETkRFBMREhMRFRETERQRExITEzcSNxM3EjgSNxM3EgAFJwABJkwRAAxXAAEoShMADQU='
|
||||
command_off: 'JgBYAAABKJQTEhISEjgRFBEUEhITEhIUEDkSNxMSEjgSNxM3EjgSNxI4ETkRFBMREhMRFRETERQRExITEzcSNxM3EjgSNxM3EgAFJwABJkwRAAxXAAEoShMADQU='
|
||||
tv_prog_up:
|
||||
friendly_name: "Prog+"
|
||||
command_on: 'JgBYAAABJ5QTEhITETkSExETEhMSExMSEjcTNxEUEjcUNhI4EjcSOBITERQSEhITExISExEUERQROBI4EjcSOBE5ETgTNxE5EgAFJgABJ0sRAAxYAAEmTBEADQU='
|
||||
command_off: 'JgBYAAABJ5QTEhITETkSExETEhMSExMSEjcTNxEUEjcUNhI4EjcSOBITERQSEhITExISExEUERQROBI4EjcSOBE5ETgTNxE5EgAFJgABJ0sRAAxYAAEmTBEADQU='
|
||||
tv_prog_down:
|
||||
friendly_name: "Prog-"
|
||||
command_on: 'JgBQAAABJ5QTEhMSETkRExITEhMTEhEUETgTNxITETgTNxI4EjcTNxI4ERMTEhMTERMRFBITERMTEhI4ETgTNxI4EjcTNxI4EQAFJwABJ0sSAA0FAAAAAAAAAAA='
|
||||
command_off: 'JgBQAAABJ5QTEhMSETkRExITEhMTEhEUETgTNxITETgTNxI4EjcTNxI4ERMTEhMTERMRFBITERMTEhI4ETgTNxI4EjcTNxI4EQAFJwABJ0sSAA0FAAAAAAAAAAA='
|
||||
tv_mute:
|
||||
friendly_name: "Mute"
|
||||
command_on: 'JgBYAAABKJQSExEUETgSExITEhMRFBITEDkSNxIUETgROBM3EjgROBI4EhMRFBA5EhMRFBEUERQRExM3ETkSExI3ETkSNxI4EgAFJgABJ0sTAAxWAAEoShIADQU='
|
||||
command_off: 'JgBYAAABKJQSExEUETgSExITEhMRFBITEDkSNxIUETgROBM3EjgROBI4EhMRFBA5EhMRFBEUERQRExM3ETkSExI3ETkSNxI4EgAFJgABJ0sTAAxWAAEoShIADQU='
|
||||
tv_1:
|
||||
friendly_name: "1"
|
||||
command_on: 'JgBgAAABJ5URExMTETgRFBEUERQRExIUEDkSNxYPEjgROBI4ETkROBM3EhQRExETETgTExEUERQRFBE4EjcTOBETEjgSNxM3EQAFJwABKEoSAAxXAAEnSxIADFYAASdKEwANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5URExMTETgRFBEUERQRExIUEDkSNxYPEjgROBI4ETkROBM3EhQRExETETgTExEUERQRFBE4EjcTOBETEjgSNxM3EQAFJwABKEoSAAxXAAEnSxIADFYAASdKEwANBQAAAAAAAAAA'
|
||||
tv_2:
|
||||
friendly_name: "2"
|
||||
command_on: 'JgBQAAABJ5USExETETkRFBEUERQQFRAVEDkROBEVEDkROBE5ETgSOBIUEDkRExIUEDkSExETEhQQOREUEjcSOBEUEjcRORI4EQAFKAABJUwRAA0FAAAAAAAAAAA='
|
||||
command_off: 'JgBQAAABJ5USExETETkRFBEUERQQFRAVEDkROBEVEDkROBE5ETgSOBIUEDkRExIUEDkSExETEhQQOREUEjcSOBEUEjcRORI4EQAFKAABJUwRAA0FAAAAAAAAAAA='
|
||||
tv_3:
|
||||
friendly_name: "3"
|
||||
command_on: 'JgBgAAABJ5QSExEVEjYSFBETEhMSExEUETgSOBITEjcSOBI3EzcRORI3EjgRFRAVETcSFBETERUQExMSEzcRORETEjgRORI3EgAFJgABKEoSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5QSExEVEjYSFBETEhMSExEUETgSOBITEjcSOBI3EzcRORI3EjgRFRAVETcSFBETERUQExMSEzcRORETEjgRORI3EgAFJgABKEoSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
tv_4:
|
||||
friendly_name: "4"
|
||||
command_on: 'JgBYAAABJ5QUEhETETkRFBAUExMQFQ8WETcSOBEUETgTNxI4ETgSOBEVEBQROBEUETkSExETExIRORE4ExMROBEUETgTNxE4EgAFJgABKEoTAAxWAAEnTBEADQU='
|
||||
command_off: 'JgBYAAABJ5QUEhETETkRFBAUExMQFQ8WETcSOBEUETgTNxI4ETgSOBEVEBQROBEUETkSExETExIRORE4ExMROBEUETgTNxE4EgAFJgABKEoTAAxWAAEnTBEADQU='
|
||||
tv_5:
|
||||
friendly_name: "5"
|
||||
command_on: 'JgBQAAABKJQRFRAVDzkSFBEUERQQFBEUETkQOREUEjcRORA5EjgRORI4ERMROREUETkQFRAVEBMSFBE4EhQQOREUETgSNxI4EwAFKAABJksRAA0FAAAAAAAAAAA='
|
||||
command_off: 'JgBQAAABKJQRFRAVDzkSFBEUERQQFBEUETkQOREUEjcRORA5EjgRORI4ERMROREUETkQFRAVEBMSFBE4EhQQOREUETgSNxI4EwAFKAABJksRAA0FAAAAAAAAAAA='
|
||||
tv_6:
|
||||
friendly_name: "6"
|
||||
command_on: 'JgBgAAABJpUTEhITETkSEhMTEhIRFBITEjcTNxEVEDgSOBI4ETgSOBEUEjcSOBEUETgSExEUERUQOBITEhMSOBEUETgRORE4EgAFJgABKEoSAAxWAAEnSxIADFYAASdLEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJpUTEhITETkSEhMTEhIRFBITEjcTNxEVEDgSOBI4ETgSOBEUEjcSOBEUETgSExEUERUQOBITEhMSOBEUETgRORE4EgAFJgABKEoSAAxWAAEnSxIADFYAASdLEQANBQAAAAAAAAAA'
|
||||
tv_7:
|
||||
friendly_name: "7"
|
||||
command_on: 'JgBgAAABJ5USEhITEjkQFBEUEhITEhIUEDkROBIUEDgSORE4ETgTNxE5ETgSOBIUEDgSExITERUQFBETEhQROBIUEDgSOBE5EQAFJwABJ0sSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5USEhITEjkQFBEUEhITEhIUEDkROBIUEDgSORE4ETgTNxE5ETgSOBIUEDgSExITERUQFBETEhQROBIUEDgSOBE5EQAFJwABJ0sSAAxXAAEnSxEADFcAASdLEQANBQAAAAAAAAAA'
|
||||
tv_8:
|
||||
friendly_name: "8"
|
||||
command_on: 'JgBgAAABKJQRFBEUETgSExIUEBQRFBETEjgSOBITETgSOBE4EjgSOBITERMTExE4ETgSFBETERQRORM2EjkTERMSEjcRORI3EwAFJgABJ0sSAAxXAAEoShEADFgAASZMEgANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABKJQRFBEUETgSExIUEBQRFBETEjgSOBITETgSOBE4EjgSOBITERMTExE4ETgSFBETERQRORM2EjkTERMSEjcRORI3EwAFJgABJ0sSAAxXAAEoShEADFgAASZMEgANBQAAAAAAAAAA'
|
||||
tv_9:
|
||||
friendly_name: "9"
|
||||
command_on: 'JgBgAAABJ5URFBEUETgSExITERUQFBETEjgRORMREjgRORI3EjgROBI4ERQRFRE3EzcTExAUEhISFBE4ETkRFBITETgSNxM3EgAFJwABKEkTAAxWAAEmTBIADFYAASdLEgANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5URFBEUETgSExITERUQFBETEjgRORMREjgRORI3EjgROBI4ERQRFRE3EzcTExAUEhISFBE4ETkRFBITETgSNxM3EgAFJwABKEkTAAxWAAEmTBIADFYAASdLEgANBQAAAAAAAAAA'
|
||||
tv_0:
|
||||
friendly_name: "0"
|
||||
command_on: 'JgBgAAABJ5USExITETgSFBETERQRFBETEjkQOBMSEjgSNxI4EjgSNxMSEhMRFBEUEjcTEhEVERMROBI4ETgSOBEUETgTNxI4EQAFJwABJkwRAAxXAAEnSxEADFcAAShKEQANBQAAAAAAAAAA'
|
||||
command_off: 'JgBgAAABJ5USExITETgSFBETERQRFBETEjkQOBMSEjgSNxI4EjgSNxMSEhMRFBEUEjcTEhEVERMROBI4ETgSOBEUETgTNxI4EQAFJwABJkwRAAxXAAEnSxEADFcAAShKEQANBQAAAAAAAAAA'
|
||||
# VideoProjecteur
|
||||
vp_onoff:
|
||||
friendly_name: "VideoProjecteur"
|
||||
command_on: 'JgBYAAABKJQVEBMTEhITNxMSExMREhMSEjgSOBITFBESOBITEhITEhI4FDYTNxMTERMSExITEDoUERMRExISOBQ2EzcTNxMSEgAF0gABKEoTAAxsAAEoShMADQU='
|
||||
command_off: 'JgDKAJCREjUUERI2EjYRExETEDcSEhETETcRExETETcRNxETETcQFBE2ETcSNhE2ExERNxI2EjYSEhETERMRExE3EhIRExE2ETcSNhETEhIRExETEhISEhISExESNhE2EjYSNhI2EK6QkRE2EhISNhI2EhISEhI2ERMRExI2ERMRExA3EjYRExI2EhIRNxE2EjYSNhISEjYRNhI2ERMSEhISEhIRNxETERMSNhE3EDcSEhETERMSEhISERMSEhETEzUSNhI1EjYSNhEADQUAAAAAAAAAAAAAAAAAAA=='
|
||||
amibot_clean:
|
||||
friendly_name: "Nettoyage"
|
||||
command_on: 'JgBIAAABJpMSExITEhMRFBETEhMSNxMTETgRFBE4EhMSOBEUETgSExITERQROBEUERMSExI4ERQROBI4EhMROBE4EjgSExI3EgANBQ=='
|
||||
amibot_base:
|
||||
friendly_name: "Base"
|
||||
command_on: 'JgBIAAABJpMTEhITEhMRFBEUERMROBIUETgRFRA4ERQTNxITEjcRFBE4FBEUERITETgSExITERQRExM3ETgSOBEUETgROBI5EQANBQ=='
|
||||
16
config/01capteur/switch/remote_amibot.yaml.old
Normal file
16
config/01capteur/switch/remote_amibot.yaml.old
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
- platform: broadlink
|
||||
#host: 10.0.0.106
|
||||
mac: 78:0F:77:FD:46:6C
|
||||
timeout: 60
|
||||
#type: rm2_pro_plus
|
||||
switches:
|
||||
# amibot
|
||||
- name: Amibot_Clean
|
||||
friendly_name: "Nettoyage"
|
||||
command_on: 'JgBIAAABJpMSExITEhMRFBETEhMSNxMTETgRFBE4EhMSOBEUETgSExITERQROBEUERMSExI4ERQROBI4EhMROBE4EjgSExI3EgANBQ=='
|
||||
|
||||
- name: Amibot_Base
|
||||
friendly_name: "Base"
|
||||
command_on: 'JgBIAAABJpMTEhITEhMRFBEUERMROBIUETgRFRA4ERQTNxITEjcRFBE4FBEUERITETgSExITERQRExM3ETgSOBEUETgROBI5EQANBQ=='
|
||||
|
||||
1
config/01capteur/switch/switches.yaml
Normal file
1
config/01capteur/switch/switches.yaml
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
84
config/01capteur/switch/wakeonlan.yaml
Normal file
84
config/01capteur/switch/wakeonlan.yaml
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
# pc TOWER NAS
|
||||
- platform: wake_on_lan
|
||||
name: "NAS Unraid Tower"
|
||||
mac: d4:be:d9:93:5e:dd
|
||||
host: 10.0.0.240
|
||||
turn_off:
|
||||
service: shell_command.turn_off_unraid_pc
|
||||
# pc proxmoxM83
|
||||
- platform: wake_on_lan
|
||||
name: "pve-lenovoM83"
|
||||
mac: 00:23:24:79:3e:e0
|
||||
host: 10.0.0.178
|
||||
turn_off:
|
||||
service: shell_command.turn_off_m83lenovo_pc
|
||||
|
||||
# pc HP3300_debian3D
|
||||
- platform: wake_on_lan
|
||||
name: "pc_HP3300"
|
||||
mac: 3C:D9:2B:74:C1:47
|
||||
host: 10.0.1.208
|
||||
turn_off:
|
||||
service: shell_command.turn_off_hp3300_pc
|
||||
# pc Lenovo M91 Bureau
|
||||
- platform: wake_on_lan
|
||||
name: "pc_lenovoM91_bureau"
|
||||
mac: 44:37:e6:6b:53:86
|
||||
host: 10.0.0.113
|
||||
turn_off:
|
||||
service: shell_command.turn_off_lenovom91_bureau_pc
|
||||
# pc HPdc7900_NAS
|
||||
- platform: wake_on_lan
|
||||
name: "hpdc7900_NAS16"
|
||||
mac: 00:25:b3:12:45:b9
|
||||
host: 10.0.0.16
|
||||
turn_off:
|
||||
service: shell_command.turn_off_hp_debnas_pc
|
||||
|
||||
|
||||
# pc atermitter
|
||||
- platform: wake_on_lan
|
||||
name: "pc_atermitter"
|
||||
mac: 00:E0:0B:14:35:7A
|
||||
host: 10.0.1.73
|
||||
turn_off:
|
||||
service: shell_command.turn_off_atermitter_pc
|
||||
# pc BUREAU Aorus
|
||||
- platform: wake_on_lan
|
||||
name: "pc_Aorus"
|
||||
mac: 18:C0:4D:B5:65:74
|
||||
host: 10.0.0.128
|
||||
turn_off:
|
||||
service: shell_command.turn_off_pc_aorus
|
||||
|
||||
|
||||
|
||||
# pc solar-deb
|
||||
- platform: wake_on_lan
|
||||
name: "solar-deb"
|
||||
mac: 9c:8e:99:c7:83:29
|
||||
host: 10.0.0.14
|
||||
turn_off:
|
||||
service: mqtt.publish
|
||||
data_template:
|
||||
topic: "cmnd/solar-deb"
|
||||
payload: "shutdown"
|
||||
|
||||
# pc yoga
|
||||
- platform: wake_on_lan
|
||||
name: "pc-yoga"
|
||||
mac: 60:57:18:99:ed:05
|
||||
host: 10.0.0.24
|
||||
turn_off:
|
||||
service: shell_command.turn_off_pc_yoga
|
||||
#screen_off
|
||||
- platform: template
|
||||
switches:
|
||||
yoga_screen:
|
||||
friendly_name: "Screen PC Yoga"
|
||||
unique_id: "pc-yoga1"
|
||||
turn_on:
|
||||
service: shell_command.screen_on_pc_yoga
|
||||
turn_off:
|
||||
service: shell_command.screen_off_pc_yoga
|
||||
208
config/01capteur/template/template.yaml
Normal file
208
config/01capteur/template/template.yaml
Normal file
@@ -0,0 +1,208 @@
|
||||
- sensor:
|
||||
- name: "Alerte Orages"
|
||||
unique_id: sensor.alerte_orages
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Orages') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune orages' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange orages' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge orages' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:weather-lightning
|
||||
|
||||
- name: "Alerte Vent violent"
|
||||
unique_id: sensor.alerte_vent_violent
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Vent violent') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune vent-violent' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange vent-violent' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge vent-violent' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:weather-windy
|
||||
|
||||
- name: "Alerte Pluie Inondation"
|
||||
unique_id: sensor.alerte_pluie_inondation
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Pluie_inondation') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune pluie_inondation' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange pluie_inondation' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge pluie_inondation' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:weather-pouring
|
||||
|
||||
- name: "Alerte Inondation"
|
||||
unique_id: sensor.alerte_inondation
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Inondation') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune inondation' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange inondation' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge inondation' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:waves-arrow-up
|
||||
|
||||
- name: "Alerte Canicule"
|
||||
unique_id: sensor.alerte_canicule
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Canicule') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune canicule' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange canicule' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge canicule' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:weather-sunny
|
||||
|
||||
- name: "Alerte Neige-verglas"
|
||||
unique_id: sensor.alerte_neige_verglas
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Neige-verglas') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune neige-verglas' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange neige-verglas' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge neige-verglas' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:snowflake
|
||||
|
||||
- name: "Alerte Grand-froid"
|
||||
unique_id: sensor.alerte_grand_froid
|
||||
state: >-
|
||||
{% set wa = (state_attr('sensor.43_weather_alert', 'Grand-froid') ) %}
|
||||
{% set at = (state_attr('binary_sensor.meteoalarm','awareness_type') ) %}
|
||||
{% set ev = (state_attr('binary_sensor.meteoalarm','event') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif 'jaune grand-froid' in ev %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif 'orange grand-froid' in ev %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif 'rouge grand-froid' in ev %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'Vert' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
icon: mdi:snowman
|
||||
|
||||
- name: "Alerte Météo"
|
||||
unique_id: sensor.alerte_meteo
|
||||
state: >-
|
||||
{% set wa = (states('sensor.43_weather_alert') ) %}
|
||||
{% set al = (state_attr('binary_sensor.meteoalarm','awareness_level') ) %}
|
||||
{% if wa in ['Vert', 'Jaune', 'Orange', 'Rouge'] %}
|
||||
{% set al = wa %}
|
||||
{% elif '1' in al %}
|
||||
{% set al = 'Vert' %}
|
||||
{% elif '2' in al %}
|
||||
{% set al = 'Jaune' %}
|
||||
{% elif '3' in al %}
|
||||
{% set al = 'Orange' %}
|
||||
{% elif '4' in al %}
|
||||
{% set al = 'Rouge' %}
|
||||
{% else %}
|
||||
{% set al = 'unknown' %}
|
||||
{% endif %}
|
||||
{{ al }}
|
||||
attributes:
|
||||
Date: >-
|
||||
{% set dt = (state_attr('binary_sensor.meteoalarm','urgency') ) %}
|
||||
{% if dt == 'Future' %}
|
||||
{% set val = 'Demain' %}
|
||||
{% else %}
|
||||
{% set val = dt %}
|
||||
{% endif %}
|
||||
{{ val }}
|
||||
Orages: >-
|
||||
{% set val = states('sensor.alerte_orages') %}
|
||||
{{ val }}
|
||||
Vent Violent: >-
|
||||
{% set val = states('sensor.alerte_vent_violent') %}
|
||||
{{ val }}
|
||||
Pluie Inondation: >-
|
||||
{% set val = states('sensor.alerte_pluie_inondation') %}
|
||||
{{ val }}
|
||||
Inondation: >-
|
||||
{% set val = states('sensor.alerte_Inondation') %}
|
||||
{{ val }}
|
||||
Canicule: >-
|
||||
{% set val = states('sensor.alerte_canicule') %}
|
||||
{{ val }}
|
||||
Grand Froid: >-
|
||||
{% set val = states('sensor.alerte_grand_froid') %}
|
||||
{{ val }}
|
||||
Neige Verglas: >-
|
||||
{% set val = states('sensor.alerte_neige_verglas') %}
|
||||
{{ val }}
|
||||
icon: mdi:weather-cloudy-alert
|
||||
|
||||
- binary_sensor:
|
||||
- state: "{{states('sensor.athom_smart_plug_elegoomars_1_wattage') | float(default =0) > 5}}"
|
||||
name: impression SLA en cours
|
||||
unique_id: is_sla_printinig_running
|
||||
device_class: running
|
||||
delay_off: "00:02:00"
|
||||
# - state: "{{states('sensor.bl0937_power_4') | float(default =0) > 5}}"
|
||||
# name: Machine a laver en cours
|
||||
# unique_id: is_washing_machine_running
|
||||
# device_class: running
|
||||
# delay_off: "00:02:00"
|
||||
# - state: "{{states('sensor.bl0937_power_sl') | float(default =0) > 5}}"
|
||||
# name: SecheLinge en cours
|
||||
# unique_id: is_sechelinge_running
|
||||
# device_class: running
|
||||
# delay_off: "00:02:00"
|
||||
@@ -1,3 +1,23 @@
|
||||
homeassistant:
|
||||
# auth_providers:
|
||||
# - type: trusted_networks
|
||||
# trusted_networks:
|
||||
# - 10.0.0.128
|
||||
# - 10.0.0.113
|
||||
# - 10.0.0.216
|
||||
# - 10.0.0.217
|
||||
# - 10.0.0.1
|
||||
# allow_bypass_login: true
|
||||
|
||||
# allowlist_external_dirs:
|
||||
# - /config/capture
|
||||
customize: !include customize.yaml
|
||||
packages: !include_dir_named packages
|
||||
|
||||
http: #si cette balise n'existe pas, ajoutez la, sinon ajouter seulement la suite (pas de duplication)
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies:
|
||||
- 10.0.0.16
|
||||
|
||||
# Loads default set of integrations. Do not remove.
|
||||
default_config:
|
||||
@@ -6,6 +26,73 @@ default_config:
|
||||
frontend:
|
||||
themes: !include_dir_merge_named themes
|
||||
|
||||
zone:
|
||||
- name: Travail
|
||||
latitude: 45.26994161017957
|
||||
longitude: 4.111876806976284
|
||||
radius: 200
|
||||
icon: mdi:factory
|
||||
|
||||
# This will override the default home zone
|
||||
- name: home
|
||||
latitude: 45.14203329491988
|
||||
longitude: 4.075071876335187
|
||||
radius: 20
|
||||
icon: mdi:home
|
||||
|
||||
- name: Near_Home
|
||||
latitude: 45.14203329491988
|
||||
longitude: 4.075071876335187
|
||||
radius: 200
|
||||
icon: mdi:broadcast
|
||||
|
||||
automation: !include automations.yaml
|
||||
script: !include scripts.yaml
|
||||
scene: !include scenes.yaml
|
||||
group: !include groups.yaml
|
||||
|
||||
automation old: !include_dir_merge_list automation/
|
||||
switch: !include_dir_merge_list 01capteur/switch/
|
||||
light: !include_dir_merge_list 01capteur/light/
|
||||
sensor: !include_dir_merge_list 01capteur/sensor/
|
||||
binary_sensor: !include_dir_merge_list 01capteur/binary_sensor/
|
||||
template: !include_dir_merge_list 01capteur/template/
|
||||
cover: !include_dir_merge_list 01capteur/cover/
|
||||
mqtt: !include 01capteur/mqtt/mqtt.yaml
|
||||
device_tracker: !include_dir_merge_list 01capteur/device_tracker/
|
||||
#openhasp: !include 01capteur/openhasp.yaml
|
||||
irrigation_unlimited: !include 01capteur/irrigation.yaml
|
||||
shell_command: !include 01capteur/shell_commands.yaml
|
||||
#modbus: !include_dir_merge_list 01capteur/modbus/
|
||||
#recorder: !include_dir_merge_list 01capteur/recorder/
|
||||
|
||||
duckdns:
|
||||
domain: maison43
|
||||
access_token: 0fd20557-743c-41da-858e-724143602751
|
||||
|
||||
recorder:
|
||||
db_url: mysql://homeassistant:homeassistant@core-mariadb/homeassistant?charset=utf8mb4
|
||||
purge_keep_days: 30
|
||||
auto_purge: true
|
||||
auto_repack: true
|
||||
commit_interval: 5
|
||||
|
||||
alarm_control_panel:
|
||||
- platform: manual
|
||||
name: Home Alarm
|
||||
code: "1974"
|
||||
arming_time: 30
|
||||
delay_time: 20
|
||||
trigger_time: 4
|
||||
disarmed:
|
||||
trigger_time: 0
|
||||
armed_home:
|
||||
arming_time: 0
|
||||
delay_time: 0
|
||||
armed_night:
|
||||
arming_time: 0
|
||||
delay_time: 0
|
||||
|
||||
api:
|
||||
|
||||
wake_on_lan:
|
||||
|
||||
350
config/custom_components/apsystems_ecur/APSystemsSocket.py
Normal file
350
config/custom_components/apsystems_ecur/APSystemsSocket.py
Normal file
@@ -0,0 +1,350 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import socket
|
||||
import binascii
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
class APSystemsInvalidData(Exception):
|
||||
pass
|
||||
|
||||
class APSystemsSocket:
|
||||
def __init__(self, ipaddr, nographs, port=8899, raw_ecu=None, raw_inverter=None):
|
||||
global no_graphs
|
||||
no_graphs = nographs
|
||||
self.ipaddr = ipaddr
|
||||
self.port = port
|
||||
|
||||
# what do we expect socket data to end in
|
||||
self.recv_suffix = b'END\n'
|
||||
|
||||
# how long to wait on socket commands until we get our recv_suffix
|
||||
self.timeout = 10
|
||||
|
||||
# how big of a buffer to read at a time from the socket
|
||||
# https://github.com/ksheumaker/homeassistant-apsystems_ecur/issues/108
|
||||
self.recv_size = 1024
|
||||
|
||||
# how long to wait between socket open/closes
|
||||
self.socket_sleep_time = 5
|
||||
|
||||
self.cmd_suffix = "END\n"
|
||||
self.ecu_query = "APS1100160001" + self.cmd_suffix
|
||||
self.inverter_query_prefix = "APS1100280002"
|
||||
self.inverter_query_suffix = self.cmd_suffix
|
||||
self.inverter_signal_prefix = "APS1100280030"
|
||||
self.inverter_signal_suffix = self.cmd_suffix
|
||||
self.ecu_id = None
|
||||
self.qty_of_inverters = 0
|
||||
self.qty_of_online_inverters = 0
|
||||
self.lifetime_energy = 0
|
||||
self.current_power = 0
|
||||
self.today_energy = 0
|
||||
self.inverters = {}
|
||||
self.firmware = None
|
||||
self.timezone = None
|
||||
self.last_update = None
|
||||
self.vsl = 0
|
||||
self.tsl = 0
|
||||
self.ecu_raw_data = raw_ecu
|
||||
self.inverter_raw_data = raw_inverter
|
||||
self.inverter_raw_signal = None
|
||||
self.read_buffer = b''
|
||||
self.socket = None
|
||||
self.socket_open = False
|
||||
self.errors = []
|
||||
|
||||
def send_read_from_socket(self, cmd):
|
||||
try:
|
||||
self.sock.settimeout(self.timeout)
|
||||
self.sock.sendall(cmd.encode('utf-8'))
|
||||
time.sleep(self.socket_sleep_time)
|
||||
self.read_buffer = b''
|
||||
self.sock.settimeout(self.timeout)
|
||||
# An infinite loop was causing the integration to block
|
||||
# https://github.com/ksheumaker/homeassistant-apsystems_ecur/issues/115
|
||||
# Solution might cause a new issue when large solar array's applies
|
||||
self.read_buffer = self.sock.recv(self.recv_size)
|
||||
return self.read_buffer
|
||||
except Exception as err:
|
||||
self.close_socket()
|
||||
raise APSystemsInvalidData(err)
|
||||
|
||||
def close_socket(self):
|
||||
try:
|
||||
if self.socket_open:
|
||||
self.sock.shutdown(socket.SHUT_RDWR)
|
||||
self.sock.close()
|
||||
self.socket_open = False
|
||||
except Exception as err:
|
||||
raise APSystemsInvalidData(err)
|
||||
|
||||
def open_socket(self):
|
||||
self.socket_open = False
|
||||
try:
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
# self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
||||
self.sock.settimeout(self.timeout)
|
||||
self.sock.connect((self.ipaddr, self.port))
|
||||
self.socket_open = True
|
||||
except Exception as err:
|
||||
raise APSystemsInvalidData(err)
|
||||
|
||||
def query_ecu(self):
|
||||
#read ECU data
|
||||
self.open_socket()
|
||||
self.ecu_raw_data = self.send_read_from_socket(self.ecu_query)
|
||||
self.close_socket()
|
||||
try:
|
||||
self.process_ecu_data()
|
||||
except Exception as err:
|
||||
raise APSystemsInvalidData(err)
|
||||
|
||||
#read inverter data
|
||||
# Some ECUs like the socket to be closed and re-opened between commands
|
||||
self.open_socket()
|
||||
cmd = self.inverter_query_prefix + self.ecu_id + self.inverter_query_suffix
|
||||
self.inverter_raw_data = self.send_read_from_socket(cmd)
|
||||
self.close_socket()
|
||||
|
||||
#read signal data
|
||||
# Some ECUs like the socket to be closed and re-opened between commands
|
||||
self.open_socket()
|
||||
cmd = self.inverter_signal_prefix + self.ecu_id + self.inverter_signal_suffix
|
||||
self.inverter_raw_signal = self.send_read_from_socket(cmd)
|
||||
self.close_socket()
|
||||
|
||||
data = self.process_inverter_data()
|
||||
data["ecu_id"] = self.ecu_id
|
||||
if self.lifetime_energy != 0:
|
||||
data["lifetime_energy"] = self.lifetime_energy
|
||||
data["current_power"] = self.current_power
|
||||
# apply filter for ECU-R-pro firmware bug where both are zero
|
||||
if self.qty_of_inverters > 0:
|
||||
data["qty_of_inverters"] = self.qty_of_inverters
|
||||
data["today_energy"] = self.today_energy
|
||||
data["qty_of_online_inverters"] = self.qty_of_online_inverters
|
||||
return(data)
|
||||
|
||||
def aps_int_from_bytes(self, codec: bytes, start: int, length: int) -> int:
|
||||
try:
|
||||
return int (binascii.b2a_hex(codec[(start):(start+length)]), 16)
|
||||
except ValueError as err:
|
||||
debugdata = binascii.b2a_hex(codec)
|
||||
error = f"Unable to convert binary to int with length={length} at location={start} with data={debugdata}"
|
||||
raise APSystemsInvalidData(error)
|
||||
|
||||
def aps_uid(self, codec, start):
|
||||
return str(binascii.b2a_hex(codec[(start):(start+12)]))[2:14]
|
||||
|
||||
def aps_str(self, codec, start, amount):
|
||||
return str(codec[start:(start+amount)])[2:(amount+2)]
|
||||
|
||||
def aps_datetimestamp(self, codec, start, amount):
|
||||
timestr=str(binascii.b2a_hex(codec[start:(start+amount)]))[2:(amount+2)]
|
||||
return timestr[0:4]+"-"+timestr[4:6]+"-"+timestr[6:8]+" "+timestr[8:10]+":"+timestr[10:12]+":"+timestr[12:14]
|
||||
|
||||
def check_ecu_checksum(self, data, cmd):
|
||||
datalen = len(data) - 1
|
||||
try:
|
||||
checksum = int(data[5:9])
|
||||
except ValueError as err:
|
||||
debugdata = binascii.b2a_hex(data)
|
||||
error = f"could not extract checksum int from '{cmd}' data={debugdata}"
|
||||
raise APSystemsInvalidData(error)
|
||||
|
||||
if datalen != checksum:
|
||||
debugdata = binascii.b2a_hex(data)
|
||||
error = f"Checksum on '{cmd}' failed checksum={checksum} datalen={datalen} data={debugdata}"
|
||||
raise APSystemsInvalidData(error)
|
||||
|
||||
start_str = self.aps_str(data, 0, 3)
|
||||
end_str = self.aps_str(data, len(data) - 4, 3)
|
||||
|
||||
if start_str != 'APS':
|
||||
debugdata = binascii.b2a_hex(data)
|
||||
error = f"Result on '{cmd}' incorrect start signature '{start_str}' != APS data={debugdata}"
|
||||
raise APSystemsInvalidData(error)
|
||||
|
||||
if end_str != 'END':
|
||||
debugdata = binascii.b2a_hex(data)
|
||||
error = f"Result on '{cmd}' incorrect end signature '{end_str}' != END data={debugdata}"
|
||||
raise APSystemsInvalidData(error)
|
||||
|
||||
return True
|
||||
|
||||
def process_ecu_data(self, data=None):
|
||||
if self.ecu_raw_data != '' and (self.aps_str(self.ecu_raw_data,9,4)) == '0001':
|
||||
data = self.ecu_raw_data
|
||||
_LOGGER.debug(binascii.b2a_hex(data))
|
||||
self.check_ecu_checksum(data, "ECU Query")
|
||||
self.ecu_id = self.aps_str(data, 13, 12)
|
||||
self.lifetime_energy = self.aps_int_from_bytes(data, 27, 4) / 10
|
||||
self.current_power = self.aps_int_from_bytes(data, 31, 4)
|
||||
self.today_energy = self.aps_int_from_bytes(data, 35, 4) / 100
|
||||
if self.aps_str(data,25,2) == "01":
|
||||
self.qty_of_inverters = self.aps_int_from_bytes(data, 46, 2)
|
||||
self.qty_of_online_inverters = self.aps_int_from_bytes(data, 48, 2)
|
||||
self.vsl = int(self.aps_str(data, 52, 3))
|
||||
self.firmware = self.aps_str(data, 55, self.vsl)
|
||||
self.tsl = int(self.aps_str(data, 55 + self.vsl, 3))
|
||||
self.timezone = self.aps_str(data, 58 + self.vsl, self.tsl)
|
||||
elif self.aps_str(data,25,2) == "02":
|
||||
self.qty_of_inverters = self.aps_int_from_bytes(data, 39, 2)
|
||||
self.qty_of_online_inverters = self.aps_int_from_bytes(data, 41, 2)
|
||||
self.vsl = int(self.aps_str(data, 49, 3))
|
||||
self.firmware = self.aps_str(data, 52, self.vsl)
|
||||
|
||||
def process_signal_data(self, data=None):
|
||||
signal_data = {}
|
||||
if self.inverter_raw_signal != '' and (self.aps_str(self.inverter_raw_signal,9,4)) == '0030':
|
||||
data = self.inverter_raw_signal
|
||||
_LOGGER.debug(binascii.b2a_hex(data))
|
||||
self.check_ecu_checksum(data, "Signal Query")
|
||||
if not self.qty_of_inverters:
|
||||
return signal_data
|
||||
location = 15
|
||||
for i in range(0, self.qty_of_inverters):
|
||||
uid = self.aps_uid(data, location)
|
||||
location += 6
|
||||
strength = data[location]
|
||||
location += 1
|
||||
strength = int((strength / 255) * 100)
|
||||
signal_data[uid] = strength
|
||||
return signal_data
|
||||
|
||||
def process_inverter_data(self, data=None):
|
||||
output = {}
|
||||
if self.inverter_raw_data != '' and (self.aps_str(self.inverter_raw_data,9,4)) == '0002':
|
||||
data = self.inverter_raw_data
|
||||
_LOGGER.debug(binascii.b2a_hex(data))
|
||||
self.check_ecu_checksum(data, "Inverter data")
|
||||
istr = ''
|
||||
cnt1 = 0
|
||||
cnt2 = 26
|
||||
if self.aps_str(data, 14, 2) == '00':
|
||||
timestamp = self.aps_datetimestamp(data, 19, 14)
|
||||
inverter_qty = self.aps_int_from_bytes(data, 17, 2)
|
||||
self.last_update = timestamp
|
||||
output["timestamp"] = timestamp
|
||||
output["inverters"] = {}
|
||||
signal = self.process_signal_data()
|
||||
inverters = {}
|
||||
|
||||
while cnt1 < inverter_qty:
|
||||
inv={}
|
||||
if self.aps_str(data, 15, 2) == '01':
|
||||
inverter_uid = self.aps_uid(data, cnt2)
|
||||
inv["uid"] = inverter_uid
|
||||
inv["online"] = bool(self.aps_int_from_bytes(data, cnt2 + 6, 1))
|
||||
istr = self.aps_str(data, cnt2 + 7, 2)
|
||||
|
||||
# Should graphs be updated?
|
||||
if inv["online"] == False and no_graphs == True:
|
||||
inv["signal"] = None
|
||||
else:
|
||||
inv["signal"] = signal.get(inverter_uid, 0)
|
||||
|
||||
# Distinguishes the different inverters from this point down
|
||||
if istr in [ '01', '04', '05']:
|
||||
power = []
|
||||
voltages = []
|
||||
|
||||
# Should graphs be updated?
|
||||
if inv["online"] == True:
|
||||
inv["temperature"] = self.aps_int_from_bytes(data, cnt2 + 11, 2) - 100
|
||||
if inv["online"] == False and no_graphs == True:
|
||||
inv["frequency"] = None
|
||||
power.append(None)
|
||||
voltages.append(None)
|
||||
power.append(None)
|
||||
voltages.append(None)
|
||||
else:
|
||||
inv["frequency"] = self.aps_int_from_bytes(data, cnt2 + 9, 2) / 10
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 13, 2))
|
||||
voltages.append(self.aps_int_from_bytes(data, cnt2 + 15, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 17, 2))
|
||||
voltages.append(self.aps_int_from_bytes(data, cnt2 + 19, 2))
|
||||
|
||||
inv_details = {
|
||||
"model" : "YC600/DS3 series",
|
||||
"channel_qty" : 2,
|
||||
"power" : power,
|
||||
"voltage" : voltages
|
||||
}
|
||||
inv.update(inv_details)
|
||||
cnt2 = cnt2 + 21
|
||||
elif istr == '02':
|
||||
power = []
|
||||
voltages = []
|
||||
|
||||
# Should graphs be updated?
|
||||
if inv["online"]:
|
||||
inv["temperature"] = self.aps_int_from_bytes(data, cnt2 + 11, 2) - 100
|
||||
if inv["online"] == False and no_graphs == True:
|
||||
inv["frequency"] = None
|
||||
power.append(None)
|
||||
voltages.append(None)
|
||||
power.append(None)
|
||||
voltages.append(None)
|
||||
power.append(None)
|
||||
voltages.append(None)
|
||||
power.append(None)
|
||||
else:
|
||||
inv["frequency"] = self.aps_int_from_bytes(data, cnt2 + 9, 2) / 10
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 13, 2))
|
||||
voltages.append(self.aps_int_from_bytes(data, cnt2 + 15, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 17, 2))
|
||||
voltages.append(self.aps_int_from_bytes(data, cnt2 + 19, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 21, 2))
|
||||
voltages.append(self.aps_int_from_bytes(data, cnt2 + 23, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 25, 2))
|
||||
|
||||
inv_details = {
|
||||
"model" : "YC1000/QT2",
|
||||
"channel_qty" : 4,
|
||||
"power" : power,
|
||||
"voltage" : voltages
|
||||
}
|
||||
inv.update(inv_details)
|
||||
cnt2 = cnt2 + 27
|
||||
elif istr == '03':
|
||||
power = []
|
||||
voltages = []
|
||||
|
||||
# Should graphs be updated?
|
||||
if inv["online"]:
|
||||
inv["temperature"] = self.aps_int_from_bytes(data, cnt2 + 11, 2) - 100
|
||||
if inv["online"] == False and no_graphs == True:
|
||||
inv["frequency"] = None
|
||||
power.append(None)
|
||||
voltages.append(None)
|
||||
power.append(None)
|
||||
power.append(None)
|
||||
power.append(None)
|
||||
else:
|
||||
inv["frequency"] = self.aps_int_from_bytes(data, cnt2 + 9, 2) / 10
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 13, 2))
|
||||
voltages.append(self.aps_int_from_bytes(data, cnt2 + 15, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 17, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 19, 2))
|
||||
power.append(self.aps_int_from_bytes(data, cnt2 + 21, 2))
|
||||
|
||||
inv_details = {
|
||||
"model" : "QS1",
|
||||
"channel_qty" : 4,
|
||||
"power" : power,
|
||||
"voltage" : voltages
|
||||
}
|
||||
inv.update(inv_details)
|
||||
cnt2 = cnt2 + 23
|
||||
else:
|
||||
cnt2 = cnt2 + 9
|
||||
inverters[inverter_uid] = inv
|
||||
cnt1 = cnt1 + 1
|
||||
self.inverters = inverters
|
||||
output["inverters"] = inverters
|
||||
return (output)
|
||||
241
config/custom_components/apsystems_ecur/__init__.py
Normal file
241
config/custom_components/apsystems_ecur/__init__.py
Normal file
@@ -0,0 +1,241 @@
|
||||
import logging
|
||||
import requests
|
||||
|
||||
import voluptuous as vol
|
||||
import traceback
|
||||
import datetime as dt
|
||||
from datetime import timedelta
|
||||
|
||||
from .APSystemsSocket import APSystemsSocket, APSystemsInvalidData
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.discovery import load_platform
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant import config_entries, exceptions
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.components.persistent_notification import (
|
||||
create as create_persistent_notification
|
||||
)
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
UpdateFailed,
|
||||
)
|
||||
from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
PLATFORMS = [ "sensor", "binary_sensor", "switch" ]
|
||||
|
||||
class WiFiSet():
|
||||
ipaddr = ""
|
||||
ssid = ""
|
||||
wpa = ""
|
||||
cache = 3
|
||||
WiFiSet = WiFiSet()
|
||||
|
||||
# handle all the communications with the ECUR class and deal with our need for caching, etc
|
||||
class ECUR():
|
||||
def __init__(self, ipaddr, ssid, wpa, cache, nographs):
|
||||
self.ecu = APSystemsSocket(ipaddr, nographs)
|
||||
self.cache_count = 0
|
||||
self.data_from_cache = False
|
||||
self.querying = True
|
||||
self.inverters_online = True
|
||||
self.ecu_restarting = False
|
||||
self.cached_data = {}
|
||||
WiFiSet.ipaddr = ipaddr
|
||||
WiFiSet.ssid = ssid
|
||||
WiFiSet.wpa = wpa
|
||||
WiFiSet.cache = cache
|
||||
|
||||
def stop_query(self):
|
||||
self.querying = False
|
||||
|
||||
def start_query(self):
|
||||
self.querying = True
|
||||
|
||||
def inverters_off(self):
|
||||
headers = {'X-Requested-With': 'XMLHttpRequest'}
|
||||
url = 'http://'+ str(WiFiSet.ipaddr) + '/index.php/configuration/set_switch_all_off'
|
||||
try:
|
||||
get_url = requests.post(url, headers=headers)
|
||||
self.inverters_online = False
|
||||
_LOGGER.debug(f"Response from ECU on switching the inverters off: {str(get_url.status_code)}")
|
||||
except Exception as err:
|
||||
_LOGGER.warning(f"Attempt to switch inverters off failed with error: {err} (This switch is only compatible with ECU-R pro and ECU-C type ECU's)")
|
||||
|
||||
def inverters_on(self):
|
||||
headers = {'X-Requested-With': 'XMLHttpRequest'}
|
||||
url = 'http://'+ str(WiFiSet.ipaddr) + '/index.php/configuration/set_switch_all_on'
|
||||
try:
|
||||
get_url = requests.post(url, headers=headers)
|
||||
self.inverters_online = True
|
||||
_LOGGER.debug(f"Response from ECU on switching the inverters on: {str(get_url.status_code)}")
|
||||
except Exception as err:
|
||||
_LOGGER.warning(f"Attempt to switch inverters on failed with error: {err} (This switch is only compatible with ECU-R pro and ECU-C type ECU's)")
|
||||
|
||||
def use_cached_data(self, msg):
|
||||
# we got invalid data, so we need to pull from cache
|
||||
self.error_msg = msg
|
||||
self.cache_count += 1
|
||||
self.data_from_cache = True
|
||||
|
||||
if self.cache_count == WiFiSet.cache:
|
||||
_LOGGER.warning(f"Communication with the ECU failed after {WiFiSet.cache} repeated attempts.")
|
||||
data = {'SSID': WiFiSet.ssid, 'channel': 0, 'method': 2, 'psk_wep': '', 'psk_wpa': WiFiSet.wpa}
|
||||
_LOGGER.debug(f"Data sent with URL: {data}")
|
||||
# Determine ECU type to decide ECU restart (for ECU-C and ECU-R with sunspec only)
|
||||
if (self.cached_data.get("ecu_id", None)[0:3] == "215") or (self.cached_data.get("ecu_id", None)[0:4] == "2162"):
|
||||
url = 'http://' + str(WiFiSet.ipaddr) + '/index.php/management/set_wlan_ap'
|
||||
headers = {'X-Requested-With': 'XMLHttpRequest'}
|
||||
try:
|
||||
get_url = requests.post(url, headers=headers, data=data)
|
||||
_LOGGER.debug(f"Response from ECU on restart: {str(get_url.status_code)}")
|
||||
self.ecu_restarting = True
|
||||
except Exception as err:
|
||||
_LOGGER.warning(f"Attempt to restart ECU failed with error: {err}. Querying is stopped automatically.")
|
||||
self.querying = False
|
||||
else:
|
||||
# Older ECU-R models starting with 2160
|
||||
_LOGGER.warning("Try manually power cycling the ECU. Querying is stopped automatically, turn switch back on after restart of ECU.")
|
||||
self.querying = False
|
||||
|
||||
if self.cached_data.get("ecu_id", None) == None:
|
||||
_LOGGER.debug(f"Cached data {self.cached_data}")
|
||||
raise UpdateFailed(f"Unable to get correct data from ECU, and no cached data. See log for details, and try power cycling the ECU.")
|
||||
return self.cached_data
|
||||
|
||||
def update(self):
|
||||
data = {}
|
||||
# if we aren't actively quering data, pull data form the cache
|
||||
# this is so we can stop querying after sunset
|
||||
if not self.querying:
|
||||
_LOGGER.debug("Not querying ECU due to query=False")
|
||||
data = self.cached_data
|
||||
self.data_from_cache = True
|
||||
data["data_from_cache"] = self.data_from_cache
|
||||
data["querying"] = self.querying
|
||||
return self.cached_data
|
||||
|
||||
_LOGGER.debug("Querying ECU...")
|
||||
try:
|
||||
data = self.ecu.query_ecu()
|
||||
_LOGGER.debug("Got data from ECU")
|
||||
|
||||
# we got good results, so we store it and set flags about our cache state
|
||||
if data["ecu_id"] != None:
|
||||
self.cached_data = data
|
||||
self.cache_count = 0
|
||||
self.data_from_cache = False
|
||||
self.ecu_restarting = False
|
||||
self.error_message = ""
|
||||
else:
|
||||
msg = f"Using cached data from last successful communication from ECU. Error: no ecu_id returned"
|
||||
_LOGGER.warning(msg)
|
||||
data = self.use_cached_data(msg)
|
||||
|
||||
except APSystemsInvalidData as err:
|
||||
msg = f"Using cached data from last successful communication from ECU. Invalid data error: {err}"
|
||||
if str(err) != 'timed out':
|
||||
_LOGGER.warning(msg)
|
||||
data = self.use_cached_data(msg)
|
||||
|
||||
except Exception as err:
|
||||
msg = f"Using cached data from last successful communication from ECU. Exception error: {err}"
|
||||
_LOGGER.warning(msg)
|
||||
data = self.use_cached_data(msg)
|
||||
|
||||
data["data_from_cache"] = self.data_from_cache
|
||||
data["querying"] = self.querying
|
||||
data["restart_ecu"] = self.ecu_restarting
|
||||
_LOGGER.debug(f"Returning {data}")
|
||||
if data.get("ecu_id", None) == None:
|
||||
raise UpdateFailed(f"Somehow data doesn't contain a valid ecu_id")
|
||||
return data
|
||||
|
||||
async def update_listener(hass, config):
|
||||
# Handle options update being triggered by config entry options updates
|
||||
_LOGGER.debug(f"Configuration updated: {config.as_dict()}")
|
||||
ecu = ECUR(config.data["host"],
|
||||
config.data["SSID"],
|
||||
config.data["WPA-PSK"],
|
||||
config.data["CACHE"],
|
||||
config.data["stop_graphs"]
|
||||
)
|
||||
|
||||
async def async_setup_entry(hass, config):
|
||||
# Setup the APsystems platform """
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
host = config.data["host"]
|
||||
interval = timedelta(seconds=config.data["scan_interval"])
|
||||
# Defaults for new parameters that might not have been set yet from previous integration versions
|
||||
cache = config.data.get("CACHE", 5)
|
||||
ssid = config.data.get("SSID", "ECU-WiFi_SSID")
|
||||
wpa = config.data.get("WPA-PSK", "myWiFipassword")
|
||||
nographs = config.data.get("stop_graphs", False)
|
||||
ecu = ECUR(host, ssid, wpa, cache, nographs)
|
||||
|
||||
|
||||
async def do_ecu_update():
|
||||
return await hass.async_add_executor_job(ecu.update)
|
||||
|
||||
coordinator = DataUpdateCoordinator(
|
||||
hass,
|
||||
_LOGGER,
|
||||
name=DOMAIN,
|
||||
update_method=do_ecu_update,
|
||||
update_interval=interval,
|
||||
)
|
||||
|
||||
hass.data[DOMAIN] = {
|
||||
"ecu" : ecu,
|
||||
"coordinator" : coordinator
|
||||
}
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=config.entry_id,
|
||||
identifiers={(DOMAIN, f"ecu_{ecu.ecu.ecu_id}")},
|
||||
manufacturer="APSystems",
|
||||
suggested_area="Roof",
|
||||
name=f"ECU {ecu.ecu.ecu_id}",
|
||||
model=ecu.ecu.firmware,
|
||||
sw_version=ecu.ecu.firmware,
|
||||
)
|
||||
|
||||
inverters = coordinator.data.get("inverters", {})
|
||||
for uid,inv_data in inverters.items():
|
||||
model = inv_data.get("model", "Inverter")
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=config.entry_id,
|
||||
identifiers={(DOMAIN, f"inverter_{uid}")},
|
||||
manufacturer="APSystems",
|
||||
suggested_area="Roof",
|
||||
name=f"Inverter {uid}",
|
||||
model=inv_data.get("model")
|
||||
)
|
||||
await hass.config_entries.async_forward_entry_setups(config, PLATFORMS)
|
||||
config.async_on_unload(config.add_update_listener(update_listener))
|
||||
return True
|
||||
|
||||
async def async_remove_config_entry_device(hass, config, device_entry) -> bool:
|
||||
if device_entry is not None:
|
||||
# Notify the user that the device has been removed
|
||||
create_persistent_notification(
|
||||
hass,
|
||||
title="Important notification",
|
||||
message=f"The following device was removed from the system: {device_entry}"
|
||||
)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
async def async_unload_entry(hass, config):
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(config, PLATFORMS)
|
||||
coordinator = hass.data[DOMAIN].get("coordinator")
|
||||
ecu = hass.data[DOMAIN].get("ecu")
|
||||
ecu.stop_query()
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(config.entry_id)
|
||||
return unload_ok
|
||||
92
config/custom_components/apsystems_ecur/binary_sensor.py
Normal file
92
config/custom_components/apsystems_ecur/binary_sensor.py
Normal file
@@ -0,0 +1,92 @@
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntity,
|
||||
)
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
RELOAD_ICON,
|
||||
CACHE_ICON,
|
||||
RESTART_ICON
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_setup_entry(hass, config, add_entities, discovery_info=None):
|
||||
|
||||
ecu = hass.data[DOMAIN].get("ecu")
|
||||
coordinator = hass.data[DOMAIN].get("coordinator")
|
||||
|
||||
sensors = [
|
||||
APSystemsECUBinarySensor(coordinator, ecu, "data_from_cache",
|
||||
label="Using Cached Data", icon=CACHE_ICON),
|
||||
APSystemsECUBinarySensor(coordinator, ecu, "restart_ecu",
|
||||
label="Restart", icon=RESTART_ICON)
|
||||
]
|
||||
add_entities(sensors)
|
||||
|
||||
|
||||
class APSystemsECUBinarySensor(CoordinatorEntity, BinarySensorEntity):
|
||||
|
||||
def __init__(self, coordinator, ecu, field, label=None, devclass=None, icon=None):
|
||||
|
||||
super().__init__(coordinator)
|
||||
|
||||
self.coordinator = coordinator
|
||||
|
||||
self._ecu = ecu
|
||||
self._field = field
|
||||
self._label = label
|
||||
if not label:
|
||||
self._label = field
|
||||
self._icon = icon
|
||||
|
||||
self._name = f"ECU {self._label}"
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return f"{self._ecu.ecu.ecu_id}_{self._field}"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
return self.coordinator.data.get(self._field)
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
|
||||
attrs = {
|
||||
"ecu_id" : self._ecu.ecu.ecu_id,
|
||||
"firmware" : self._ecu.ecu.firmware,
|
||||
"timezone" : self._ecu.ecu.timezone,
|
||||
"last_update" : self._ecu.ecu.last_update
|
||||
}
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
return EntityCategory.DIAGNOSTIC
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
parent = f"ecu_{self._ecu.ecu.ecu_id}"
|
||||
return {
|
||||
"identifiers": {
|
||||
(DOMAIN, parent),
|
||||
}
|
||||
}
|
||||
|
||||
103
config/custom_components/apsystems_ecur/config_flow.py
Normal file
103
config/custom_components/apsystems_ecur/config_flow.py
Normal file
@@ -0,0 +1,103 @@
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
import traceback
|
||||
from datetime import timedelta
|
||||
from homeassistant.core import callback
|
||||
from .APSystemsSocket import APSystemsSocket, APSystemsInvalidData
|
||||
from homeassistant import config_entries, exceptions
|
||||
from homeassistant.const import CONF_HOST, CONF_SCAN_INTERVAL
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
from .const import DOMAIN, CONF_SSID, CONF_WPA_PSK, CONF_CACHE, CONF_STOP_GRAPHS
|
||||
|
||||
STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str,
|
||||
vol.Required(CONF_SCAN_INTERVAL, default=300): int,
|
||||
vol.Optional(CONF_CACHE, default=5): int,
|
||||
vol.Optional(CONF_SSID, default="ECU-WIFI_local"): str,
|
||||
vol.Optional(CONF_WPA_PSK, default="default"): str,
|
||||
vol.Optional(CONF_STOP_GRAPHS, default=False): bool,
|
||||
})
|
||||
|
||||
@config_entries.HANDLERS.register(DOMAIN)
|
||||
class APSsystemsFlowHandler(config_entries.ConfigFlow):
|
||||
|
||||
VERSION = 1
|
||||
def __init__(self):
|
||||
_LOGGER.debug("Starting config flow class...")
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
_LOGGER.debug("Starting user step")
|
||||
errors = {}
|
||||
if user_input is None:
|
||||
_LOGGER.debug("Show form because user input is empty")
|
||||
return self.async_show_form(
|
||||
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
|
||||
)
|
||||
_LOGGER.debug("User input is not empty, processing input")
|
||||
try:
|
||||
_LOGGER.debug("Initial attempt to query ECU")
|
||||
ap_ecu = APSystemsSocket(user_input["host"], user_input["stop_graphs"])
|
||||
test_query = await self.hass.async_add_executor_job(ap_ecu.query_ecu)
|
||||
ecu_id = test_query.get("ecu_id", None)
|
||||
if ecu_id != None:
|
||||
return self.async_create_entry(title=f"ECU: {ecu_id}", data=user_input)
|
||||
else:
|
||||
errors["host"] = "no_ecuid"
|
||||
except APSystemsInvalidData as err:
|
||||
_LOGGER.exception(f"APSystemsInvalidData exception: {err}")
|
||||
errors["host"] = "cannot_connect"
|
||||
except Exception as err:
|
||||
_LOGGER.exception(f"Unknown error occurred during setup: {err}")
|
||||
errors["host"] = "unknown"
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry):
|
||||
_LOGGER.debug("get options flow")
|
||||
return APSsystemsOptionsFlowHandler(config_entry)
|
||||
|
||||
class APSsystemsOptionsFlowHandler(config_entries.OptionsFlow):
|
||||
def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
|
||||
_LOGGER.debug("Starting options flow step class")
|
||||
self.config_entry = config_entry
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
errors = {}
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="init",
|
||||
errors=errors,
|
||||
data_schema=vol.Schema({
|
||||
vol.Required(CONF_HOST, default=self.config_entry.data.get(CONF_HOST)): str,
|
||||
vol.Optional(CONF_SCAN_INTERVAL, default=300,
|
||||
description={"suggested_value": self.config_entry.data.get(CONF_SCAN_INTERVAL)}): int,
|
||||
vol.Optional(CONF_CACHE, default=5,
|
||||
description={"suggested_value": self.config_entry.data.get(CONF_CACHE)}): int,
|
||||
vol.Optional(CONF_SSID, default="ECU-WiFi_SSID",
|
||||
description={"suggested_value": self.config_entry.data.get(CONF_SSID)}): str,
|
||||
vol.Optional(CONF_WPA_PSK, default="myWiFipassword",
|
||||
description={"suggested_value": self.config_entry.data.get(CONF_WPA_PSK)}): str,
|
||||
vol.Optional(CONF_STOP_GRAPHS, default=self.config_entry.data.get(CONF_STOP_GRAPHS)): bool
|
||||
})
|
||||
)
|
||||
try:
|
||||
ap_ecu = APSystemsSocket(user_input["host"], user_input["stop_graphs"])
|
||||
_LOGGER.debug("Attempt to query ECU")
|
||||
test_query = await self.hass.async_add_executor_job(ap_ecu.query_ecu)
|
||||
ecu_id = test_query.get("ecu_id", None)
|
||||
if ecu_id != None:
|
||||
self.hass.config_entries.async_update_entry(
|
||||
self.config_entry, data=user_input, options=self.config_entry.options
|
||||
)
|
||||
coordinator = self.hass.data[DOMAIN].get("coordinator")
|
||||
coordinator.update_interval = timedelta(seconds=self.config_entry.data.get(CONF_SCAN_INTERVAL))
|
||||
return self.async_create_entry(title=f"ECU: {ecu_id}", data={})
|
||||
else:
|
||||
errors["host"] = "no_ecuid"
|
||||
except APSystemsInvalidData as err:
|
||||
errors["host"] = "cannot_connect"
|
||||
except Exception as err:
|
||||
_LOGGER.debug(f"Unknown error occurred during setup: {err}")
|
||||
errors["host"] = "unknown"
|
||||
13
config/custom_components/apsystems_ecur/const.py
Normal file
13
config/custom_components/apsystems_ecur/const.py
Normal file
@@ -0,0 +1,13 @@
|
||||
DOMAIN = 'apsystems_ecur'
|
||||
SOLAR_ICON = "mdi:solar-power"
|
||||
FREQ_ICON = "mdi:sine-wave"
|
||||
SIGNAL_ICON = "mdi:signal"
|
||||
RELOAD_ICON = "mdi:reload"
|
||||
CACHE_ICON = "mdi:cached"
|
||||
RESTART_ICON = "mdi:restart"
|
||||
POWER_ICON = "mdi:power"
|
||||
|
||||
CONF_SSID = "SSID"
|
||||
CONF_WPA_PSK = "WPA-PSK"
|
||||
CONF_CACHE = "CACHE"
|
||||
CONF_STOP_GRAPHS = "stop_graphs"
|
||||
30
config/custom_components/apsystems_ecur/diagnostics.py
Normal file
30
config/custom_components/apsystems_ecur/diagnostics.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
TO_REDACT = {CONF_TOKEN}
|
||||
|
||||
from .const import (
|
||||
DOMAIN
|
||||
)
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_get_device_diagnostics(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry, device: DeviceEntry
|
||||
) -> dict:
|
||||
"""Return diagnostics for a config entry."""
|
||||
|
||||
_LOGGER.debug("Diagnostics being called")
|
||||
|
||||
ecu = hass.data[DOMAIN].get("ecu")
|
||||
_LOGGER.debug(f"Diagnostics being called {ecu}")
|
||||
|
||||
diag_data = {"entry": async_redact_data(ecu.ecu.dump_data(), TO_REDACT)}
|
||||
|
||||
return diag_data
|
||||
14
config/custom_components/apsystems_ecur/manifest.json
Normal file
14
config/custom_components/apsystems_ecur/manifest.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"domain": "apsystems_ecur",
|
||||
"name": "APSystems PV solar ECU",
|
||||
"codeowners": ["@ksheumaker"],
|
||||
"config_flow": true,
|
||||
"dependencies": [],
|
||||
"documentation": "https://github.com/ksheumaker/homeassistant-apsystems_ecur",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_polling",
|
||||
"issue_tracker": "https://github.com/ksheumaker/homeassistant-apsystems_ecur/issues",
|
||||
"loggers": ["custom_components.apsystems_ecur"],
|
||||
"requirements": [],
|
||||
"version": "v1.4.3"
|
||||
}
|
||||
284
config/custom_components/apsystems_ecur/sensor.py
Normal file
284
config/custom_components/apsystems_ecur/sensor.py
Normal file
@@ -0,0 +1,284 @@
|
||||
from datetime import timedelta, datetime, date
|
||||
import logging
|
||||
|
||||
import async_timeout
|
||||
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.components.sensor import SensorEntity
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
)
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorStateClass,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
SOLAR_ICON,
|
||||
FREQ_ICON,
|
||||
SIGNAL_ICON
|
||||
)
|
||||
|
||||
from homeassistant.const import (
|
||||
UnitOfPower,
|
||||
UnitOfEnergy,
|
||||
UnitOfTemperature,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfFrequency,
|
||||
PERCENTAGE
|
||||
)
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_setup_entry(hass, config, add_entities, discovery_info=None):
|
||||
|
||||
ecu = hass.data[DOMAIN].get("ecu")
|
||||
coordinator = hass.data[DOMAIN].get("coordinator")
|
||||
|
||||
sensors = [
|
||||
APSystemsECUSensor(coordinator, ecu, "current_power",
|
||||
label="Current Power",
|
||||
unit=UnitOfPower.WATT,
|
||||
devclass=SensorDeviceClass.POWER,
|
||||
icon=SOLAR_ICON,
|
||||
stateclass=SensorStateClass.MEASUREMENT
|
||||
),
|
||||
APSystemsECUSensor(coordinator, ecu, "today_energy",
|
||||
label="Today Energy",
|
||||
unit=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
devclass=SensorDeviceClass.ENERGY,
|
||||
icon=SOLAR_ICON,
|
||||
stateclass=SensorStateClass.TOTAL_INCREASING
|
||||
),
|
||||
APSystemsECUSensor(coordinator, ecu, "lifetime_energy",
|
||||
label="Lifetime Energy",
|
||||
unit=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
devclass=SensorDeviceClass.ENERGY,
|
||||
icon=SOLAR_ICON,
|
||||
stateclass=SensorStateClass.TOTAL_INCREASING
|
||||
),
|
||||
APSystemsECUSensor(coordinator, ecu, "qty_of_inverters",
|
||||
label="Inverters",
|
||||
icon=SOLAR_ICON,
|
||||
entity_category=EntityCategory.DIAGNOSTIC
|
||||
),
|
||||
APSystemsECUSensor(coordinator, ecu, "qty_of_online_inverters",
|
||||
label="Inverters Online",
|
||||
icon=SOLAR_ICON,
|
||||
entity_category=EntityCategory.DIAGNOSTIC
|
||||
),
|
||||
]
|
||||
|
||||
inverters = coordinator.data.get("inverters", {})
|
||||
for uid,inv_data in inverters.items():
|
||||
_LOGGER.debug(f"Inverter {uid} {inv_data.get('channel_qty')}")
|
||||
# https://github.com/ksheumaker/homeassistant-apsystems_ecur/issues/110
|
||||
if inv_data.get("channel_qty") != None:
|
||||
sensors.extend([
|
||||
APSystemsECUInverterSensor(coordinator, ecu, uid, "temperature",
|
||||
label="Temperature",
|
||||
unit=UnitOfTemperature.CELSIUS,
|
||||
devclass=SensorDeviceClass.TEMPERATURE,
|
||||
stateclass=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC
|
||||
),
|
||||
APSystemsECUInverterSensor(coordinator, ecu, uid, "frequency",
|
||||
label="Frequency",
|
||||
unit=UnitOfFrequency.HERTZ,
|
||||
stateclass=SensorStateClass.MEASUREMENT,
|
||||
devclass=SensorDeviceClass.FREQUENCY,
|
||||
icon=FREQ_ICON,
|
||||
entity_category=EntityCategory.DIAGNOSTIC
|
||||
),
|
||||
APSystemsECUInverterSensor(coordinator, ecu, uid, "voltage",
|
||||
label="Voltage",
|
||||
unit=UnitOfElectricPotential.VOLT,
|
||||
stateclass=SensorStateClass.MEASUREMENT,
|
||||
devclass=SensorDeviceClass.VOLTAGE, entity_category=EntityCategory.DIAGNOSTIC
|
||||
),
|
||||
APSystemsECUInverterSensor(coordinator, ecu, uid, "signal",
|
||||
label="Signal",
|
||||
unit=PERCENTAGE,
|
||||
stateclass=SensorStateClass.MEASUREMENT,
|
||||
devclass=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||
icon=SIGNAL_ICON,
|
||||
entity_category=EntityCategory.DIAGNOSTIC
|
||||
)
|
||||
])
|
||||
for i in range(0, inv_data.get("channel_qty", 0)):
|
||||
sensors.append(
|
||||
APSystemsECUInverterSensor(coordinator, ecu, uid, f"power",
|
||||
index=i, label=f"Power Ch {i+1}",
|
||||
unit=UnitOfPower.WATT,
|
||||
devclass=SensorDeviceClass.POWER,
|
||||
icon=SOLAR_ICON,
|
||||
stateclass=SensorStateClass.MEASUREMENT
|
||||
)
|
||||
)
|
||||
add_entities(sensors)
|
||||
|
||||
|
||||
class APSystemsECUInverterSensor(CoordinatorEntity, SensorEntity):
|
||||
def __init__(self, coordinator, ecu, uid, field, index=0, label=None, icon=None, unit=None, devclass=None, stateclass=None, entity_category=None):
|
||||
|
||||
super().__init__(coordinator)
|
||||
|
||||
self.coordinator = coordinator
|
||||
|
||||
self._index = index
|
||||
self._uid = uid
|
||||
self._ecu = ecu
|
||||
self._field = field
|
||||
self._devclass = devclass
|
||||
self._label = label
|
||||
if not label:
|
||||
self._label = field
|
||||
self._icon = icon
|
||||
self._unit = unit
|
||||
self._stateclass = stateclass
|
||||
self._entity_category = entity_category
|
||||
|
||||
self._name = f"Inverter {self._uid} {self._label}"
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
field = self._field
|
||||
if self._index != None:
|
||||
field = f"{field}_{self._index}"
|
||||
return f"{self._ecu.ecu.ecu_id}_{self._uid}_{field}"
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
return self._devclass
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
_LOGGER.debug(f"State called for {self._field}")
|
||||
if self._field == "voltage":
|
||||
return self.coordinator.data.get("inverters", {}).get(self._uid, {}).get("voltage", [])[0]
|
||||
elif self._field == "power":
|
||||
_LOGGER.debug(f"POWER {self._uid} {self._index}")
|
||||
return self.coordinator.data.get("inverters", {}).get(self._uid, {}).get("power", [])[self._index]
|
||||
else:
|
||||
return self.coordinator.data.get("inverters", {}).get(self._uid, {}).get(self._field)
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
return self._unit
|
||||
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
attrs = {
|
||||
"ecu_id" : self._ecu.ecu.ecu_id,
|
||||
"inverter_uid" : self._uid,
|
||||
"last_update" : self._ecu.ecu.last_update,
|
||||
}
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def state_class(self):
|
||||
_LOGGER.debug(f"State class {self._stateclass} - {self._field}")
|
||||
return self._stateclass
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
parent = f"inverter_{self._uid}"
|
||||
return {
|
||||
"identifiers": {
|
||||
(DOMAIN, parent),
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
return self._entity_category
|
||||
|
||||
class APSystemsECUSensor(CoordinatorEntity, SensorEntity):
|
||||
|
||||
def __init__(self, coordinator, ecu, field, label=None, icon=None, unit=None, devclass=None, stateclass=None, entity_category=None):
|
||||
|
||||
super().__init__(coordinator)
|
||||
|
||||
self.coordinator = coordinator
|
||||
|
||||
self._ecu = ecu
|
||||
self._field = field
|
||||
self._label = label
|
||||
if not label:
|
||||
self._label = field
|
||||
self._icon = icon
|
||||
self._unit = unit
|
||||
self._devclass = devclass
|
||||
self._stateclass = stateclass
|
||||
self._entity_category = entity_category
|
||||
|
||||
self._name = f"ECU {self._label}"
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return f"{self._ecu.ecu.ecu_id}_{self._field}"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
return self._devclass
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
_LOGGER.debug(f"State called for {self._field}")
|
||||
return self.coordinator.data.get(self._field)
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
return self._unit
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
|
||||
attrs = {
|
||||
"ecu_id" : self._ecu.ecu.ecu_id,
|
||||
"Firmware" : self._ecu.ecu.firmware,
|
||||
"Timezone" : self._ecu.ecu.timezone,
|
||||
"last_update" : self._ecu.ecu.last_update
|
||||
}
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def state_class(self):
|
||||
_LOGGER.debug(f"State class {self._stateclass} - {self._field}")
|
||||
return self._stateclass
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
parent = f"ecu_{self._ecu.ecu.ecu_id}"
|
||||
return {
|
||||
"identifiers": {
|
||||
(DOMAIN, parent),
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
return self._entity_category
|
||||
132
config/custom_components/apsystems_ecur/switch.py
Normal file
132
config/custom_components/apsystems_ecur/switch.py
Normal file
@@ -0,0 +1,132 @@
|
||||
import logging
|
||||
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity
|
||||
)
|
||||
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
RELOAD_ICON,
|
||||
POWER_ICON
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_setup_entry(hass, config, add_entities, discovery_info=None):
|
||||
|
||||
ecu = hass.data[DOMAIN].get("ecu")
|
||||
coordinator = hass.data[DOMAIN].get("coordinator")
|
||||
switches = [
|
||||
APSystemsECUQuerySwitch(coordinator, ecu, "query_device",
|
||||
label="Query Device", icon=RELOAD_ICON),
|
||||
APSystemsECUInvertersSwitch(coordinator, ecu, "inverters_online",
|
||||
label="Inverters Online", icon=POWER_ICON),
|
||||
]
|
||||
add_entities(switches)
|
||||
|
||||
class APSystemsECUQuerySwitch(CoordinatorEntity, SwitchEntity):
|
||||
def __init__(self, coordinator, ecu, field, label=None, icon=None):
|
||||
super().__init__(coordinator)
|
||||
self.coordinator = coordinator
|
||||
self._ecu = ecu
|
||||
self._field = field
|
||||
self._label = label
|
||||
if not label:
|
||||
self._label = field
|
||||
self._icon = icon
|
||||
self._name = f"ECU {self._label}"
|
||||
self._state = True
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return f"{self._ecu.ecu.ecu_id}_{self._field}"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
parent = f"ecu_{self._ecu.ecu.ecu_id}"
|
||||
return {
|
||||
"identifiers": {
|
||||
(DOMAIN, parent),
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
return EntityCategory.CONFIG
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
return self._ecu.querying
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
self._ecu.stop_query()
|
||||
self._state = False
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
self._ecu.start_query()
|
||||
self._state = True
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
class APSystemsECUInvertersSwitch(CoordinatorEntity, SwitchEntity):
|
||||
def __init__(self, coordinator, ecu, field, label=None, icon=None):
|
||||
super().__init__(coordinator)
|
||||
self.coordinator = coordinator
|
||||
self._ecu = ecu
|
||||
self._field = field
|
||||
self._label = label
|
||||
if not label:
|
||||
self._label = field
|
||||
self._icon = icon
|
||||
self._name = f"ECU {self._label}"
|
||||
self._state = True
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return f"{self._ecu.ecu.ecu_id}_{self._field}"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
parent = f"ecu_{self._ecu.ecu.ecu_id}"
|
||||
return {
|
||||
"identifiers": {
|
||||
(DOMAIN, parent),
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
return EntityCategory.CONFIG
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
return self._ecu.inverters_online
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
self._ecu.inverters_off()
|
||||
self._state = False
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
self._ecu.inverters_on()
|
||||
self._state = True
|
||||
self.schedule_update_ha_state()
|
||||
48
config/custom_components/apsystems_ecur/translations/de.json
Normal file
48
config/custom_components/apsystems_ecur/translations/de.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"host": "ECU IP-Adresse (bitte Verbindungstabelle in der readme prüfen).",
|
||||
"scan_interval": "ECU Abfrage Frequenz in Sekunden (minimum 300 empfohlen).",
|
||||
"CACHE": "Wiederholungen, wenn ECU ausfällt (Bereich zwischen 1 - 5 empfohlen)",
|
||||
"SSID": "SSID angeben (nur für Modelle ECU-R (sunspec) und ECU-C)",
|
||||
"WPA-PSK": "Kennwort angeben (nur für Modelle ECU-R (sunspec) und ECU-C)",
|
||||
"stop_graphs": "Aktualisieren die Diagramme nicht, wenn die Wechselrichter offline sind"
|
||||
},
|
||||
"title": "APsystems ECU Konfiguration"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Es wurde keine ECU unter dieser IP-Adresse gefunden oder life-time energy ist Null.",
|
||||
"no_ecuid": "Es wurde keine ECU ID von der ECU zurückgegeben.",
|
||||
"unknown": "Unbekannter Fehler, bitte Logs überprüfen."
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "ECU IP-Adresse (bitte Verbindungstabelle in der readme prüfen).",
|
||||
"scan_interval": "ECU Abfrage Frequenz in Sekunden (minimum 300 empfohlen).",
|
||||
"CACHE": "Wiederholungen, wenn ECU ausfällt (Bereich zwischen 1 - 5 empfohlen)",
|
||||
"SSID": "SSID angeben (nur für Modelle ECU-R (sunspec) und ECU-C)",
|
||||
"WPA-PSK": "Kennwort angeben (nur für Modelle ECU-R (sunspec) und ECU-C)",
|
||||
"stop_graphs": "Aktualisieren die Diagramme nicht, wenn die Wechselrichter offline sind"
|
||||
},
|
||||
"title": "APsystems ECU Optionen"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Es wurde keine ECU unter dieser IP-Adresse gefunden oder life-time energy ist Null.",
|
||||
"no_ecuid": "Es wurde keine ECU ID von der ECU zurückgegeben.",
|
||||
"unknown": "Unbekannter Fehler, bitte Logs überprüfen."
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
config/custom_components/apsystems_ecur/translations/en.json
Normal file
48
config/custom_components/apsystems_ecur/translations/en.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"host": "ECU IP address (follow connection method table in readme)",
|
||||
"scan_interval": "ECU query interval in seconds (minimum 300 recommended)",
|
||||
"CACHE": "Retries when ECU fails (range between 1 - 5 recommended)",
|
||||
"SSID": "Specify SSID (For ECU-R (sunspec) and ECU-C models only)",
|
||||
"WPA-PSK": "Specify password (For ECU-R (sunspec) and ECU-C models only)",
|
||||
"stop_graphs": "Do not update graphs when inverters are offline"
|
||||
},
|
||||
"title": "APsystems ECU Config"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Can't find ECU at this IP-Address or life-time energy is zero",
|
||||
"no_ecuid": "No ECU ID returned from ECU",
|
||||
"unknown": "Unknown error, see log for details"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "ECU IP address (follow connection method table in readme)",
|
||||
"scan_interval": "ECU query interval in seconds (minimum 300 recommended)",
|
||||
"CACHE": "Retries when ECU fails (range between 1 - 5 recommended)",
|
||||
"SSID": "Specify SSID (For ECU-R (sunspec) and ECU-C models only)",
|
||||
"WPA-PSK": "Specify password (For ECU-R (sunspec) and ECU-C models only)",
|
||||
"stop_graphs": "Do not update graphs when inverters are offline"
|
||||
},
|
||||
"title": "APsystems ECU Options"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Can't find ECU at this IP-Address or life-time energy is zero",
|
||||
"no_ecuid": "No ECU ID returned from ECU",
|
||||
"unknown": "Unknown error, see log for details"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
config/custom_components/apsystems_ecur/translations/es.json
Normal file
48
config/custom_components/apsystems_ecur/translations/es.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"host": "Dirección IP de la ECU (Sigue el método para conectarse en la tabla del archivo readme)",
|
||||
"scan_interval": "Intervalo de conexión a la ECU en segundos (Mínimo 300 recomendado)",
|
||||
"CACHE": "Reintentos cuando la ECU falla (Rango entre 1 - 5 recomendado)",
|
||||
"SSID": "Introduce SSID (Solo para modelos ECU-R (sunspec) and ECU-C)",
|
||||
"WPA-PSK": "Introduce contraseña (Solo para modelos ECU-R (sunspec) and ECU-C)",
|
||||
"stop_graphs": "No actualice los gráficos cuando los inversores estén fuera de línea"
|
||||
},
|
||||
"title": "Configuración APsystems ECU"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "No puedo encontrar la ECU en esta dirección IP o la energía life-time es cero",
|
||||
"no_ecuid": "La ECU no ha devuelto ningún ECU ID",
|
||||
"unknown": "Error desconocido, lee el log para mas detalles"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Dirección IP de la ECU (Sigue el método para conectarse en la tabla del archivo readme)",
|
||||
"scan_interval": "Intervalo de conexión a la ECU en segundos (Mínimo 300 recomendado)",
|
||||
"CACHE": "Reintentos cuando la ECU falla (Rango entre 1 - 5 recomendado)",
|
||||
"SSID": "Introduce SSID (Solo para modelos ECU-R (sunspec) and ECU-C)",
|
||||
"WPA-PSK": "Introduce contraseña (Solo para modelos ECU-R (sunspec) and ECU-C)",
|
||||
"stop_graphs": "No actualice los gráficos cuando los inversores estén fuera de línea"
|
||||
},
|
||||
"title": "Configuración APsystems ECU"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "No puedo encontrar la ECU en esta dirección IP o la energía life-time es cero",
|
||||
"no_ecuid": "La ECU no ha devuelto ningún ECU ID",
|
||||
"unknown": "Error desconocido, lee el log para mas detalles"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
49
config/custom_components/apsystems_ecur/translations/fr.json
Normal file
49
config/custom_components/apsystems_ecur/translations/fr.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"host": "Adresse IP ECU (Voir “Prerequisites” dans le fichier Readme)",
|
||||
"scan_interval": "Intervalle des requêtes sur l'ECU en secondes (Min de 300 recommandées)",
|
||||
"CACHE": "Nombre de tentatives en cas d'échec de communication (1 à 5 recommandée)",
|
||||
"SSID": "Spécifier le SSID (Pour ECU-R (Sunspec) et ECU-C seulement)",
|
||||
"WPA-PSK": "Spécifier le mot de passe (Pour ECU-R (Sunspec) et ECU-C seulement)",
|
||||
"stop_graphs": "Ne pas mettre à jour les graphiques lorsque les onduleurs sont hors ligne"
|
||||
},
|
||||
"title": "Configuration ECU APsystems"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ne trouve pas d'ECU à cette adresse IP ou énergie totale produite nulle",
|
||||
"no_ecuid": "Pas d'ID ECU retourné pour cet ECU",
|
||||
"unknown": "Erreur inconnue, veuillez consulter le journal des logs pour plus de détails"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Adresse IP ECU (Voir “Prerequisites” dans le fichier Readme)",
|
||||
"scan_interval": "Intervalle des requêtes sur l'ECU en secondes (Min de 300 recommandées)",
|
||||
"CACHE": "Nombre de tentatives en cas d'échec de communication (1 à 5 recommandée)",
|
||||
"SSID": "Spécifier le SSID (Pour ECU-R (Sunspec) et ECU-C seulement)",
|
||||
"WPA-PSK": "Spécifier le mot de passe (Pour ECU-R (Sunspec) et ECU-C seulement)",
|
||||
"stop_graphs": "Ne pas mettre à jour les graphiques lorsque les onduleurs sont hors ligne"
|
||||
},
|
||||
"title": "Options ECU APsystems"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ne trouve pas d'ECU à cette adresse IP ou énergie totale produite nulle",
|
||||
"inverter": "Type d'onduleur inconnu, veuillez vérifier les journaux",
|
||||
"no_ecuid": "Pas d'ID ECU retourné pour cet ECU",
|
||||
"unknown": "Erreur inconnue, veuillez consulter le journal des logs pour plus de détails"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
config/custom_components/apsystems_ecur/translations/nl.json
Normal file
48
config/custom_components/apsystems_ecur/translations/nl.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"host": "ECU IP-adres (volg de connectie methode tabel in de readme)",
|
||||
"scan_interval": "ECU query interval in seconden (minimum 300 aanbevolen)",
|
||||
"CACHE": "Pogingen als de ECU niet reageert (tussen 1 - 5 aanbevolen)",
|
||||
"SSID": "Specificeer SSID (Alleen voor ECU-R (sunspec) en ECU-C modellen)",
|
||||
"WPA-PSK": "Specificeer wachtwoord (voor ECU-R (sunspec) en ECU-C modellen)",
|
||||
"stop_graphs": "Werk grafieken niet bij als de omvormers offline zijn"
|
||||
},
|
||||
"title": "APsystems ECU Configuratie"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Kan de ECU niet vinden op dit IP-adres of life-time energy is nul",
|
||||
"no_ecuid": "Geen ECU ID ontvangen",
|
||||
"unknown": "Onbekende fout, zie het log for details"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "ECU IP-adres (volg de connectie methode tabel in de readme)",
|
||||
"scan_interval": "ECU query interval in seconden (minimum 300 aanbevolen)",
|
||||
"CACHE": "Pogingen als de ECU niet reageert (tussen 1 - 5 aanbevolen)",
|
||||
"SSID": "Specificeer SSID (Alleen voor ECU-R (sunspec) en ECU-C modellen)",
|
||||
"WPA-PSK": "Specificeer wachtwoord (voor ECU-R (sunspec) en ECU-C modellen)",
|
||||
"stop_graphs": "Werk grafieken niet bij als de omvormers offline zijn"
|
||||
},
|
||||
"title": "APsystems ECU Opties"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Kan de ECU niet vinden op dit IP-adres of life-time energy is nul",
|
||||
"no_ecuid": "Geen ECU ID ontvangen",
|
||||
"unknown": "Onbekende fout, zie het log voor details"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
config/custom_components/average/__init__.py
Normal file
48
config/custom_components/average/__init__.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2019-2022, Andrey "Limych" Khrolenok <andrey@khrolenok.ru>
|
||||
# Creative Commons BY-NC-SA 4.0 International Public License
|
||||
# (see LICENSE.md or https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
||||
|
||||
"""
|
||||
The Average Sensor.
|
||||
|
||||
For more details about this sensor, please refer to the documentation at
|
||||
https://github.com/Limych/ha-average/
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
from homeassistant.const import SERVICE_RELOAD
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.reload import async_reload_integration_platforms
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import DOMAIN, PLATFORMS, STARTUP_MESSAGE
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the platforms."""
|
||||
# Print startup message
|
||||
_LOGGER.info(STARTUP_MESSAGE)
|
||||
|
||||
# await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
|
||||
|
||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||
|
||||
async def reload_service_handler(service: ServiceCall) -> None:
|
||||
"""Reload all average sensors from config."""
|
||||
print("+++++++++++++++++++++++++")
|
||||
print(component)
|
||||
# print(hass.data[DATA_INSTANCES]["sensor"].entities[0])
|
||||
|
||||
await async_reload_integration_platforms(hass, DOMAIN, PLATFORMS)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=vol.Schema({})
|
||||
)
|
||||
|
||||
return True
|
||||
65
config/custom_components/average/const.py
Normal file
65
config/custom_components/average/const.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""The Average Sensor.
|
||||
|
||||
For more details about this sensor, please refer to the documentation at
|
||||
https://github.com/Limych/ha-average/
|
||||
"""
|
||||
from datetime import timedelta
|
||||
from typing import Final
|
||||
|
||||
# Base component constants
|
||||
from homeassistant.const import Platform
|
||||
|
||||
NAME: Final = "Average Sensor"
|
||||
DOMAIN: Final = "average"
|
||||
VERSION: Final = "2.3.4"
|
||||
ISSUE_URL: Final = "https://github.com/Limych/ha-average/issues"
|
||||
|
||||
STARTUP_MESSAGE: Final = f"""
|
||||
-------------------------------------------------------------------
|
||||
{NAME}
|
||||
Version: {VERSION}
|
||||
This is a custom integration!
|
||||
If you have ANY issues with this you need to open an issue here:
|
||||
{ISSUE_URL}
|
||||
-------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
PLATFORMS = [
|
||||
Platform.SENSOR,
|
||||
]
|
||||
|
||||
# Configuration and options
|
||||
CONF_START: Final = "start"
|
||||
CONF_END: Final = "end"
|
||||
CONF_DURATION: Final = "duration"
|
||||
CONF_PRECISION: Final = "precision"
|
||||
CONF_PERIOD_KEYS: Final = [CONF_START, CONF_END, CONF_DURATION]
|
||||
CONF_PROCESS_UNDEF_AS: Final = "process_undef_as"
|
||||
|
||||
# Defaults
|
||||
DEFAULT_NAME: Final = "Average"
|
||||
DEFAULT_PRECISION: Final = 2
|
||||
|
||||
# Attributes
|
||||
ATTR_START: Final = "start"
|
||||
ATTR_END: Final = "end"
|
||||
ATTR_SOURCES: Final = "sources"
|
||||
ATTR_COUNT_SOURCES: Final = "count_sources"
|
||||
ATTR_AVAILABLE_SOURCES: Final = "available_sources"
|
||||
ATTR_COUNT: Final = "count"
|
||||
ATTR_MIN_VALUE: Final = "min_value"
|
||||
ATTR_MAX_VALUE: Final = "max_value"
|
||||
#
|
||||
ATTR_TO_PROPERTY: Final = [
|
||||
ATTR_START,
|
||||
ATTR_END,
|
||||
ATTR_SOURCES,
|
||||
ATTR_COUNT_SOURCES,
|
||||
ATTR_AVAILABLE_SOURCES,
|
||||
ATTR_COUNT,
|
||||
ATTR_MAX_VALUE,
|
||||
ATTR_MIN_VALUE,
|
||||
]
|
||||
|
||||
|
||||
UPDATE_MIN_TIME: Final = timedelta(seconds=20)
|
||||
19
config/custom_components/average/manifest.json
Normal file
19
config/custom_components/average/manifest.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"domain": "average",
|
||||
"name": "Average Sensor",
|
||||
"after_dependencies": [
|
||||
"history",
|
||||
"recorder",
|
||||
"weather"
|
||||
],
|
||||
"codeowners": [
|
||||
"@Limych"
|
||||
],
|
||||
"config_flow": false,
|
||||
"dependencies": [],
|
||||
"documentation": "https://github.com/Limych/ha-average",
|
||||
"iot_class": "calculated",
|
||||
"issue_tracker": "https://github.com/Limych/ha-average/issues",
|
||||
"requirements": [],
|
||||
"version": "2.3.4"
|
||||
}
|
||||
561
config/custom_components/average/sensor.py
Normal file
561
config/custom_components/average/sensor.py
Normal file
@@ -0,0 +1,561 @@
|
||||
# Copyright (c) 2019-2022, Andrey "Limych" Khrolenok <andrey@khrolenok.ru>
|
||||
# Creative Commons BY-NC-SA 4.0 International Public License
|
||||
# (see LICENSE.md or https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
||||
|
||||
"""The Average Sensor.
|
||||
|
||||
For more details about this sensor, please refer to the documentation at
|
||||
https://github.com/Limych/ha-average/
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
import datetime
|
||||
import logging
|
||||
import math
|
||||
import numbers
|
||||
from typing import Any, Optional
|
||||
|
||||
from _sha1 import sha1
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
|
||||
from homeassistant.components.group import expand_entity_ids
|
||||
from homeassistant.components.recorder import get_instance, history
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.components.water_heater import DOMAIN as WATER_HEATER_DOMAIN
|
||||
from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ICON,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_ENTITIES,
|
||||
CONF_NAME,
|
||||
CONF_UNIQUE_ID,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, State, callback, split_entity_id
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
from homeassistant.util import Throttle
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.unit_conversion import TemperatureConverter
|
||||
from homeassistant.util.unit_system import TEMPERATURE_UNITS
|
||||
|
||||
from .const import (
|
||||
ATTR_AVAILABLE_SOURCES,
|
||||
ATTR_COUNT,
|
||||
ATTR_COUNT_SOURCES,
|
||||
ATTR_END,
|
||||
ATTR_MAX_VALUE,
|
||||
ATTR_MIN_VALUE,
|
||||
ATTR_START,
|
||||
ATTR_TO_PROPERTY,
|
||||
CONF_DURATION,
|
||||
CONF_END,
|
||||
CONF_PERIOD_KEYS,
|
||||
CONF_PRECISION,
|
||||
CONF_PROCESS_UNDEF_AS,
|
||||
CONF_START,
|
||||
DEFAULT_NAME,
|
||||
DEFAULT_PRECISION,
|
||||
UPDATE_MIN_TIME,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_period_keys(conf):
|
||||
"""Ensure maximum 2 of CONF_PERIOD_KEYS are provided."""
|
||||
count = sum(param in conf for param in CONF_PERIOD_KEYS)
|
||||
if (count == 1 and CONF_DURATION not in conf) or count > 2:
|
||||
raise vol.Invalid(
|
||||
"You must provide none, only "
|
||||
+ CONF_DURATION
|
||||
+ " or maximum 2 of the following: "
|
||||
", ".join(CONF_PERIOD_KEYS)
|
||||
)
|
||||
return conf
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(
|
||||
PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_ENTITIES): cv.entity_ids,
|
||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_START): cv.template,
|
||||
vol.Optional(CONF_END): cv.template,
|
||||
vol.Optional(CONF_DURATION): cv.positive_time_period,
|
||||
vol.Optional(CONF_PRECISION, default=DEFAULT_PRECISION): int,
|
||||
vol.Optional(CONF_PROCESS_UNDEF_AS): vol.Any(int, float),
|
||||
}
|
||||
),
|
||||
check_period_keys,
|
||||
)
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant, config, async_add_entities, discovery_info=None
|
||||
):
|
||||
"""Set up platform."""
|
||||
start = config.get(CONF_START)
|
||||
end = config.get(CONF_END)
|
||||
|
||||
for template in [start, end]:
|
||||
if template is not None:
|
||||
template.hass = hass
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
AverageSensor(
|
||||
hass,
|
||||
config.get(CONF_UNIQUE_ID),
|
||||
config.get(CONF_NAME),
|
||||
start,
|
||||
end,
|
||||
config.get(CONF_DURATION),
|
||||
config.get(CONF_ENTITIES),
|
||||
config.get(CONF_PRECISION),
|
||||
config.get(CONF_PROCESS_UNDEF_AS),
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
class AverageSensor(SensorEntity):
|
||||
"""Implementation of an Average sensor."""
|
||||
|
||||
_unrecorded_attributes = frozenset(
|
||||
{
|
||||
ATTR_START,
|
||||
ATTR_END,
|
||||
ATTR_COUNT_SOURCES,
|
||||
ATTR_AVAILABLE_SOURCES,
|
||||
ATTR_COUNT,
|
||||
ATTR_MAX_VALUE,
|
||||
ATTR_MIN_VALUE,
|
||||
}
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
unique_id: Optional[str],
|
||||
name: str,
|
||||
start,
|
||||
end,
|
||||
duration,
|
||||
entity_ids: list,
|
||||
precision: int,
|
||||
undef,
|
||||
):
|
||||
"""Initialize the sensor."""
|
||||
self._start_template = start
|
||||
self._end_template = end
|
||||
self._duration = duration
|
||||
self._period = self.start = self.end = None
|
||||
self._precision = precision
|
||||
self._undef = undef
|
||||
self._temperature_mode = None
|
||||
|
||||
self.sources = expand_entity_ids(hass, entity_ids)
|
||||
self.count_sources = len(self.sources)
|
||||
self.available_sources = 0
|
||||
self.count = 0
|
||||
self.min_value = self.max_value = None
|
||||
|
||||
self._attr_name = name
|
||||
self._attr_native_value = None
|
||||
self._attr_native_unit_of_measurement = None
|
||||
self._attr_icon = None
|
||||
self._attr_state_class = SensorStateClass.MEASUREMENT
|
||||
self._attr_device_class = None
|
||||
#
|
||||
self._attr_unique_id = (
|
||||
str(
|
||||
sha1(
|
||||
";".join(
|
||||
[str(start), str(duration), str(end), ",".join(self.sources)]
|
||||
).encode("utf-8")
|
||||
).hexdigest()
|
||||
)
|
||||
if unique_id == "__legacy__"
|
||||
else unique_id
|
||||
)
|
||||
|
||||
@property
|
||||
def _has_period(self) -> bool:
|
||||
"""Return True if sensor has any period setting."""
|
||||
return (
|
||||
self._start_template is not None
|
||||
or self._end_template is not None
|
||||
or self._duration is not None
|
||||
)
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
"""Return the polling state."""
|
||||
return self._has_period
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return self.available_sources > 0 and self._has_state(self._attr_native_value)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Optional[Mapping[str, Any]]:
|
||||
"""Return entity specific state attributes."""
|
||||
state_attr = {
|
||||
attr: getattr(self, attr)
|
||||
for attr in ATTR_TO_PROPERTY
|
||||
if getattr(self, attr) is not None
|
||||
}
|
||||
return state_attr
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@callback
|
||||
async def async_sensor_state_listener(entity, old_state, new_state):
|
||||
"""Handle device state changes."""
|
||||
last_state = self._attr_native_value
|
||||
await self._async_update_state()
|
||||
if last_state != self._attr_native_value:
|
||||
self.async_schedule_update_ha_state(True)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@callback
|
||||
async def async_sensor_startup(event):
|
||||
"""Update template on startup."""
|
||||
if self._has_period:
|
||||
self.async_schedule_update_ha_state(True)
|
||||
else:
|
||||
async_track_state_change(
|
||||
self.hass, self.sources, async_sensor_state_listener
|
||||
)
|
||||
await async_sensor_state_listener(None, None, None)
|
||||
|
||||
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, async_sensor_startup)
|
||||
|
||||
@staticmethod
|
||||
def _has_state(state) -> bool:
|
||||
"""Return True if state has any value."""
|
||||
return state is not None and state not in [
|
||||
STATE_UNKNOWN,
|
||||
STATE_UNAVAILABLE,
|
||||
"None",
|
||||
"",
|
||||
]
|
||||
|
||||
def _get_temperature(self, state: State) -> Optional[float]:
|
||||
"""Get temperature value from entity."""
|
||||
ha_unit = self.hass.config.units.temperature_unit
|
||||
domain = split_entity_id(state.entity_id)[0]
|
||||
if domain == WEATHER_DOMAIN:
|
||||
temperature = state.attributes.get("temperature")
|
||||
entity_unit = ha_unit
|
||||
elif domain in (CLIMATE_DOMAIN, WATER_HEATER_DOMAIN):
|
||||
temperature = state.attributes.get("current_temperature")
|
||||
entity_unit = ha_unit
|
||||
else:
|
||||
temperature = state.state
|
||||
entity_unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
|
||||
if not self._has_state(temperature):
|
||||
return None
|
||||
|
||||
try:
|
||||
temperature = TemperatureConverter.convert(
|
||||
float(temperature), entity_unit, ha_unit
|
||||
)
|
||||
except ValueError as exc:
|
||||
_LOGGER.error('Could not convert value "%s" to float: %s', state, exc)
|
||||
return None
|
||||
|
||||
return temperature
|
||||
|
||||
def _get_state_value(self, state: State) -> Optional[float]:
|
||||
"""Return value of given entity state and count some sensor attributes."""
|
||||
state = self._get_temperature(state) if self._temperature_mode else state.state
|
||||
if not self._has_state(state):
|
||||
return self._undef
|
||||
|
||||
try:
|
||||
state = float(state)
|
||||
except ValueError as exc:
|
||||
_LOGGER.error('Could not convert value "%s" to float: %s', state, exc)
|
||||
return None
|
||||
|
||||
self.count += 1
|
||||
rstate = round(state, self._precision)
|
||||
if self.min_value is None:
|
||||
self.min_value = self.max_value = rstate
|
||||
else:
|
||||
self.min_value = min(self.min_value, rstate)
|
||||
self.max_value = max(self.max_value, rstate)
|
||||
return state
|
||||
|
||||
@Throttle(UPDATE_MIN_TIME)
|
||||
async def async_update(self):
|
||||
"""Update the sensor state if it needed."""
|
||||
if self._has_period:
|
||||
await self._async_update_state()
|
||||
|
||||
@staticmethod
|
||||
def handle_template_exception(exc, field):
|
||||
"""Log an error nicely if the template cannot be interpreted."""
|
||||
if exc.args and exc.args[0].startswith(
|
||||
"UndefinedError: 'None' has no attribute"
|
||||
):
|
||||
# Common during HA startup - so just a warning
|
||||
_LOGGER.warning(exc)
|
||||
|
||||
else:
|
||||
_LOGGER.error('Error parsing template for field "%s": %s', field, exc)
|
||||
|
||||
async def _async_update_period(self): # pylint: disable=too-many-branches
|
||||
"""Parse the templates and calculate a datetime tuples."""
|
||||
start = end = None
|
||||
now = dt_util.now()
|
||||
|
||||
# Parse start
|
||||
if self._start_template is not None:
|
||||
_LOGGER.debug("Process start template: %s", self._start_template)
|
||||
try:
|
||||
start_rendered = self._start_template.async_render()
|
||||
except (TemplateError, TypeError) as ex:
|
||||
self.handle_template_exception(ex, "start")
|
||||
return
|
||||
if isinstance(start_rendered, str):
|
||||
start = dt_util.parse_datetime(start_rendered)
|
||||
if start is None:
|
||||
try:
|
||||
start = dt_util.as_local(
|
||||
dt_util.utc_from_timestamp(math.floor(float(start_rendered)))
|
||||
)
|
||||
except ValueError:
|
||||
_LOGGER.error(
|
||||
'Parsing error: field "start" must be a datetime or a timestamp'
|
||||
)
|
||||
return
|
||||
|
||||
# Parse end
|
||||
if self._end_template is not None:
|
||||
_LOGGER.debug("Process end template: %s", self._end_template)
|
||||
try:
|
||||
end_rendered = self._end_template.async_render()
|
||||
except (TemplateError, TypeError) as ex:
|
||||
self.handle_template_exception(ex, "end")
|
||||
return
|
||||
if isinstance(end_rendered, str):
|
||||
end = dt_util.parse_datetime(end_rendered)
|
||||
if end is None:
|
||||
try:
|
||||
end = dt_util.as_local(
|
||||
dt_util.utc_from_timestamp(math.floor(float(end_rendered)))
|
||||
)
|
||||
except ValueError:
|
||||
_LOGGER.error(
|
||||
'Parsing error: field "end" must be a datetime or a timestamp'
|
||||
)
|
||||
return
|
||||
|
||||
# Calculate start or end using the duration
|
||||
if self._duration is not None:
|
||||
_LOGGER.debug("Process duration: %s", self._duration)
|
||||
if start is None:
|
||||
if end is None:
|
||||
end = now
|
||||
start = end - self._duration
|
||||
else:
|
||||
end = start + self._duration
|
||||
|
||||
_LOGGER.debug("Calculation period: start=%s, end=%s", start, end)
|
||||
if start is None or end is None:
|
||||
return
|
||||
|
||||
if start > end:
|
||||
start, end = end, start
|
||||
|
||||
if start > now:
|
||||
# History hasn't been written yet for this period
|
||||
return
|
||||
end = min(end, now) # No point in making stats of the future
|
||||
|
||||
self._period = start, end
|
||||
self.start = start.replace(microsecond=0).isoformat()
|
||||
self.end = end.replace(microsecond=0).isoformat()
|
||||
|
||||
def _init_mode(self, state: State):
|
||||
"""Initialize sensor mode."""
|
||||
if self._temperature_mode is not None:
|
||||
return
|
||||
|
||||
domain = split_entity_id(state.entity_id)[0]
|
||||
self._attr_device_class = state.attributes.get(ATTR_DEVICE_CLASS)
|
||||
self._attr_native_unit_of_measurement = state.attributes.get(
|
||||
ATTR_UNIT_OF_MEASUREMENT
|
||||
)
|
||||
self._temperature_mode = (
|
||||
self._attr_device_class == SensorDeviceClass.TEMPERATURE
|
||||
or domain in (WEATHER_DOMAIN, CLIMATE_DOMAIN, WATER_HEATER_DOMAIN)
|
||||
or self._attr_native_unit_of_measurement in TEMPERATURE_UNITS
|
||||
)
|
||||
if self._temperature_mode:
|
||||
_LOGGER.debug("%s is a temperature entity.", state.entity_id)
|
||||
self._attr_device_class = SensorDeviceClass.TEMPERATURE
|
||||
self._attr_native_unit_of_measurement = (
|
||||
self.hass.config.units.temperature_unit
|
||||
)
|
||||
else:
|
||||
_LOGGER.debug("%s is NOT a temperature entity.", state.entity_id)
|
||||
self._attr_icon = state.attributes.get(ATTR_ICON)
|
||||
|
||||
async def _async_update_state(
|
||||
self,
|
||||
): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
||||
"""Update the sensor state."""
|
||||
_LOGGER.debug('Updating sensor "%s"', self.name)
|
||||
start = end = start_ts = end_ts = None
|
||||
p_period = self._period
|
||||
|
||||
# Parse templates
|
||||
await self._async_update_period()
|
||||
|
||||
if self._period is not None:
|
||||
now = datetime.datetime.now()
|
||||
start, end = self._period
|
||||
if p_period is None:
|
||||
p_start = p_end = now
|
||||
else:
|
||||
p_start, p_end = p_period
|
||||
|
||||
# Convert times to UTC
|
||||
start = dt_util.as_utc(start)
|
||||
end = dt_util.as_utc(end)
|
||||
p_start = dt_util.as_utc(p_start)
|
||||
p_end = dt_util.as_utc(p_end)
|
||||
|
||||
# Compute integer timestamps
|
||||
now_ts = math.floor(dt_util.as_timestamp(now))
|
||||
start_ts = math.floor(dt_util.as_timestamp(start))
|
||||
end_ts = math.floor(dt_util.as_timestamp(end))
|
||||
p_start_ts = math.floor(dt_util.as_timestamp(p_start))
|
||||
p_end_ts = math.floor(dt_util.as_timestamp(p_end))
|
||||
|
||||
# If period has not changed and current time after the period end..
|
||||
if start_ts == p_start_ts and end_ts == p_end_ts and end_ts <= now_ts:
|
||||
# Don't compute anything as the value cannot have changed
|
||||
return
|
||||
|
||||
self.available_sources = 0
|
||||
values = []
|
||||
self.count = 0
|
||||
self.min_value = self.max_value = None
|
||||
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
for entity_id in self.sources:
|
||||
_LOGGER.debug('Processing entity "%s"', entity_id)
|
||||
|
||||
state = self.hass.states.get(entity_id) # type: State
|
||||
|
||||
if state is None:
|
||||
_LOGGER.error('Unable to find an entity "%s"', entity_id)
|
||||
continue
|
||||
|
||||
self._init_mode(state)
|
||||
|
||||
value = 0
|
||||
elapsed = 0
|
||||
|
||||
if self._period is None:
|
||||
# Get current state
|
||||
value = self._get_state_value(state)
|
||||
_LOGGER.debug("Current state: %s", value)
|
||||
|
||||
else:
|
||||
# Get history between start and now
|
||||
history_list = await get_instance(self.hass).async_add_executor_job(
|
||||
history.state_changes_during_period,
|
||||
self.hass,
|
||||
start,
|
||||
end,
|
||||
str(entity_id),
|
||||
)
|
||||
|
||||
if (
|
||||
entity_id not in history_list.keys()
|
||||
or history_list[entity_id] is None
|
||||
or len(history_list[entity_id]) == 0
|
||||
):
|
||||
value = self._get_state_value(state)
|
||||
_LOGGER.warning(
|
||||
'Historical data not found for entity "%s". '
|
||||
"Current state used: %s",
|
||||
entity_id,
|
||||
value,
|
||||
)
|
||||
else:
|
||||
# Get the first state
|
||||
item = history_list[entity_id][0]
|
||||
_LOGGER.debug("Initial historical state: %s", item)
|
||||
last_state = None
|
||||
last_time = start_ts
|
||||
if item is not None and self._has_state(item.state):
|
||||
last_state = self._get_state_value(item)
|
||||
|
||||
# Get the other states
|
||||
for item in history_list.get(entity_id):
|
||||
_LOGGER.debug("Historical state: %s", item)
|
||||
current_state = self._get_state_value(item)
|
||||
current_time = item.last_changed.timestamp()
|
||||
|
||||
if last_state is not None:
|
||||
last_elapsed = current_time - last_time
|
||||
value += last_state * last_elapsed
|
||||
elapsed += last_elapsed
|
||||
|
||||
last_state = current_state
|
||||
last_time = current_time
|
||||
|
||||
# Count time elapsed between last history state and now
|
||||
if last_state is None:
|
||||
value = None
|
||||
else:
|
||||
last_elapsed = end_ts - last_time
|
||||
value += last_state * last_elapsed
|
||||
elapsed += last_elapsed
|
||||
if elapsed:
|
||||
value /= elapsed
|
||||
|
||||
_LOGGER.debug("Historical average state: %s", value)
|
||||
|
||||
if isinstance(value, numbers.Number):
|
||||
values.append(value)
|
||||
self.available_sources += 1
|
||||
|
||||
if values:
|
||||
self._attr_native_value = round(sum(values) / len(values), self._precision)
|
||||
if self._precision < 1:
|
||||
self._attr_native_value = int(self._attr_native_value)
|
||||
else:
|
||||
self._attr_native_value = None
|
||||
|
||||
_LOGGER.debug(
|
||||
"Total average state: %s %s",
|
||||
self._attr_native_value,
|
||||
self._attr_native_unit_of_measurement,
|
||||
)
|
||||
3
config/custom_components/average/services.yaml
Normal file
3
config/custom_components/average/services.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
reload:
|
||||
name: Reload
|
||||
description: Reload all average sensor entities
|
||||
294
config/custom_components/hacs/__init__.py
Normal file
294
config/custom_components/hacs/__init__.py
Normal file
@@ -0,0 +1,294 @@
|
||||
"""
|
||||
HACS gives you a powerful UI to handle downloads of all your custom needs.
|
||||
|
||||
For more details about this integration, please refer to the documentation at
|
||||
https://hacs.xyz/
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from aiogithubapi import AIOGitHubAPIException, GitHub, GitHubAPI
|
||||
from aiogithubapi.const import ACCEPT_HEADERS
|
||||
from awesomeversion import AwesomeVersion
|
||||
from homeassistant.components.lovelace.system_health import system_health_info
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import Platform, __version__ as HAVERSION
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.discovery import async_load_platform
|
||||
from homeassistant.helpers.event import async_call_later
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.start import async_at_start
|
||||
from homeassistant.loader import async_get_integration
|
||||
import voluptuous as vol
|
||||
|
||||
from .base import HacsBase
|
||||
from .const import DOMAIN, MINIMUM_HA_VERSION, STARTUP
|
||||
from .data_client import HacsDataClient
|
||||
from .enums import ConfigurationType, HacsDisabledReason, HacsStage, LovelaceMode
|
||||
from .frontend import async_register_frontend
|
||||
from .utils.configuration_schema import hacs_config_combined
|
||||
from .utils.data import HacsData
|
||||
from .utils.logger import LOGGER
|
||||
from .utils.queue_manager import QueueManager
|
||||
from .utils.version import version_left_higher_or_equal_then_right
|
||||
from .websocket import async_register_websocket_commands
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({DOMAIN: hacs_config_combined()}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
async def async_initialize_integration(
|
||||
hass: HomeAssistant,
|
||||
*,
|
||||
config_entry: ConfigEntry | None = None,
|
||||
config: dict[str, Any] | None = None,
|
||||
) -> bool:
|
||||
"""Initialize the integration"""
|
||||
hass.data[DOMAIN] = hacs = HacsBase()
|
||||
hacs.enable_hacs()
|
||||
|
||||
if config is not None:
|
||||
if DOMAIN not in config:
|
||||
return True
|
||||
if hacs.configuration.config_type == ConfigurationType.CONFIG_ENTRY:
|
||||
return True
|
||||
hacs.configuration.update_from_dict(
|
||||
{
|
||||
"config_type": ConfigurationType.YAML,
|
||||
**config[DOMAIN],
|
||||
"config": config[DOMAIN],
|
||||
}
|
||||
)
|
||||
|
||||
if config_entry is not None:
|
||||
if config_entry.source == SOURCE_IMPORT:
|
||||
hass.async_create_task(hass.config_entries.async_remove(config_entry.entry_id))
|
||||
return False
|
||||
|
||||
hacs.configuration.update_from_dict(
|
||||
{
|
||||
"config_entry": config_entry,
|
||||
"config_type": ConfigurationType.CONFIG_ENTRY,
|
||||
**config_entry.data,
|
||||
**config_entry.options,
|
||||
}
|
||||
)
|
||||
|
||||
integration = await async_get_integration(hass, DOMAIN)
|
||||
|
||||
hacs.set_stage(None)
|
||||
|
||||
hacs.log.info(STARTUP, integration.version)
|
||||
|
||||
clientsession = async_get_clientsession(hass)
|
||||
|
||||
hacs.integration = integration
|
||||
hacs.version = integration.version
|
||||
hacs.configuration.dev = integration.version == "0.0.0"
|
||||
hacs.hass = hass
|
||||
hacs.queue = QueueManager(hass=hass)
|
||||
hacs.data = HacsData(hacs=hacs)
|
||||
hacs.data_client = HacsDataClient(
|
||||
session=clientsession,
|
||||
client_name=f"HACS/{integration.version}",
|
||||
)
|
||||
hacs.system.running = True
|
||||
hacs.session = clientsession
|
||||
|
||||
hacs.core.lovelace_mode = LovelaceMode.YAML
|
||||
try:
|
||||
lovelace_info = await system_health_info(hacs.hass)
|
||||
hacs.core.lovelace_mode = LovelaceMode(lovelace_info.get("mode", "yaml"))
|
||||
except BaseException: # lgtm [py/catch-base-exception] pylint: disable=broad-except
|
||||
# If this happens, the users YAML is not valid, we assume YAML mode
|
||||
pass
|
||||
hacs.log.debug("Configuration type: %s", hacs.configuration.config_type)
|
||||
hacs.core.config_path = hacs.hass.config.path()
|
||||
|
||||
if hacs.core.ha_version is None:
|
||||
hacs.core.ha_version = AwesomeVersion(HAVERSION)
|
||||
|
||||
## Legacy GitHub client
|
||||
hacs.github = GitHub(
|
||||
hacs.configuration.token,
|
||||
clientsession,
|
||||
headers={
|
||||
"User-Agent": f"HACS/{hacs.version}",
|
||||
"Accept": ACCEPT_HEADERS["preview"],
|
||||
},
|
||||
)
|
||||
|
||||
## New GitHub client
|
||||
hacs.githubapi = GitHubAPI(
|
||||
token=hacs.configuration.token,
|
||||
session=clientsession,
|
||||
**{"client_name": f"HACS/{hacs.version}"},
|
||||
)
|
||||
|
||||
async def async_startup():
|
||||
"""HACS startup tasks."""
|
||||
hacs.enable_hacs()
|
||||
|
||||
for location in (
|
||||
hass.config.path("custom_components/custom_updater.py"),
|
||||
hass.config.path("custom_components/custom_updater/__init__.py"),
|
||||
):
|
||||
if os.path.exists(location):
|
||||
hacs.log.critical(
|
||||
"This cannot be used with custom_updater. "
|
||||
"To use this you need to remove custom_updater form %s",
|
||||
location,
|
||||
)
|
||||
|
||||
hacs.disable_hacs(HacsDisabledReason.CONSTRAINS)
|
||||
return False
|
||||
|
||||
if not version_left_higher_or_equal_then_right(
|
||||
hacs.core.ha_version.string,
|
||||
MINIMUM_HA_VERSION,
|
||||
):
|
||||
hacs.log.critical(
|
||||
"You need HA version %s or newer to use this integration.",
|
||||
MINIMUM_HA_VERSION,
|
||||
)
|
||||
hacs.disable_hacs(HacsDisabledReason.CONSTRAINS)
|
||||
return False
|
||||
|
||||
if not await hacs.data.restore():
|
||||
hacs.disable_hacs(HacsDisabledReason.RESTORE)
|
||||
return False
|
||||
|
||||
if not hacs.configuration.experimental:
|
||||
can_update = await hacs.async_can_update()
|
||||
hacs.log.debug("Can update %s repositories", can_update)
|
||||
|
||||
hacs.set_active_categories()
|
||||
|
||||
async_register_websocket_commands(hass)
|
||||
async_register_frontend(hass, hacs)
|
||||
|
||||
if hacs.configuration.config_type == ConfigurationType.YAML:
|
||||
hass.async_create_task(
|
||||
async_load_platform(hass, Platform.SENSOR, DOMAIN, {}, hacs.configuration.config)
|
||||
)
|
||||
hacs.log.info("Update entities are only supported when using UI configuration")
|
||||
|
||||
else:
|
||||
await hass.config_entries.async_forward_entry_setups(
|
||||
config_entry,
|
||||
[Platform.SENSOR, Platform.UPDATE]
|
||||
if hacs.configuration.experimental
|
||||
else [Platform.SENSOR],
|
||||
)
|
||||
|
||||
hacs.set_stage(HacsStage.SETUP)
|
||||
if hacs.system.disabled:
|
||||
return False
|
||||
|
||||
# Schedule startup tasks
|
||||
async_at_start(hass=hass, at_start_cb=hacs.startup_tasks)
|
||||
|
||||
hacs.set_stage(HacsStage.WAITING)
|
||||
hacs.log.info("Setup complete, waiting for Home Assistant before startup tasks starts")
|
||||
|
||||
return not hacs.system.disabled
|
||||
|
||||
async def async_try_startup(_=None):
|
||||
"""Startup wrapper for yaml config."""
|
||||
try:
|
||||
startup_result = await async_startup()
|
||||
except AIOGitHubAPIException:
|
||||
startup_result = False
|
||||
if not startup_result:
|
||||
if (
|
||||
hacs.configuration.config_type == ConfigurationType.YAML
|
||||
or hacs.system.disabled_reason != HacsDisabledReason.INVALID_TOKEN
|
||||
):
|
||||
hacs.log.info("Could not setup HACS, trying again in 15 min")
|
||||
async_call_later(hass, 900, async_try_startup)
|
||||
return
|
||||
hacs.enable_hacs()
|
||||
|
||||
await async_try_startup()
|
||||
|
||||
# Mischief managed!
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict[str, Any]) -> bool:
|
||||
"""Set up this integration using yaml."""
|
||||
if DOMAIN in config:
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"deprecated_yaml_configuration",
|
||||
is_fixable=False,
|
||||
issue_domain=DOMAIN,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_yaml_configuration",
|
||||
learn_more_url="https://hacs.xyz/docs/configuration/options",
|
||||
)
|
||||
LOGGER.warning(
|
||||
"YAML configuration of HACS is deprecated and will be "
|
||||
"removed in version 2.0.0, there will be no automatic "
|
||||
"import of this. "
|
||||
"Please remove it from your configuration, "
|
||||
"restart Home Assistant and use the UI to configure it instead."
|
||||
)
|
||||
return await async_initialize_integration(hass=hass, config=config)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Set up this integration using UI."""
|
||||
config_entry.async_on_unload(config_entry.add_update_listener(async_reload_entry))
|
||||
setup_result = await async_initialize_integration(hass=hass, config_entry=config_entry)
|
||||
hacs: HacsBase = hass.data[DOMAIN]
|
||||
return setup_result and not hacs.system.disabled
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Handle removal of an entry."""
|
||||
hacs: HacsBase = hass.data[DOMAIN]
|
||||
|
||||
if hacs.queue.has_pending_tasks:
|
||||
hacs.log.warning("Pending tasks, can not unload, try again later.")
|
||||
return False
|
||||
|
||||
# Clear out pending queue
|
||||
hacs.queue.clear()
|
||||
|
||||
for task in hacs.recuring_tasks:
|
||||
# Cancel all pending tasks
|
||||
task()
|
||||
|
||||
# Store data
|
||||
await hacs.data.async_write(force=True)
|
||||
|
||||
try:
|
||||
if hass.data.get("frontend_panels", {}).get("hacs"):
|
||||
hacs.log.info("Removing sidepanel")
|
||||
hass.components.frontend.async_remove_panel("hacs")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
platforms = ["sensor"]
|
||||
if hacs.configuration.experimental:
|
||||
platforms.append("update")
|
||||
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(config_entry, platforms)
|
||||
|
||||
hacs.set_stage(None)
|
||||
hacs.disable_hacs(HacsDisabledReason.REMOVED)
|
||||
|
||||
hass.data.pop(DOMAIN, None)
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
||||
async def async_reload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
||||
"""Reload the HACS config entry."""
|
||||
if not await async_unload_entry(hass, config_entry):
|
||||
return
|
||||
await async_setup_entry(hass, config_entry)
|
||||
1184
config/custom_components/hacs/base.py
Normal file
1184
config/custom_components/hacs/base.py
Normal file
File diff suppressed because it is too large
Load Diff
247
config/custom_components/hacs/config_flow.py
Normal file
247
config/custom_components/hacs/config_flow.py
Normal file
@@ -0,0 +1,247 @@
|
||||
"""Adds config flow for HACS."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from contextlib import suppress
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from aiogithubapi import (
|
||||
GitHubDeviceAPI,
|
||||
GitHubException,
|
||||
GitHubLoginDeviceModel,
|
||||
GitHubLoginOauthModel,
|
||||
)
|
||||
from aiogithubapi.common.const import OAUTH_USER_LOGIN
|
||||
from awesomeversion import AwesomeVersion
|
||||
from homeassistant.config_entries import ConfigFlow, OptionsFlow
|
||||
from homeassistant.const import __version__ as HAVERSION
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import UnknownFlow
|
||||
from homeassistant.helpers import aiohttp_client
|
||||
from homeassistant.loader import async_get_integration
|
||||
import voluptuous as vol
|
||||
|
||||
from .base import HacsBase
|
||||
from .const import CLIENT_ID, DOMAIN, LOCALE, MINIMUM_HA_VERSION
|
||||
from .enums import ConfigurationType
|
||||
from .utils.configuration_schema import (
|
||||
APPDAEMON,
|
||||
COUNTRY,
|
||||
DEBUG,
|
||||
EXPERIMENTAL,
|
||||
NETDAEMON,
|
||||
RELEASE_LIMIT,
|
||||
SIDEPANEL_ICON,
|
||||
SIDEPANEL_TITLE,
|
||||
)
|
||||
from .utils.logger import LOGGER
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
class HacsFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Config flow for HACS."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
hass: HomeAssistant
|
||||
activation_task: asyncio.Task | None = None
|
||||
device: GitHubDeviceAPI | None = None
|
||||
|
||||
_registration: GitHubLoginDeviceModel | None = None
|
||||
_activation: GitHubLoginOauthModel | None = None
|
||||
_reauth: bool = False
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize."""
|
||||
self._errors = {}
|
||||
self._user_input = {}
|
||||
|
||||
async def async_step_user(self, user_input):
|
||||
"""Handle a flow initialized by the user."""
|
||||
self._errors = {}
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
if self.hass.data.get(DOMAIN):
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
if user_input:
|
||||
if [x for x in user_input if x.startswith("acc_") and not user_input[x]]:
|
||||
self._errors["base"] = "acc"
|
||||
return await self._show_config_form(user_input)
|
||||
|
||||
self._user_input = user_input
|
||||
|
||||
return await self.async_step_device(user_input)
|
||||
|
||||
## Initial form
|
||||
return await self._show_config_form(user_input)
|
||||
|
||||
@callback
|
||||
def async_remove(self):
|
||||
"""Cleanup."""
|
||||
if self.activation_task and not self.activation_task.done():
|
||||
self.activation_task.cancel()
|
||||
|
||||
async def async_step_device(self, _user_input):
|
||||
"""Handle device steps."""
|
||||
|
||||
async def _wait_for_activation() -> None:
|
||||
try:
|
||||
response = await self.device.activation(device_code=self._registration.device_code)
|
||||
self._activation = response.data
|
||||
finally:
|
||||
|
||||
async def _progress():
|
||||
with suppress(UnknownFlow):
|
||||
await self.hass.config_entries.flow.async_configure(flow_id=self.flow_id)
|
||||
|
||||
self.hass.async_create_task(_progress())
|
||||
|
||||
if not self.device:
|
||||
integration = await async_get_integration(self.hass, DOMAIN)
|
||||
self.device = GitHubDeviceAPI(
|
||||
client_id=CLIENT_ID,
|
||||
session=aiohttp_client.async_get_clientsession(self.hass),
|
||||
**{"client_name": f"HACS/{integration.version}"},
|
||||
)
|
||||
try:
|
||||
response = await self.device.register()
|
||||
self._registration = response.data
|
||||
except GitHubException as exception:
|
||||
LOGGER.exception(exception)
|
||||
return self.async_abort(reason="could_not_register")
|
||||
|
||||
if self.activation_task is None:
|
||||
self.activation_task = self.hass.async_create_task(_wait_for_activation())
|
||||
|
||||
if self.activation_task.done():
|
||||
if (exception := self.activation_task.exception()) is not None:
|
||||
LOGGER.exception(exception)
|
||||
return self.async_show_progress_done(next_step_id="could_not_register")
|
||||
return self.async_show_progress_done(next_step_id="device_done")
|
||||
|
||||
return self.async_show_progress(
|
||||
step_id="device",
|
||||
progress_action="wait_for_device",
|
||||
description_placeholders={
|
||||
"url": OAUTH_USER_LOGIN,
|
||||
"code": self._registration.user_code,
|
||||
},
|
||||
)
|
||||
|
||||
async def _show_config_form(self, user_input):
|
||||
"""Show the configuration form to edit location data."""
|
||||
|
||||
if not user_input:
|
||||
user_input = {}
|
||||
|
||||
if AwesomeVersion(HAVERSION) < MINIMUM_HA_VERSION:
|
||||
return self.async_abort(
|
||||
reason="min_ha_version",
|
||||
description_placeholders={"version": MINIMUM_HA_VERSION},
|
||||
)
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required("acc_logs", default=user_input.get("acc_logs", False)): bool,
|
||||
vol.Required("acc_addons", default=user_input.get("acc_addons", False)): bool,
|
||||
vol.Required(
|
||||
"acc_untested", default=user_input.get("acc_untested", False)
|
||||
): bool,
|
||||
vol.Required("acc_disable", default=user_input.get("acc_disable", False)): bool,
|
||||
vol.Optional(
|
||||
"experimental", default=user_input.get("experimental", False)
|
||||
): bool,
|
||||
}
|
||||
),
|
||||
errors=self._errors,
|
||||
)
|
||||
|
||||
async def async_step_device_done(self, user_input: dict[str, bool] | None = None):
|
||||
"""Handle device steps"""
|
||||
if self._reauth:
|
||||
existing_entry = self.hass.config_entries.async_get_entry(self.context["entry_id"])
|
||||
self.hass.config_entries.async_update_entry(
|
||||
existing_entry, data={**existing_entry.data, "token": self._activation.access_token}
|
||||
)
|
||||
await self.hass.config_entries.async_reload(existing_entry.entry_id)
|
||||
return self.async_abort(reason="reauth_successful")
|
||||
|
||||
return self.async_create_entry(
|
||||
title="",
|
||||
data={
|
||||
"token": self._activation.access_token,
|
||||
},
|
||||
options={
|
||||
"experimental": self._user_input.get("experimental", False),
|
||||
},
|
||||
)
|
||||
|
||||
async def async_step_could_not_register(self, _user_input=None):
|
||||
"""Handle issues that need transition await from progress step."""
|
||||
return self.async_abort(reason="could_not_register")
|
||||
|
||||
async def async_step_reauth(self, _user_input=None):
|
||||
"""Perform reauth upon an API authentication error."""
|
||||
return await self.async_step_reauth_confirm()
|
||||
|
||||
async def async_step_reauth_confirm(self, user_input=None):
|
||||
"""Dialog that informs the user that reauth is required."""
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="reauth_confirm",
|
||||
data_schema=vol.Schema({}),
|
||||
)
|
||||
self._reauth = True
|
||||
return await self.async_step_device(None)
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry):
|
||||
return HacsOptionsFlowHandler(config_entry)
|
||||
|
||||
|
||||
class HacsOptionsFlowHandler(OptionsFlow):
|
||||
"""HACS config flow options handler."""
|
||||
|
||||
def __init__(self, config_entry):
|
||||
"""Initialize HACS options flow."""
|
||||
self.config_entry = config_entry
|
||||
|
||||
async def async_step_init(self, _user_input=None):
|
||||
"""Manage the options."""
|
||||
return await self.async_step_user()
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow initialized by the user."""
|
||||
hacs: HacsBase = self.hass.data.get(DOMAIN)
|
||||
if user_input is not None:
|
||||
limit = int(user_input.get(RELEASE_LIMIT, 5))
|
||||
if limit <= 0 or limit > 100:
|
||||
return self.async_abort(reason="release_limit_value")
|
||||
return self.async_create_entry(title="", data=user_input)
|
||||
|
||||
if hacs is None or hacs.configuration is None:
|
||||
return self.async_abort(reason="not_setup")
|
||||
|
||||
if hacs.queue.has_pending_tasks:
|
||||
return self.async_abort(reason="pending_tasks")
|
||||
|
||||
if hacs.configuration.config_type == ConfigurationType.YAML:
|
||||
schema = {vol.Optional("not_in_use", default=""): str}
|
||||
else:
|
||||
schema = {
|
||||
vol.Optional(SIDEPANEL_TITLE, default=hacs.configuration.sidepanel_title): str,
|
||||
vol.Optional(SIDEPANEL_ICON, default=hacs.configuration.sidepanel_icon): str,
|
||||
vol.Optional(RELEASE_LIMIT, default=hacs.configuration.release_limit): int,
|
||||
vol.Optional(COUNTRY, default=hacs.configuration.country): vol.In(LOCALE),
|
||||
vol.Optional(APPDAEMON, default=hacs.configuration.appdaemon): bool,
|
||||
vol.Optional(NETDAEMON, default=hacs.configuration.netdaemon): bool,
|
||||
vol.Optional(DEBUG, default=hacs.configuration.debug): bool,
|
||||
vol.Optional(EXPERIMENTAL, default=hacs.configuration.experimental): bool,
|
||||
}
|
||||
|
||||
return self.async_show_form(step_id="user", data_schema=vol.Schema(schema))
|
||||
293
config/custom_components/hacs/const.py
Normal file
293
config/custom_components/hacs/const.py
Normal file
@@ -0,0 +1,293 @@
|
||||
"""Constants for HACS"""
|
||||
from typing import TypeVar
|
||||
|
||||
from aiogithubapi.common.const import ACCEPT_HEADERS
|
||||
|
||||
NAME_SHORT = "HACS"
|
||||
DOMAIN = "hacs"
|
||||
CLIENT_ID = "395a8e669c5de9f7c6e8"
|
||||
MINIMUM_HA_VERSION = "2023.6.0"
|
||||
|
||||
URL_BASE = "/hacsfiles"
|
||||
|
||||
TV = TypeVar("TV")
|
||||
|
||||
PACKAGE_NAME = "custom_components.hacs"
|
||||
|
||||
DEFAULT_CONCURRENT_TASKS = 15
|
||||
DEFAULT_CONCURRENT_BACKOFF_TIME = 1
|
||||
|
||||
HACS_REPOSITORY_ID = "172733314"
|
||||
|
||||
HACS_ACTION_GITHUB_API_HEADERS = {
|
||||
"User-Agent": "HACS/action",
|
||||
"Accept": ACCEPT_HEADERS["preview"],
|
||||
}
|
||||
|
||||
VERSION_STORAGE = "6"
|
||||
STORENAME = "hacs"
|
||||
|
||||
HACS_SYSTEM_ID = "0717a0cd-745c-48fd-9b16-c8534c9704f9-bc944b0f-fd42-4a58-a072-ade38d1444cd"
|
||||
|
||||
STARTUP = """
|
||||
-------------------------------------------------------------------
|
||||
HACS (Home Assistant Community Store)
|
||||
|
||||
Version: %s
|
||||
This is a custom integration
|
||||
If you have any issues with this you need to open an issue here:
|
||||
https://github.com/hacs/integration/issues
|
||||
-------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
LOCALE = [
|
||||
"ALL",
|
||||
"AF",
|
||||
"AL",
|
||||
"DZ",
|
||||
"AS",
|
||||
"AD",
|
||||
"AO",
|
||||
"AI",
|
||||
"AQ",
|
||||
"AG",
|
||||
"AR",
|
||||
"AM",
|
||||
"AW",
|
||||
"AU",
|
||||
"AT",
|
||||
"AZ",
|
||||
"BS",
|
||||
"BH",
|
||||
"BD",
|
||||
"BB",
|
||||
"BY",
|
||||
"BE",
|
||||
"BZ",
|
||||
"BJ",
|
||||
"BM",
|
||||
"BT",
|
||||
"BO",
|
||||
"BQ",
|
||||
"BA",
|
||||
"BW",
|
||||
"BV",
|
||||
"BR",
|
||||
"IO",
|
||||
"BN",
|
||||
"BG",
|
||||
"BF",
|
||||
"BI",
|
||||
"KH",
|
||||
"CM",
|
||||
"CA",
|
||||
"CV",
|
||||
"KY",
|
||||
"CF",
|
||||
"TD",
|
||||
"CL",
|
||||
"CN",
|
||||
"CX",
|
||||
"CC",
|
||||
"CO",
|
||||
"KM",
|
||||
"CG",
|
||||
"CD",
|
||||
"CK",
|
||||
"CR",
|
||||
"HR",
|
||||
"CU",
|
||||
"CW",
|
||||
"CY",
|
||||
"CZ",
|
||||
"CI",
|
||||
"DK",
|
||||
"DJ",
|
||||
"DM",
|
||||
"DO",
|
||||
"EC",
|
||||
"EG",
|
||||
"SV",
|
||||
"GQ",
|
||||
"ER",
|
||||
"EE",
|
||||
"ET",
|
||||
"FK",
|
||||
"FO",
|
||||
"FJ",
|
||||
"FI",
|
||||
"FR",
|
||||
"GF",
|
||||
"PF",
|
||||
"TF",
|
||||
"GA",
|
||||
"GM",
|
||||
"GE",
|
||||
"DE",
|
||||
"GH",
|
||||
"GI",
|
||||
"GR",
|
||||
"GL",
|
||||
"GD",
|
||||
"GP",
|
||||
"GU",
|
||||
"GT",
|
||||
"GG",
|
||||
"GN",
|
||||
"GW",
|
||||
"GY",
|
||||
"HT",
|
||||
"HM",
|
||||
"VA",
|
||||
"HN",
|
||||
"HK",
|
||||
"HU",
|
||||
"IS",
|
||||
"IN",
|
||||
"ID",
|
||||
"IR",
|
||||
"IQ",
|
||||
"IE",
|
||||
"IM",
|
||||
"IL",
|
||||
"IT",
|
||||
"JM",
|
||||
"JP",
|
||||
"JE",
|
||||
"JO",
|
||||
"KZ",
|
||||
"KE",
|
||||
"KI",
|
||||
"KP",
|
||||
"KR",
|
||||
"KW",
|
||||
"KG",
|
||||
"LA",
|
||||
"LV",
|
||||
"LB",
|
||||
"LS",
|
||||
"LR",
|
||||
"LY",
|
||||
"LI",
|
||||
"LT",
|
||||
"LU",
|
||||
"MO",
|
||||
"MK",
|
||||
"MG",
|
||||
"MW",
|
||||
"MY",
|
||||
"MV",
|
||||
"ML",
|
||||
"MT",
|
||||
"MH",
|
||||
"MQ",
|
||||
"MR",
|
||||
"MU",
|
||||
"YT",
|
||||
"MX",
|
||||
"FM",
|
||||
"MD",
|
||||
"MC",
|
||||
"MN",
|
||||
"ME",
|
||||
"MS",
|
||||
"MA",
|
||||
"MZ",
|
||||
"MM",
|
||||
"NA",
|
||||
"NR",
|
||||
"NP",
|
||||
"NL",
|
||||
"NC",
|
||||
"NZ",
|
||||
"NI",
|
||||
"NE",
|
||||
"NG",
|
||||
"NU",
|
||||
"NF",
|
||||
"MP",
|
||||
"NO",
|
||||
"OM",
|
||||
"PK",
|
||||
"PW",
|
||||
"PS",
|
||||
"PA",
|
||||
"PG",
|
||||
"PY",
|
||||
"PE",
|
||||
"PH",
|
||||
"PN",
|
||||
"PL",
|
||||
"PT",
|
||||
"PR",
|
||||
"QA",
|
||||
"RO",
|
||||
"RU",
|
||||
"RW",
|
||||
"RE",
|
||||
"BL",
|
||||
"SH",
|
||||
"KN",
|
||||
"LC",
|
||||
"MF",
|
||||
"PM",
|
||||
"VC",
|
||||
"WS",
|
||||
"SM",
|
||||
"ST",
|
||||
"SA",
|
||||
"SN",
|
||||
"RS",
|
||||
"SC",
|
||||
"SL",
|
||||
"SG",
|
||||
"SX",
|
||||
"SK",
|
||||
"SI",
|
||||
"SB",
|
||||
"SO",
|
||||
"ZA",
|
||||
"GS",
|
||||
"SS",
|
||||
"ES",
|
||||
"LK",
|
||||
"SD",
|
||||
"SR",
|
||||
"SJ",
|
||||
"SZ",
|
||||
"SE",
|
||||
"CH",
|
||||
"SY",
|
||||
"TW",
|
||||
"TJ",
|
||||
"TZ",
|
||||
"TH",
|
||||
"TL",
|
||||
"TG",
|
||||
"TK",
|
||||
"TO",
|
||||
"TT",
|
||||
"TN",
|
||||
"TR",
|
||||
"TM",
|
||||
"TC",
|
||||
"TV",
|
||||
"UG",
|
||||
"UA",
|
||||
"AE",
|
||||
"GB",
|
||||
"US",
|
||||
"UM",
|
||||
"UY",
|
||||
"UZ",
|
||||
"VU",
|
||||
"VE",
|
||||
"VN",
|
||||
"VG",
|
||||
"VI",
|
||||
"WF",
|
||||
"EH",
|
||||
"YE",
|
||||
"ZM",
|
||||
"ZW",
|
||||
]
|
||||
57
config/custom_components/hacs/data_client.py
Normal file
57
config/custom_components/hacs/data_client.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""HACS Data client."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from aiohttp import ClientSession, ClientTimeout
|
||||
|
||||
from .exceptions import HacsException, HacsNotModifiedException
|
||||
|
||||
|
||||
class HacsDataClient:
|
||||
"""HACS Data client."""
|
||||
|
||||
def __init__(self, session: ClientSession, client_name: str) -> None:
|
||||
"""Initialize."""
|
||||
self._client_name = client_name
|
||||
self._etags = {}
|
||||
self._session = session
|
||||
|
||||
async def _do_request(
|
||||
self,
|
||||
filename: str,
|
||||
section: str | None = None,
|
||||
) -> dict[str, dict[str, Any]] | list[str]:
|
||||
"""Do request."""
|
||||
endpoint = "/".join([v for v in [section, filename] if v is not None])
|
||||
try:
|
||||
response = await self._session.get(
|
||||
f"https://data-v2.hacs.xyz/{endpoint}",
|
||||
timeout=ClientTimeout(total=60),
|
||||
headers={
|
||||
"User-Agent": self._client_name,
|
||||
"If-None-Match": self._etags.get(endpoint, ""),
|
||||
},
|
||||
)
|
||||
if response.status == 304:
|
||||
raise HacsNotModifiedException() from None
|
||||
response.raise_for_status()
|
||||
except HacsNotModifiedException:
|
||||
raise
|
||||
except asyncio.TimeoutError:
|
||||
raise HacsException("Timeout of 60s reached") from None
|
||||
except Exception as exception:
|
||||
raise HacsException(f"Error fetching data from HACS: {exception}") from exception
|
||||
|
||||
self._etags[endpoint] = response.headers.get("etag")
|
||||
|
||||
return await response.json()
|
||||
|
||||
async def get_data(self, section: str | None) -> dict[str, dict[str, Any]]:
|
||||
"""Get data."""
|
||||
return await self._do_request(filename="data.json", section=section)
|
||||
|
||||
async def get_repositories(self, section: str) -> list[str]:
|
||||
"""Get repositories."""
|
||||
return await self._do_request(filename="repositories.json", section=section)
|
||||
82
config/custom_components/hacs/diagnostics.py
Normal file
82
config/custom_components/hacs/diagnostics.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""Diagnostics support for HACS."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aiogithubapi import GitHubException
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .base import HacsBase
|
||||
from .const import DOMAIN
|
||||
from .utils.configuration_schema import TOKEN
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a config entry."""
|
||||
hacs: HacsBase = hass.data[DOMAIN]
|
||||
|
||||
data = {
|
||||
"entry": entry.as_dict(),
|
||||
"hacs": {
|
||||
"stage": hacs.stage,
|
||||
"version": hacs.version,
|
||||
"disabled_reason": hacs.system.disabled_reason,
|
||||
"new": hacs.status.new,
|
||||
"startup": hacs.status.startup,
|
||||
"categories": hacs.common.categories,
|
||||
"renamed_repositories": hacs.common.renamed_repositories,
|
||||
"archived_repositories": hacs.common.archived_repositories,
|
||||
"ignored_repositories": hacs.common.ignored_repositories,
|
||||
"lovelace_mode": hacs.core.lovelace_mode,
|
||||
"configuration": {},
|
||||
},
|
||||
"custom_repositories": [
|
||||
repo.data.full_name
|
||||
for repo in hacs.repositories.list_all
|
||||
if not hacs.repositories.is_default(str(repo.data.id))
|
||||
],
|
||||
"repositories": [],
|
||||
}
|
||||
|
||||
for key in (
|
||||
"appdaemon",
|
||||
"country",
|
||||
"debug",
|
||||
"dev",
|
||||
"experimental",
|
||||
"netdaemon",
|
||||
"python_script",
|
||||
"release_limit",
|
||||
"theme",
|
||||
):
|
||||
data["hacs"]["configuration"][key] = getattr(hacs.configuration, key, None)
|
||||
|
||||
for repository in hacs.repositories.list_downloaded:
|
||||
data["repositories"].append(
|
||||
{
|
||||
"data": repository.data.to_json(),
|
||||
"integration_manifest": repository.integration_manifest,
|
||||
"repository_manifest": repository.repository_manifest.to_dict(),
|
||||
"ref": repository.ref,
|
||||
"paths": {
|
||||
"localpath": repository.localpath.replace(hacs.core.config_path, "/config"),
|
||||
"local": repository.content.path.local.replace(
|
||||
hacs.core.config_path, "/config"
|
||||
),
|
||||
"remote": repository.content.path.remote,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
rate_limit_response = await hacs.githubapi.rate_limit()
|
||||
data["rate_limit"] = rate_limit_response.data.as_dict
|
||||
except GitHubException as exception:
|
||||
data["rate_limit"] = str(exception)
|
||||
|
||||
return async_redact_data(data, (TOKEN,))
|
||||
119
config/custom_components/hacs/entity.py
Normal file
119
config/custom_components/hacs/entity.py
Normal file
@@ -0,0 +1,119 @@
|
||||
"""HACS Base entities."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import DOMAIN, HACS_SYSTEM_ID, NAME_SHORT
|
||||
from .enums import HacsDispatchEvent, HacsGitHubRepo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .base import HacsBase
|
||||
from .repositories.base import HacsRepository
|
||||
|
||||
|
||||
def system_info(hacs: HacsBase) -> dict:
|
||||
"""Return system info."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, HACS_SYSTEM_ID)},
|
||||
"name": NAME_SHORT,
|
||||
"manufacturer": "hacs.xyz",
|
||||
"model": "",
|
||||
"sw_version": str(hacs.version),
|
||||
"configuration_url": "homeassistant://hacs",
|
||||
"entry_type": DeviceEntryType.SERVICE,
|
||||
}
|
||||
|
||||
|
||||
class HacsBaseEntity(Entity):
|
||||
"""Base HACS entity."""
|
||||
|
||||
repository: HacsRepository | None = None
|
||||
_attr_should_poll = False
|
||||
|
||||
def __init__(self, hacs: HacsBase) -> None:
|
||||
"""Initialize."""
|
||||
self.hacs = hacs
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register for status events."""
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(
|
||||
self.hass,
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
self._update_and_write_state,
|
||||
)
|
||||
)
|
||||
|
||||
@callback
|
||||
def _update(self) -> None:
|
||||
"""Update the sensor."""
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Manual updates of the sensor."""
|
||||
self._update()
|
||||
|
||||
@callback
|
||||
def _update_and_write_state(self, _: Any) -> None:
|
||||
"""Update the entity and write state."""
|
||||
self._update()
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class HacsSystemEntity(HacsBaseEntity):
|
||||
"""Base system entity."""
|
||||
|
||||
_attr_icon = "hacs:hacs"
|
||||
_attr_unique_id = HACS_SYSTEM_ID
|
||||
|
||||
@property
|
||||
def device_info(self) -> dict[str, any]:
|
||||
"""Return device information about HACS."""
|
||||
return system_info(self.hacs)
|
||||
|
||||
|
||||
class HacsRepositoryEntity(HacsBaseEntity):
|
||||
"""Base repository entity."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hacs: HacsBase,
|
||||
repository: HacsRepository,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(hacs=hacs)
|
||||
self.repository = repository
|
||||
self._attr_unique_id = str(repository.data.id)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return self.hacs.repositories.is_downloaded(repository_id=str(self.repository.data.id))
|
||||
|
||||
@property
|
||||
def device_info(self) -> dict[str, any]:
|
||||
"""Return device information about HACS."""
|
||||
if self.repository.data.full_name == HacsGitHubRepo.INTEGRATION:
|
||||
return system_info(self.hacs)
|
||||
|
||||
return {
|
||||
"identifiers": {(DOMAIN, str(self.repository.data.id))},
|
||||
"name": self.repository.display_name,
|
||||
"model": self.repository.data.category,
|
||||
"manufacturer": ", ".join(
|
||||
author.replace("@", "") for author in self.repository.data.authors
|
||||
),
|
||||
"configuration_url": "homeassistant://hacs",
|
||||
"entry_type": DeviceEntryType.SERVICE,
|
||||
}
|
||||
|
||||
@callback
|
||||
def _update_and_write_state(self, data: dict) -> None:
|
||||
"""Update the entity and write state."""
|
||||
if data.get("repository_id") == self.repository.data.id:
|
||||
self._update()
|
||||
self.async_write_ha_state()
|
||||
90
config/custom_components/hacs/enums.py
Normal file
90
config/custom_components/hacs/enums.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""Helper constants."""
|
||||
# pylint: disable=missing-class-docstring
|
||||
import sys
|
||||
|
||||
if sys.version_info.minor >= 11:
|
||||
# Needs Python 3.11
|
||||
from enum import StrEnum # # pylint: disable=no-name-in-module
|
||||
else:
|
||||
try:
|
||||
# https://github.com/home-assistant/core/blob/dev/homeassistant/backports/enum.py
|
||||
# Considered internal to Home Assistant, can be removed whenever.
|
||||
from homeassistant.backports.enum import StrEnum
|
||||
except ImportError:
|
||||
from enum import Enum
|
||||
|
||||
class StrEnum(str, Enum):
|
||||
pass
|
||||
|
||||
|
||||
class HacsGitHubRepo(StrEnum):
|
||||
"""HacsGitHubRepo."""
|
||||
|
||||
DEFAULT = "hacs/default"
|
||||
INTEGRATION = "hacs/integration"
|
||||
|
||||
|
||||
class HacsCategory(StrEnum):
|
||||
APPDAEMON = "appdaemon"
|
||||
INTEGRATION = "integration"
|
||||
LOVELACE = "lovelace"
|
||||
PLUGIN = "plugin" # Kept for legacy purposes
|
||||
NETDAEMON = "netdaemon"
|
||||
PYTHON_SCRIPT = "python_script"
|
||||
TEMPLATE = "template"
|
||||
THEME = "theme"
|
||||
REMOVED = "removed"
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
|
||||
class HacsDispatchEvent(StrEnum):
|
||||
"""HacsDispatchEvent."""
|
||||
|
||||
CONFIG = "hacs_dispatch_config"
|
||||
ERROR = "hacs_dispatch_error"
|
||||
RELOAD = "hacs_dispatch_reload"
|
||||
REPOSITORY = "hacs_dispatch_repository"
|
||||
REPOSITORY_DOWNLOAD_PROGRESS = "hacs_dispatch_repository_download_progress"
|
||||
STAGE = "hacs_dispatch_stage"
|
||||
STARTUP = "hacs_dispatch_startup"
|
||||
STATUS = "hacs_dispatch_status"
|
||||
|
||||
|
||||
class RepositoryFile(StrEnum):
|
||||
"""Repository file names."""
|
||||
|
||||
HACS_JSON = "hacs.json"
|
||||
MAINIFEST_JSON = "manifest.json"
|
||||
|
||||
|
||||
class ConfigurationType(StrEnum):
|
||||
YAML = "yaml"
|
||||
CONFIG_ENTRY = "config_entry"
|
||||
|
||||
|
||||
class LovelaceMode(StrEnum):
|
||||
"""Lovelace Modes."""
|
||||
|
||||
STORAGE = "storage"
|
||||
AUTO = "auto"
|
||||
AUTO_GEN = "auto-gen"
|
||||
YAML = "yaml"
|
||||
|
||||
|
||||
class HacsStage(StrEnum):
|
||||
SETUP = "setup"
|
||||
STARTUP = "startup"
|
||||
WAITING = "waiting"
|
||||
RUNNING = "running"
|
||||
BACKGROUND = "background"
|
||||
|
||||
|
||||
class HacsDisabledReason(StrEnum):
|
||||
RATE_LIMIT = "rate_limit"
|
||||
REMOVED = "removed"
|
||||
INVALID_TOKEN = "invalid_token"
|
||||
CONSTRAINS = "constrains"
|
||||
LOAD_HACS = "load_hacs"
|
||||
RESTORE = "restore"
|
||||
49
config/custom_components/hacs/exceptions.py
Normal file
49
config/custom_components/hacs/exceptions.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""Custom Exceptions for HACS."""
|
||||
|
||||
|
||||
class HacsException(Exception):
|
||||
"""Super basic."""
|
||||
|
||||
|
||||
class HacsRepositoryArchivedException(HacsException):
|
||||
"""For repositories that are archived."""
|
||||
|
||||
|
||||
class HacsNotModifiedException(HacsException):
|
||||
"""For responses that are not modified."""
|
||||
|
||||
|
||||
class HacsExpectedException(HacsException):
|
||||
"""For stuff that are expected."""
|
||||
|
||||
|
||||
class HacsRepositoryExistException(HacsException):
|
||||
"""For repositories that are already exist."""
|
||||
|
||||
|
||||
class HacsExecutionStillInProgress(HacsException):
|
||||
"""Exception to raise if execution is still in progress."""
|
||||
|
||||
|
||||
class AddonRepositoryException(HacsException):
|
||||
"""Exception to raise when user tries to add add-on repository."""
|
||||
|
||||
exception_message = (
|
||||
"The repository does not seem to be a integration, "
|
||||
"but an add-on repository. HACS does not manage add-ons."
|
||||
)
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__(self.exception_message)
|
||||
|
||||
|
||||
class HomeAssistantCoreRepositoryException(HacsException):
|
||||
"""Exception to raise when user tries to add the home-assistant/core repository."""
|
||||
|
||||
exception_message = (
|
||||
"You can not add homeassistant/core, to use core integrations "
|
||||
"check the Home Assistant documentation for how to add them."
|
||||
)
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__(self.exception_message)
|
||||
85
config/custom_components/hacs/frontend.py
Normal file
85
config/custom_components/hacs/frontend.py
Normal file
@@ -0,0 +1,85 @@
|
||||
""""Starting setup task: Frontend"."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
||||
from .const import DOMAIN, URL_BASE
|
||||
from .hacs_frontend import VERSION as FE_VERSION, locate_dir
|
||||
from .hacs_frontend_experimental import (
|
||||
VERSION as EXPERIMENTAL_FE_VERSION,
|
||||
locate_dir as experimental_locate_dir,
|
||||
)
|
||||
|
||||
try:
|
||||
from homeassistant.components.frontend import add_extra_js_url
|
||||
except ImportError:
|
||||
|
||||
def add_extra_js_url(hass: HomeAssistant, url: str, es5: bool = False) -> None:
|
||||
hacs: HacsBase = hass.data.get(DOMAIN)
|
||||
hacs.log.error("Could not import add_extra_js_url from frontend.")
|
||||
if "frontend_extra_module_url" not in hass.data:
|
||||
hass.data["frontend_extra_module_url"] = set()
|
||||
hass.data["frontend_extra_module_url"].add(url)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .base import HacsBase
|
||||
|
||||
|
||||
@callback
|
||||
def async_register_frontend(hass: HomeAssistant, hacs: HacsBase) -> None:
|
||||
"""Register the frontend."""
|
||||
|
||||
# Setup themes endpoint if needed
|
||||
hacs.async_setup_frontend_endpoint_themes()
|
||||
|
||||
# Register frontend
|
||||
if hacs.configuration.dev and (frontend_path := os.getenv("HACS_FRONTEND_DIR")):
|
||||
hacs.log.warning(
|
||||
"<HacsFrontend> Frontend development mode enabled. Do not run in production!"
|
||||
)
|
||||
hass.http.register_static_path(
|
||||
f"{URL_BASE}/frontend", f"{frontend_path}/hacs_frontend", cache_headers=False
|
||||
)
|
||||
elif hacs.configuration.experimental:
|
||||
hacs.log.info("<HacsFrontend> Using experimental frontend")
|
||||
hass.http.register_static_path(
|
||||
f"{URL_BASE}/frontend", experimental_locate_dir(), cache_headers=False
|
||||
)
|
||||
else:
|
||||
#
|
||||
hass.http.register_static_path(f"{URL_BASE}/frontend", locate_dir(), cache_headers=False)
|
||||
|
||||
# Custom iconset
|
||||
hass.http.register_static_path(
|
||||
f"{URL_BASE}/iconset.js", str(hacs.integration_dir / "iconset.js")
|
||||
)
|
||||
add_extra_js_url(hass, f"{URL_BASE}/iconset.js")
|
||||
|
||||
hacs.frontend_version = (
|
||||
FE_VERSION if not hacs.configuration.experimental else EXPERIMENTAL_FE_VERSION
|
||||
)
|
||||
|
||||
# Add to sidepanel if needed
|
||||
if DOMAIN not in hass.data.get("frontend_panels", {}):
|
||||
hass.components.frontend.async_register_built_in_panel(
|
||||
component_name="custom",
|
||||
sidebar_title=hacs.configuration.sidepanel_title,
|
||||
sidebar_icon=hacs.configuration.sidepanel_icon,
|
||||
frontend_url_path=DOMAIN,
|
||||
config={
|
||||
"_panel_custom": {
|
||||
"name": "hacs-frontend",
|
||||
"embed_iframe": True,
|
||||
"trust_external": False,
|
||||
"js_url": f"/hacsfiles/frontend/entrypoint.js?hacstag={hacs.frontend_version}",
|
||||
}
|
||||
},
|
||||
require_admin=True,
|
||||
)
|
||||
|
||||
# Setup plugin endpoint if needed
|
||||
hacs.async_setup_frontend_endpoint_plugin()
|
||||
5
config/custom_components/hacs/hacs_frontend/__init__.py
Normal file
5
config/custom_components/hacs/hacs_frontend/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""HACS Frontend"""
|
||||
from .version import VERSION
|
||||
|
||||
def locate_dir():
|
||||
return __path__[0]
|
||||
File diff suppressed because one or more lines are too long
23
config/custom_components/hacs/hacs_frontend/c.0a1cf8d0.js
Normal file
23
config/custom_components/hacs/hacs_frontend/c.0a1cf8d0.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import{a as t,r as i,n as a}from"./main-ad130be7.js";import{L as n,s}from"./c.82eccc94.js";let r=t([a("ha-list-item")],(function(t,a){return{F:class extends a{constructor(...i){super(...i),t(this)}},d:[{kind:"get",static:!0,key:"styles",value:function(){return[s,i`
|
||||
:host {
|
||||
padding-left: var(--mdc-list-side-padding, 20px);
|
||||
padding-right: var(--mdc-list-side-padding, 20px);
|
||||
}
|
||||
:host([graphic="avatar"]:not([twoLine])),
|
||||
:host([graphic="icon"]:not([twoLine])) {
|
||||
height: 48px;
|
||||
}
|
||||
span.material-icons:first-of-type {
|
||||
margin-inline-start: 0px !important;
|
||||
margin-inline-end: var(
|
||||
--mdc-list-item-graphic-margin,
|
||||
16px
|
||||
) !important;
|
||||
direction: var(--direction);
|
||||
}
|
||||
span.material-icons:last-of-type {
|
||||
margin-inline-start: auto !important;
|
||||
margin-inline-end: 0px !important;
|
||||
direction: var(--direction);
|
||||
}
|
||||
`]}}]}}),n);const e=t=>`https://brands.home-assistant.io/${t.useFallback?"_/":""}${t.domain}/${t.darkOptimized?"dark_":""}${t.type}.png`,o=t=>t.split("/")[4],p=t=>t.startsWith("https://brands.home-assistant.io/");export{r as H,e as b,o as e,p as i};
|
||||
24
config/custom_components/hacs/hacs_frontend/c.0ca5587f.js
Normal file
24
config/custom_components/hacs/hacs_frontend/c.0ca5587f.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import{a as e,h as t,Y as i,e as n,i as o,$ as r,L as l,N as a,r as d,n as s}from"./main-ad130be7.js";import"./c.9b92f489.js";e([s("ha-button-menu")],(function(e,t){class s extends t{constructor(...t){super(...t),e(this)}}return{F:s,d:[{kind:"field",key:i,value:void 0},{kind:"field",decorators:[n()],key:"corner",value:()=>"TOP_START"},{kind:"field",decorators:[n()],key:"menuCorner",value:()=>"START"},{kind:"field",decorators:[n({type:Number})],key:"x",value:()=>null},{kind:"field",decorators:[n({type:Number})],key:"y",value:()=>null},{kind:"field",decorators:[n({type:Boolean})],key:"multi",value:()=>!1},{kind:"field",decorators:[n({type:Boolean})],key:"activatable",value:()=>!1},{kind:"field",decorators:[n({type:Boolean})],key:"disabled",value:()=>!1},{kind:"field",decorators:[n({type:Boolean})],key:"fixed",value:()=>!1},{kind:"field",decorators:[o("mwc-menu",!0)],key:"_menu",value:void 0},{kind:"get",key:"items",value:function(){var e;return null===(e=this._menu)||void 0===e?void 0:e.items}},{kind:"get",key:"selected",value:function(){var e;return null===(e=this._menu)||void 0===e?void 0:e.selected}},{kind:"method",key:"focus",value:function(){var e,t;null!==(e=this._menu)&&void 0!==e&&e.open?this._menu.focusItemAtIndex(0):null===(t=this._triggerButton)||void 0===t||t.focus()}},{kind:"method",key:"render",value:function(){return r`
|
||||
<div @click=${this._handleClick}>
|
||||
<slot name="trigger" @slotchange=${this._setTriggerAria}></slot>
|
||||
</div>
|
||||
<mwc-menu
|
||||
.corner=${this.corner}
|
||||
.menuCorner=${this.menuCorner}
|
||||
.fixed=${this.fixed}
|
||||
.multi=${this.multi}
|
||||
.activatable=${this.activatable}
|
||||
.y=${this.y}
|
||||
.x=${this.x}
|
||||
>
|
||||
<slot></slot>
|
||||
</mwc-menu>
|
||||
`}},{kind:"method",key:"firstUpdated",value:function(e){l(a(s.prototype),"firstUpdated",this).call(this,e),"rtl"===document.dir&&this.updateComplete.then((()=>{this.querySelectorAll("mwc-list-item").forEach((e=>{const t=document.createElement("style");t.innerHTML="span.material-icons:first-of-type { margin-left: var(--mdc-list-item-graphic-margin, 32px) !important; margin-right: 0px !important;}",e.shadowRoot.appendChild(t)}))}))}},{kind:"method",key:"_handleClick",value:function(){this.disabled||(this._menu.anchor=this,this._menu.show())}},{kind:"get",key:"_triggerButton",value:function(){return this.querySelector('ha-icon-button[slot="trigger"], mwc-button[slot="trigger"]')}},{kind:"method",key:"_setTriggerAria",value:function(){this._triggerButton&&(this._triggerButton.ariaHasPopup="menu")}},{kind:"get",static:!0,key:"styles",value:function(){return d`
|
||||
:host {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
::slotted([disabled]) {
|
||||
color: var(--disabled-text-color);
|
||||
}
|
||||
`}}]}}),t);
|
||||
390
config/custom_components/hacs/hacs_frontend/c.0f6bb17e.js
Normal file
390
config/custom_components/hacs/hacs_frontend/c.0f6bb17e.js
Normal file
@@ -0,0 +1,390 @@
|
||||
import{a as e,h as t,e as i,g as a,t as s,$ as o,j as r,R as n,w as l,r as h,n as c,m as d,L as p,N as u,o as v,b as f,aI as b,ai as m,c as k,E as g,aJ as y,aC as w,aK as x,aL as $,d as _,s as R}from"./main-ad130be7.js";import{f as z}from"./c.3243a8b0.js";import{c as j}from"./c.4a97632a.js";import"./c.f1291e50.js";import"./c.2d5ed670.js";import"./c.97b7c4b0.js";import{r as F}from"./c.4204ca09.js";import{i as P}from"./c.21c042d4.js";import{s as I}from"./c.2645c235.js";import"./c.a5f69ed4.js";import"./c.3f859915.js";import"./c.9b92f489.js";import"./c.82eccc94.js";import"./c.8e28b461.js";import"./c.4feb0cb8.js";import"./c.0ca5587f.js";import"./c.5d3ce9d6.js";import"./c.f6611997.js";import"./c.743a15a1.js";import"./c.4266acdb.js";e([c("ha-tab")],(function(e,t){return{F:class extends t{constructor(...t){super(...t),e(this)}},d:[{kind:"field",decorators:[i({type:Boolean,reflect:!0})],key:"active",value:()=>!1},{kind:"field",decorators:[i({type:Boolean,reflect:!0})],key:"narrow",value:()=>!1},{kind:"field",decorators:[i()],key:"name",value:void 0},{kind:"field",decorators:[a("mwc-ripple")],key:"_ripple",value:void 0},{kind:"field",decorators:[s()],key:"_shouldRenderRipple",value:()=>!1},{kind:"method",key:"render",value:function(){return o`
|
||||
<div
|
||||
tabindex="0"
|
||||
role="tab"
|
||||
aria-selected=${this.active}
|
||||
aria-label=${r(this.name)}
|
||||
@focus=${this.handleRippleFocus}
|
||||
@blur=${this.handleRippleBlur}
|
||||
@mousedown=${this.handleRippleActivate}
|
||||
@mouseup=${this.handleRippleDeactivate}
|
||||
@mouseenter=${this.handleRippleMouseEnter}
|
||||
@mouseleave=${this.handleRippleMouseLeave}
|
||||
@touchstart=${this.handleRippleActivate}
|
||||
@touchend=${this.handleRippleDeactivate}
|
||||
@touchcancel=${this.handleRippleDeactivate}
|
||||
@keydown=${this._handleKeyDown}
|
||||
>
|
||||
${this.narrow?o`<slot name="icon"></slot>`:""}
|
||||
<span class="name">${this.name}</span>
|
||||
${this._shouldRenderRipple?o`<mwc-ripple></mwc-ripple>`:""}
|
||||
</div>
|
||||
`}},{kind:"field",key:"_rippleHandlers",value(){return new n((()=>(this._shouldRenderRipple=!0,this._ripple)))}},{kind:"method",key:"_handleKeyDown",value:function(e){13===e.keyCode&&e.target.click()}},{kind:"method",decorators:[l({passive:!0})],key:"handleRippleActivate",value:function(e){this._rippleHandlers.startPress(e)}},{kind:"method",key:"handleRippleDeactivate",value:function(){this._rippleHandlers.endPress()}},{kind:"method",key:"handleRippleMouseEnter",value:function(){this._rippleHandlers.startHover()}},{kind:"method",key:"handleRippleMouseLeave",value:function(){this._rippleHandlers.endHover()}},{kind:"method",key:"handleRippleFocus",value:function(){this._rippleHandlers.startFocus()}},{kind:"method",key:"handleRippleBlur",value:function(){this._rippleHandlers.endFocus()}},{kind:"get",static:!0,key:"styles",value:function(){return h`
|
||||
div {
|
||||
padding: 0 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: var(--header-height);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
:host([active]) {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
:host(:not([narrow])[active]) div {
|
||||
border-bottom: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
:host([narrow]) {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:host([narrow]) div {
|
||||
padding: 0 4px;
|
||||
}
|
||||
`}}]}}),t),e([c("hass-tabs-subpage")],(function(e,t){class a extends t{constructor(...t){super(...t),e(this)}}return{F:a,d:[{kind:"field",decorators:[i({attribute:!1})],key:"hass",value:void 0},{kind:"field",decorators:[i({type:Boolean})],key:"supervisor",value:()=>!1},{kind:"field",decorators:[i({attribute:!1})],key:"localizeFunc",value:void 0},{kind:"field",decorators:[i({type:String,attribute:"back-path"})],key:"backPath",value:void 0},{kind:"field",decorators:[i()],key:"backCallback",value:void 0},{kind:"field",decorators:[i({type:Boolean,attribute:"main-page"})],key:"mainPage",value:()=>!1},{kind:"field",decorators:[i({attribute:!1})],key:"route",value:void 0},{kind:"field",decorators:[i({attribute:!1})],key:"tabs",value:void 0},{kind:"field",decorators:[i({type:Boolean,reflect:!0})],key:"narrow",value:()=>!1},{kind:"field",decorators:[i({type:Boolean,reflect:!0,attribute:"is-wide"})],key:"isWide",value:()=>!1},{kind:"field",decorators:[i({type:Boolean,reflect:!0})],key:"rtl",value:()=>!1},{kind:"field",decorators:[s()],key:"_activeTab",value:void 0},{kind:"field",decorators:[F(".content")],key:"_savedScrollPos",value:void 0},{kind:"field",key:"_getTabs",value(){return d(((e,t,i,a,s,r,n)=>{const l=e.filter((e=>(!e.component||e.core||P(this.hass,e.component))&&(!e.advancedOnly||i)));if(l.length<2){if(1===l.length){const e=l[0];return[e.translationKey?n(e.translationKey):e.name]}return[""]}return l.map((e=>o`
|
||||
<a href=${e.path}>
|
||||
<ha-tab
|
||||
.hass=${this.hass}
|
||||
.active=${e.path===(null==t?void 0:t.path)}
|
||||
.narrow=${this.narrow}
|
||||
.name=${e.translationKey?n(e.translationKey):e.name}
|
||||
>
|
||||
${e.iconPath?o`<ha-svg-icon
|
||||
slot="icon"
|
||||
.path=${e.iconPath}
|
||||
></ha-svg-icon>`:""}
|
||||
</ha-tab>
|
||||
</a>
|
||||
`))}))}},{kind:"method",key:"willUpdate",value:function(e){if(e.has("route")&&(this._activeTab=this.tabs.find((e=>`${this.route.prefix}${this.route.path}`.includes(e.path)))),e.has("hass")){const t=e.get("hass");t&&t.language===this.hass.language||(this.rtl=j(this.hass))}p(u(a.prototype),"willUpdate",this).call(this,e)}},{kind:"method",key:"render",value:function(){var e,t;const i=this._getTabs(this.tabs,this._activeTab,null===(e=this.hass.userData)||void 0===e?void 0:e.showAdvanced,this.hass.config.components,this.hass.language,this.narrow,this.localizeFunc||this.hass.localize),a=i.length>1;return o`
|
||||
<div class="toolbar">
|
||||
${this.mainPage||!this.backPath&&null!==(t=history.state)&&void 0!==t&&t.root?o`
|
||||
<ha-menu-button
|
||||
.hassio=${this.supervisor}
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
></ha-menu-button>
|
||||
`:this.backPath?o`
|
||||
<a href=${this.backPath}>
|
||||
<ha-icon-button-arrow-prev
|
||||
.hass=${this.hass}
|
||||
></ha-icon-button-arrow-prev>
|
||||
</a>
|
||||
`:o`
|
||||
<ha-icon-button-arrow-prev
|
||||
.hass=${this.hass}
|
||||
@click=${this._backTapped}
|
||||
></ha-icon-button-arrow-prev>
|
||||
`}
|
||||
${this.narrow||!a?o`<div class="main-title">
|
||||
<slot name="header">${a?"":i[0]}</slot>
|
||||
</div>`:""}
|
||||
${a?o`
|
||||
<div id="tabbar" class=${v({"bottom-bar":this.narrow})}>
|
||||
${i}
|
||||
</div>
|
||||
`:""}
|
||||
<div id="toolbar-icon">
|
||||
<slot name="toolbar-icon"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="content ${v({tabs:a})}"
|
||||
@scroll=${this._saveScrollPos}
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div id="fab" class=${v({tabs:a})}>
|
||||
<slot name="fab"></slot>
|
||||
</div>
|
||||
`}},{kind:"method",decorators:[l({passive:!0})],key:"_saveScrollPos",value:function(e){this._savedScrollPos=e.target.scrollTop}},{kind:"method",key:"_backTapped",value:function(){this.backCallback?this.backCallback():history.back()}},{kind:"get",static:!0,key:"styles",value:function(){return h`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
background-color: var(--primary-background-color);
|
||||
}
|
||||
|
||||
:host([narrow]) {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
ha-menu-button {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
height: var(--header-height);
|
||||
background-color: var(--sidebar-background-color);
|
||||
font-weight: 400;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.toolbar a {
|
||||
color: var(--sidebar-text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.bottom-bar a {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
#tabbar {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#tabbar > a {
|
||||
overflow: hidden;
|
||||
max-width: 45%;
|
||||
}
|
||||
|
||||
#tabbar.bottom-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--sidebar-background-color);
|
||||
border-top: 1px solid var(--divider-color);
|
||||
justify-content: space-around;
|
||||
z-index: 2;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
#tabbar:not(.bottom-bar) {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
:host(:not([narrow])) #toolbar-icon {
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
ha-menu-button,
|
||||
ha-icon-button-arrow-prev,
|
||||
::slotted([slot="toolbar-icon"]) {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
pointer-events: auto;
|
||||
color: var(--sidebar-icon-color);
|
||||
}
|
||||
|
||||
.main-title {
|
||||
flex: 1;
|
||||
max-height: var(--header-height);
|
||||
line-height: 20px;
|
||||
color: var(--sidebar-text-color);
|
||||
margin: var(--main-title-margin, 0 0 0 24px);
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
width: calc(
|
||||
100% - env(safe-area-inset-left) - env(safe-area-inset-right)
|
||||
);
|
||||
margin-left: env(safe-area-inset-left);
|
||||
margin-right: env(safe-area-inset-right);
|
||||
height: calc(100% - 1px - var(--header-height));
|
||||
height: calc(
|
||||
100% - 1px - var(--header-height) - env(safe-area-inset-bottom)
|
||||
);
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
:host([narrow]) .content.tabs {
|
||||
height: calc(100% - 2 * var(--header-height));
|
||||
height: calc(
|
||||
100% - 2 * var(--header-height) - env(safe-area-inset-bottom)
|
||||
);
|
||||
}
|
||||
|
||||
#fab {
|
||||
position: fixed;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
z-index: 1;
|
||||
}
|
||||
:host([narrow]) #fab.tabs {
|
||||
bottom: calc(84px + env(safe-area-inset-bottom));
|
||||
}
|
||||
#fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
:host([rtl]) #fab {
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
:host([rtl][is-wide]) #fab {
|
||||
bottom: 24px;
|
||||
left: 24px;
|
||||
right: auto;
|
||||
}
|
||||
`}}]}}),t);let E=e([c("hacs-store-panel")],(function(e,t){return{F:class extends t{constructor(...t){super(...t),e(this)}},d:[{kind:"field",decorators:[i({attribute:!1})],key:"filters",value:()=>({})},{kind:"field",decorators:[i({attribute:!1})],key:"hacs",value:void 0},{kind:"field",decorators:[i()],key:"_searchInput",value:()=>""},{kind:"field",decorators:[i({attribute:!1})],key:"hass",value:void 0},{kind:"field",decorators:[i({attribute:!1})],key:"narrow",value:void 0},{kind:"field",decorators:[i({attribute:!1})],key:"isWide",value:void 0},{kind:"field",decorators:[i({attribute:!1})],key:"route",value:void 0},{kind:"field",decorators:[i({attribute:!1})],key:"sections",value:void 0},{kind:"field",decorators:[i()],key:"section",value:void 0},{kind:"field",key:"_repositoriesInActiveSection",value(){return d(((e,t)=>[(null==e?void 0:e.filter((e=>{var i,a,s;return(null===(i=this.hacs.sections)||void 0===i||null===(a=i.find((e=>e.id===t)))||void 0===a||null===(s=a.categories)||void 0===s?void 0:s.includes(e.category))&&e.installed})))||[],(null==e?void 0:e.filter((e=>{var i,a,s;return(null===(i=this.hacs.sections)||void 0===i||null===(a=i.find((e=>e.id===t)))||void 0===a||null===(s=a.categories)||void 0===s?void 0:s.includes(e.category))&&e.new&&!e.installed})))||[]]))}},{kind:"get",key:"allRepositories",value:function(){const[e,t]=this._repositoriesInActiveSection(this.hacs.repositories,this.section);return t.concat(e)}},{kind:"field",key:"_filterRepositories",value:()=>d(z)},{kind:"get",key:"visibleRepositories",value:function(){const e=this.allRepositories.filter((e=>{var t,i;return null===(t=this.filters[this.section])||void 0===t||null===(i=t.find((t=>t.id===e.category)))||void 0===i?void 0:i.checked}));return this._filterRepositories(e,this._searchInput)}},{kind:"method",key:"firstUpdated",value:async function(){this.addEventListener("filter-change",(e=>this._updateFilters(e)))}},{kind:"method",key:"_updateFilters",value:function(e){var t;const i=null===(t=this.filters[this.section])||void 0===t?void 0:t.find((t=>t.id===e.detail.id));this.filters[this.section].find((e=>e.id===i.id)).checked=!i.checked,this.requestUpdate()}},{kind:"method",key:"render",value:function(){var e;if(!this.hacs)return o``;const t=this._repositoriesInActiveSection(this.hacs.repositories,this.section)[1];if(!this.filters[this.section]&&this.hacs.info.categories){var i;const e=null===(i=f(this.hacs.language,this.route))||void 0===i?void 0:i.categories;this.filters[this.section]=[],null==e||e.filter((e=>{var t;return null===(t=this.hacs.info)||void 0===t?void 0:t.categories.includes(e)})).forEach((e=>{this.filters[this.section].push({id:e,value:e,checked:!0})}))}return o`<hass-tabs-subpage
|
||||
back-path="/hacs/entry"
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
.tabs=${this.hacs.sections}
|
||||
hasFab
|
||||
>
|
||||
<ha-icon-overflow-menu
|
||||
slot="toolbar-icon"
|
||||
narrow
|
||||
.hass=${this.hass}
|
||||
.items=${[{path:b,label:this.hacs.localize("menu.documentation"),action:()=>m.open("https://hacs.xyz/","_blank","noreferrer=true")},{path:k,label:"GitHub",action:()=>m.open("https://github.com/hacs","_blank","noreferrer=true")},{path:g,label:this.hacs.localize("menu.open_issue"),action:()=>m.open("https://hacs.xyz/docs/issues","_blank","noreferrer=true")},{path:y,label:this.hacs.localize("menu.custom_repositories"),disabled:this.hacs.info.disabled_reason,action:()=>this.dispatchEvent(new CustomEvent("hacs-dialog",{detail:{type:"custom-repositories",repositories:this.hacs.repositories},bubbles:!0,composed:!0}))},{path:w,label:this.hacs.localize("menu.about"),action:()=>I(this,this.hacs)}]}
|
||||
>
|
||||
</ha-icon-overflow-menu>
|
||||
${this.narrow?o`
|
||||
<search-input
|
||||
.hass=${this.hass}
|
||||
class="header"
|
||||
slot="header"
|
||||
.label=${this.hacs.localize("search.downloaded")}
|
||||
.filter=${this._searchInput||""}
|
||||
@value-changed=${this._inputValueChanged}
|
||||
></search-input>
|
||||
`:o`<div class="search">
|
||||
<search-input
|
||||
.hass=${this.hass}
|
||||
.label=${0===t.length?this.hacs.localize("search.downloaded"):this.hacs.localize("search.downloaded_new")}
|
||||
.filter=${this._searchInput||""}
|
||||
@value-changed=${this._inputValueChanged}
|
||||
></search-input>
|
||||
</div>`}
|
||||
<div class="content ${this.narrow?"narrow-content":""}">
|
||||
${(null===(e=this.filters[this.section])||void 0===e?void 0:e.length)>1?o`<div class="filters">
|
||||
<hacs-filter
|
||||
.hacs=${this.hacs}
|
||||
.filters="${this.filters[this.section]}"
|
||||
></hacs-filter>
|
||||
</div>`:""}
|
||||
${null!=t&&t.length?o`<ha-alert .rtl=${j(this.hass)}>
|
||||
${this.hacs.localize("store.new_repositories_note")}
|
||||
<mwc-button
|
||||
class="max-content"
|
||||
slot="action"
|
||||
.label=${this.hacs.localize("menu.dismiss")}
|
||||
@click=${this._clearAllNewRepositories}
|
||||
>
|
||||
</mwc-button>
|
||||
</ha-alert> `:""}
|
||||
<div class="container ${this.narrow?"narrow":""}">
|
||||
${void 0===this.hacs.repositories?"":0===this.allRepositories.length?this._renderEmpty():0===this.visibleRepositories.length?this._renderNoResultsFound():this._renderRepositories()}
|
||||
</div>
|
||||
</div>
|
||||
<ha-fab
|
||||
slot="fab"
|
||||
.label=${this.hacs.localize("store.explore")}
|
||||
.extended=${!this.narrow}
|
||||
@click=${this._addRepository}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${x}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
</hass-tabs-subpage>`}},{kind:"method",key:"_renderRepositories",value:function(){return this.visibleRepositories.map((e=>o`<hacs-repository-card
|
||||
.hass=${this.hass}
|
||||
.hacs=${this.hacs}
|
||||
.repository=${e}
|
||||
.narrow=${this.narrow}
|
||||
?narrow=${this.narrow}
|
||||
></hacs-repository-card>`))}},{kind:"method",key:"_clearAllNewRepositories",value:async function(){var e;await $(this.hass,{categories:(null===(e=f(this.hacs.language,this.route))||void 0===e?void 0:e.categories)||[]})}},{kind:"method",key:"_renderNoResultsFound",value:function(){return o`<ha-alert
|
||||
.rtl=${j(this.hass)}
|
||||
alert-type="warning"
|
||||
.title="${this.hacs.localize("store.no_repositories")} 😕"
|
||||
>
|
||||
${this.hacs.localize("store.no_repositories_found_desc1",{searchInput:this._searchInput})}
|
||||
<br />
|
||||
${this.hacs.localize("store.no_repositories_found_desc2")}
|
||||
</ha-alert>`}},{kind:"method",key:"_renderEmpty",value:function(){return o`<ha-alert
|
||||
.title="${this.hacs.localize("store.no_repositories")} 😕"
|
||||
.rtl=${j(this.hass)}
|
||||
>
|
||||
${this.hacs.localize("store.no_repositories_desc1")}
|
||||
<br />
|
||||
${this.hacs.localize("store.no_repositories_desc2")}
|
||||
</ha-alert>`}},{kind:"method",key:"_inputValueChanged",value:function(e){this._searchInput=e.detail.value,window.localStorage.setItem("hacs-search",this._searchInput)}},{kind:"method",key:"_addRepository",value:function(){this.dispatchEvent(new CustomEvent("hacs-dialog",{detail:{type:"add-repository",repositories:this.hacs.repositories,section:this.section},bubbles:!0,composed:!0}))}},{kind:"get",static:!0,key:"styles",value:function(){return[_,R,h`
|
||||
.filter {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
.content {
|
||||
height: calc(100vh - 128px);
|
||||
overflow: auto;
|
||||
}
|
||||
.narrow-content {
|
||||
height: calc(100vh - 128px);
|
||||
}
|
||||
.container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(480px, 1fr));
|
||||
justify-items: center;
|
||||
grid-gap: 8px 8px;
|
||||
padding: 8px 16px 16px;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
ha-svg-icon {
|
||||
color: var(--hcv-text-color-on-background);
|
||||
}
|
||||
hacs-repository-card {
|
||||
max-width: 500px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
hacs-repository-card[narrow] {
|
||||
width: 100%;
|
||||
}
|
||||
hacs-repository-card[narrow]:last-of-type {
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
ha-alert {
|
||||
color: var(--hcv-text-color-primary);
|
||||
display: block;
|
||||
margin-top: -4px;
|
||||
}
|
||||
.narrow {
|
||||
width: 100%;
|
||||
display: block;
|
||||
padding: 0px;
|
||||
margin: 0;
|
||||
}
|
||||
search-input {
|
||||
display: block;
|
||||
}
|
||||
|
||||
search-input.header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed !important;
|
||||
}
|
||||
.max-content {
|
||||
width: max-content;
|
||||
}
|
||||
`]}}]}}),t);export{E as HacsStorePanel};
|
||||
File diff suppressed because one or more lines are too long
16
config/custom_components/hacs/hacs_frontend/c.11ad1623.js
Normal file
16
config/custom_components/hacs/hacs_frontend/c.11ad1623.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import{a as e,e as t,i,L as a,N as d,$ as r,r as n,n as o}from"./main-ad130be7.js";import{H as s}from"./c.0a1cf8d0.js";e([o("ha-clickable-list-item")],(function(e,o){class s extends o{constructor(...t){super(...t),e(this)}}return{F:s,d:[{kind:"field",decorators:[t()],key:"href",value:void 0},{kind:"field",decorators:[t({type:Boolean})],key:"disableHref",value:()=>!1},{kind:"field",decorators:[t({type:Boolean,reflect:!0})],key:"openNewTab",value:()=>!1},{kind:"field",decorators:[i("a")],key:"_anchor",value:void 0},{kind:"method",key:"render",value:function(){const e=a(d(s.prototype),"render",this).call(this),t=this.href||"";return r`${this.disableHref?r`<a aria-role="option">${e}</a>`:r`<a
|
||||
aria-role="option"
|
||||
target=${this.openNewTab?"_blank":""}
|
||||
href=${t}
|
||||
>${e}</a
|
||||
>`}`}},{kind:"method",key:"firstUpdated",value:function(){a(d(s.prototype),"firstUpdated",this).call(this),this.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||this._anchor.click()}))}},{kind:"get",static:!0,key:"styles",value:function(){return[a(d(s),"styles",this),n`
|
||||
a {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: var(--mdc-list-side-padding, 20px);
|
||||
padding-right: var(--mdc-list-side-padding, 20px);
|
||||
overflow: hidden;
|
||||
}
|
||||
`]}}]}}),s);
|
||||
540
config/custom_components/hacs/hacs_frontend/c.14dc9dca.js
Normal file
540
config/custom_components/hacs/hacs_frontend/c.14dc9dca.js
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
const n=(n,o)=>n&&n.config.components.includes(o);export{n as i};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{al as e,am as a,aj as s,an as r,ao as u}from"./main-ad130be7.js";async function i(i,o,n){const t=new e("updateLovelaceResources"),l=await a(i),d=`/hacsfiles/${o.full_name.split("/")[1]}`,c=s({repository:o,version:n}),p=l.find((e=>e.url.includes(d)));t.debug({namespace:d,url:c,exsisting:p}),p&&p.url!==c?(t.debug(`Updating exsusting resource for ${d}`),await r(i,{url:c,resource_id:p.id,res_type:p.type})):l.map((e=>e.url)).includes(c)||(t.debug(`Adding ${c} to Lovelace resources`),await u(i,{url:c,res_type:"module"}))}export{i as u};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user