Added vwfriend ha evcc

This commit is contained in:
Simon 2023-09-21 09:25:11 +02:00
parent e4d75f78ad
commit b93e84b8c3
35 changed files with 4247 additions and 73 deletions

18
.env
View File

@ -1,5 +1,5 @@
UID=1000
GID=1000
GID=1004
DIR=/srv/docker
DOMAIN=milvert.com
DOMAIN_PEEK=peekskog.se
@ -30,10 +30,24 @@ LIBRESPEED_PW=NDVlMzA0MzQ0YmM3NTA0OGIxMzEzMjk4
PIHOLE_PW=NmE4Njc4Y2RjMmUxZmIxMWZkOTg1NTZj
UUID=1000
PGID=1000
PGID=1004
TZ=Europe/Stockholm
TGRAMAPI=5306622927:AAGsDD83H1joum_hlTiCtSFWwIyM3nEEntU
TGRAMCHAT=-1005306622927
TGRAM_SHOUTRRR_ADDRESS=telegram://5306622927:AAGsDD83H1joum_hlTiCtSFWwIyM3nEEntU@telegram?chats=-1001662562579
VWSFRIEND_USERNAME='admin'
VWSFRIEND_HOSTNAME='vwsfriend'
VWSFRIEND_PASSWORD='bajsa123'
WECONNECT_USER='simon@milvert.com'
WECONNECT_PASSWORD='khLe86qM925qkB'
WECONNECT_SPIN=9331
WECONNECT_INTERVAL=180
VW_DB_HOSTNAME='postgres'
VW_DB_NAME='vwfriend'
VW_DB_USER='vwfriend'
VW_DB_PASSWORD='icCJ8iwKJBeRBg'
ADDITIONAL_PARAMETERS=-vv --mqttbroker mqtt --mqttport 1883 -mu simon -mp bajsa123

View File

@ -54,7 +54,7 @@ services:
- PUID=${UID}
- PGID=${GID}
labels:
- "traefik.enable=true"
- "traefik.enable=false"
- "traefik.http.services.landet_domo-service.loadbalancer.server.port=8080"
- "traefik.http.routers.landet_domo-secure.entrypoints=web-secure"
- "traefik.http.routers.landet_domo-secure.rule=Host(`landet.${DOMAIN}`)"

View File

@ -11,7 +11,7 @@ services:
max-file: "3"
networks:
- backend
image: koenkk/zigbee2mqtt:1.30.4
image: koenkk/zigbee2mqtt:1.32.0
restart: always
volumes:
- ./zigbee_home_2:/app/data
@ -41,7 +41,7 @@ services:
max-file: "5"
networks:
- backend
image: koenkk/zigbee2mqtt:1.30.4
image: koenkk/zigbee2mqtt:1.32.0
restart: always
volumes:
- ${DIR}/zigbee2matt:/app/data
@ -63,30 +63,6 @@ services:
- "traefik.http.routers.zig1-secure.middlewares=chain-authelia@file"
- "traefik.http.routers.zig1-secure.tls=true"
grafana:
image: grafana/grafana:9.3.6
container_name: grafana
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
restart: always
networks:
- backend
volumes:
- ./grafana/grafana.ini:/etc/grafana/grafana.ini
# Data persistency
# sudo mkdir -p /srv/docker/grafana/data; chown 472:472 /srv/docker/grafana/data
- "${DIR}/grafana:/var/lib/grafana"
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.routers.grafana-secure.entrypoints=web-secure"
- "traefik.http.routers.grafana-secure.rule=Host(`data.${DOMAIN}`)"
- "traefik.http.routers.grafana-secure.middlewares=chain-no-auth@file"
- "traefik.http.routers.grafana-secure.tls.certresolver=milvert_dns"
- "traefik.http.routers.grafana-secure.tls=true"
influx:
image: influxdb:2.6
@ -195,7 +171,7 @@ services:
mqtt:
# image: eclipse-mosquitto:1.6.13
image: eclipse-mosquitto:2.0
image: eclipse-mosquitto:2.0.17
container_name: mqtt
logging:
driver: "json-file"
@ -203,7 +179,6 @@ services:
max-size: "10m"
max-file: "5"
networks:
- frontend
- backend
restart: always
ports:
@ -327,10 +302,6 @@ services:
restart: unless-stopped
networks:
backend:
backend_macvlan:
ipv4_address: 10.0.0.201
pihole_net:
ipv4_address: 10.0.5.3
labels:
- diun.enable=true
- "traefik.enable=true"
@ -348,15 +319,3 @@ networks:
external: true
backend:
external: false
backend_macvlan:
driver: macvlan
driver_opts:
parent: eno1
ipam:
config:
- subnet: 10.0.0.200/27
pihole_net:
driver: bridge
ipam:
config:
- subnet: 10.0.5.0/29

View File

@ -13,6 +13,10 @@ secrets:
file: $SECRETSDIR/authelia_notifier_smtp_password
authelia_duo_api_secret_key:
file: $SECRETSDIR/authelia_duo_api_secret_key
vwfriend_password:
file: $SECRETSDIR/vwfriend_password
vwconnect_password:
file: $SECRETSDIR/vwconnect_password
########################### EXTENSION FIELDS ##########################
@ -21,8 +25,8 @@ secrets:
#######################################################################
x-environment: &default-tz-puid-pgid
- TZ=$TZ
- PUID=$PUID
- PGID=$PGID
- PUID=${UID}
- PGID=${GID}
x-common-keys-monitoring: &common-keys-monitoring
networks:
@ -85,7 +89,6 @@ services:
- ./notify.txt:/tmp/authelia/notification.txt
networks:
- backend
- frontend
ports:
# The HTTP port
- "9091:9091"
@ -252,9 +255,272 @@ services:
#entrypoint: redis-server --appendonly yes --requirepass $REDIS_PASSWORD --maxmemory 512mb --maxmemory-policy allkeys-lru
labels:
- diun.enable=true
######################### HOME ############################
#
# HOME
#
###############################################################
ha:
container_name: ha
image: homeassistant/home-assistant:2023.8
restart: always
privileged: true
networks:
backend:
docker_vlan:
ipv4_address: 10.0.0.203
depends_on:
- postgres
ports:
- 8123:8123
volumes:
- ./ha/config:/config
- /etc/localtime:/etc/localtime:ro
environment:
- PUID=${UUID}
- PGID=${PGID}
- TZ=${TZ}
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.routers.ha.entrypoints=web-secure"
- "traefik.http.routers.ha.rule=Host(`ha.${DOMAIN}`)"
- "traefik.http.routers.ha.middlewares=chain-no-auth@file"
- "traefik.http.routers.ha.tls.certresolver=milvert_dns"
- "traefik.http.routers.ha.tls=true"
- "traefik.http.services.ha.loadbalancer.server.port=8123"
hassconf:
container_name: hassconf
image: causticlab/hass-configurator-docker:0.5.2
restart: unless-stopped
networks:
- backend
ports:
- 3218:3218
volumes:
- ./ha/hass_config:/config
- ./ha/config:/hass-config
depends_on:
- ha
labels:
- diun.enable=true
environment:
- PUID=${UUID}
- PGID=${PGID}
- TZ=${TZ}
appdaemon:
container_name: appdaemon
image: acockburn/appdaemon:4.4.2
restart: unless-stopped
depends_on:
- ha
labels:
- diun.enable=true
volumes:
- ./ha/appdaemon_config:/conf
- /etc/localtime:/etc/localtime:ro
ports:
- 5050:5050
networks:
- backend
environment:
- PUID=${UUID}
- PGID=${PGID}
- TZ=${TZ}
# The following values ar overridden in docker-compose.override.yml
- HA_URL=http://ha:8123
- DASH_URL=http://appdaemon:5050
- TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmZmM0YTI1ZjVlYWM0NGY5OTA3OGFmOWJiMTJmYmUzZCIsImlhdCI6MTY5MzczMDQwNSwiZXhwIjoyMDA5MDkwNDA1fQ.YVH8WhH6FMvTkecJ-taCACP6kVG9is2hHmTR3tk3cns
evcc:
command:
- evcc
container_name: evcc
image: evcc/evcc:0.120.0
ports:
- 7070:7070/tcp
dns:
- 8.8.8.8
volumes:
- "./evcc/evcc.yaml:/etc/evcc.yaml:ro"
- ./evcc/evcc:/root/.evcc
restart: unless-stopped
networks:
- backend
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.routers.evcc.entrypoints=web-secure"
- "traefik.http.routers.evcc.rule=Host(`box.${DOMAIN}`)"
- "traefik.http.services.evcc.loadbalancer.server.port=7070"
- "traefik.http.routers.evcc.middlewares=chain-no-auth@file"
- "traefik.http.routers.evcc.tls.certresolver=milvert_dns"
- "traefik.http.routers.evcc.tls=true"
grafana:
image: grafana/grafana:10.0.0
container_name: grafana
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
restart: always
networks:
- backend
volumes:
- ./grafana/grafana.ini:/etc/grafana/grafana.ini
# Data persistency
# sudo mkdir -p /srv/docker/grafana/data; chown 472:472 /srv/docker/grafana/data
- "${DIR}/grafana:/var/lib/grafana"
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.routers.grafana-secure.entrypoints=web-secure"
- "traefik.http.routers.grafana-secure.rule=Host(`data.${DOMAIN}`)"
- "traefik.http.routers.grafana-secure.middlewares=chain-no-auth@file"
- "traefik.http.routers.grafana-secure.tls.certresolver=milvert_dns"
- "traefik.http.routers.grafana-secure.tls=true"
######################### WEB ############################
#
# WEB
#
###############################################################
librespeed:
image: ghcr.io/linuxserver/librespeed:5.2.5
container_name: librespeed
environment:
- PUID=${UUID}
- PGID=${PGID}
- TZ=${TZ}
- PASSWORD=${LIBRESPEED_PW}
- CUSTOM_RESULTS=false
- DB_TYPE=sqlite
volumes:
- ./librespeed/config:/config
restart: unless-stopped
networks:
- backend
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.routers.librespeed.entrypoints=web-secure"
- "traefik.http.routers.librespeed.rule=Host(`librespeed.${DOMAIN}`)"
- "traefik.http.routers.librespeed.middlewares=chain-authelia@file"
- "traefik.http.routers.librespeed.tls.certresolver=milvert_dns"
- "traefik.http.routers.librespeed.tls=true"
vwsfriend:
image: tillsteinbach/vwsfriend:0.23.11
container_name: vwfriend
ports:
- ${VWSFRIEND_PORT-4000}:${VWSFRIEND_PORT-4000}
networks:
- backend
volumes:
- ./vwsfriend_data:/config
environment:
- VWSFRIEND_USERNAME=${VWSFRIEND_USERNAME-admin}
- VWSFRIEND_PASSWORD=${VWSFRIEND_PASSWORD}
- VWSFRIEND_PORT=${VWSFRIEND_PORT-4000}
- WECONNECT_USER
- WECONNECT_PASSWORD
- WECONNECT_SPIN
- WECONNECT_INTERVAL
- DATABASE_URL=postgresql://${VW_DB_USER}:${VW_DB_PASSWORD}@${VW_DB_HOSTNAME}:5432/${VW_DB_NAME}
- ADDITIONAL_PARAMETERS=--with-database --with-abrp ${ADDITIONAL_PARAMETERS}
depends_on:
- postgres
restart: unless-stopped
dns:
- 8.8.8.8
healthcheck:
test: (wget -qO- http://localhost:${VWSFRIEND_PORT-4000}/healthcheck | grep "ok" -q) || exit 1
interval: 60s
timeout: 10s
retries: 3
secrets:
- vwfriend_password
- vwconnect_password
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.services.vwsfriend-service.loadbalancer.server.port=4000"
- "traefik.http.routers.vwsfriend.entrypoints=web-secure"
- "traefik.http.routers.vwsfriend.rule=Host(`vw.${DOMAIN}`)"
- "traefik.http.routers.vwsfriend.middlewares=chain-no-auth@file"
- "traefik.http.routers.vwsfriend.tls.certresolver=milvert_dns"
- "traefik.http.routers.vwsfriend.tls=true"
vwgrafana:
image: tillsteinbach/vwsfriend-grafana:0.23.11
container_name: vwgrafana
ports:
- ${GF_SERVER_HTTP_PORT-3001}:${GF_SERVER_HTTP_PORT-3000}
networks:
backend:
volumes:
- ./vwfriend_grafana/data:/var/lib/grafana
- ./vwfriend_grafana/dashboard:/home/grafana/dummy
environment:
- PUID=${UUID}
- PGID=${PGID}
- TZ=${TZ}
- GF_SECURITY_ADMIN_USER=${VWSFRIEND_USERNAME-admin}
- GF_SECURITY_ADMIN_PASSWORD=${VWSFRIEND_PASSWORD-secret}
- GF_SERVER_HTTP_PORT=${GF_SERVER_HTTP_PORT-3000}
- DB_USER=${VW_DB_USER-admin}
- DB_PASSWORD=${VW_DB_PASSWORD-secret}
- DB_HOSTNAME=${vw_DB_HOSTNAME-postgres}
- DB_PORT=${DB_PORT-5432}
- DB_NAME=${VW_DB_NAME-vwsfriend}
- VWSFRIEND_USERNAME=${VWSFRIEND_USERNAME-admin}
- VWSFRIEND_PASSWORD=${VWSFRIEND_PASSWORD-secret}
- VWSFRIEND_HOSTNAME=${VWSFRIEND_HOSTNAME-vwsfriendbackend}
- VWSFRIEND_PORT=${VWSFRIEND_PORT-4000}
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "(wget -qO- http://localhost:${GF_SERVER_HTTP_PORT-3000}/api/health | grep '\"database\": \"ok\"' -q) || exit 1"]
interval: 60s
timeout: 10s
retries: 3
labels:
- diun.enable=true
- "traefik.enable=true"
- "traefik.http.services.vwgrafana.loadbalancer.server.port=3000"
- "traefik.http.routers.vwgrafana.entrypoints=web-secure"
- "traefik.http.routers.vwgrafana.rule=Host(`vwgrafana.${DOMAIN}`)"
- "traefik.http.routers.vwgrafana.middlewares=chain-no-auth@file"
- "traefik.http.routers.vwgrafana.tls.certresolver=milvert_dns"
- "traefik.http.routers.vwgrafana.tls=true"
networks:
frontend:
external: true
backend:
external: false
# MACVLAN guide: https://blog.oddbit.com/post/2018-03-12-using-docker-macvlan-networks/
# ip link add vlan-shim link eno1 type macvlan mode bridge
# ip addr add 10.0.0.223/32 dev vlan-shim
# ip link set vlan-shim up
# ip route add 10.0.0.192/27 dev vlan-shim
docker_vlan:
external: true
driver: macvlan
driver_opts:
parent: eno1
ipam:
config:
- subnet: 10.0.0.200/27
volumes:
vwfriend_grafana:

133
evcc/evcc.yaml Normal file
View File

@ -0,0 +1,133 @@
sponsortoken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODEzODIyNTYsImlhdCI6MTY4Njc3NDI1NiwiaXNzIjoiZXZjYy5pbyIsInN1YiI6Im1pbHZlcnQifQ.HUEmc0NSPt9x5MbOHUAGU6bp3H3E3qwu6O6BAHH9FvE
#log: debug
#levels:
# easee: trace
interval: 30s
vehicles:
- name: car
type: custom
title: id4
capacity: 79 # kWh
soc:
source: mqtt
topic: weconnect/0/vehicles/WVGZZZE2ZPE051949/domains/fuelStatus/rangeStatus/primaryEngine/currentSOC_pct
range:
source: mqtt
topic: weconnect/0/vehicles/WVGZZZE2ZPE051949/domains/fuelStatus/rangeStatus/primaryEngine/remainingRange_km
onIdentify: # set defaults when vehicle is identified
mode: pv # enable PV-charging when vehicle is identified
minSoC: 20 # immediately charge to 0% regardless of mode unless "off" (disabled)
targetSoC: 90 # limit charge to 90%
chargers:
- name: wallbox
type: easee
user: simon+easee@milvert.com
password: X7#aEzjlEysBgl
charger: EHCNF485
loadpoints:
- title: Garage
charger: wallbox
vehicle: car
mode: pv
phases: 3
mincurrent: 6
maxcurrent: 16
resetOnDisconnect: True
enable:
threshold: 0
delay: 15s
disable:
threshold: 500
delay:
2m
site:
title: Hemma
meters:
pv:
- pv
grid: my_grid
meters:
- name: pv
type: custom
power:
source: mqtt
topic: inverter/measure/active_power
jq: .value
energy:
source: mqtt
topic: inverter/calculated/accumulated_yield_energy
jq: .value
timeout: 1h
currents:
- source: mqtt
topic: inverter/measure/phase_A_current
jq: .value
- source: mqtt
topic: inverter/measure/phase_B_current
jq: .value
- source: mqtt
topic: inverter/measure/phase_C_current
jq: .value
- name: my_grid
type: custom
power:
source: calc
add:
- source: mqtt
topic: dsmr/reading/electricity_currently_returned
scale: -1000
- source: mqtt
topic: dsmr/reading/electricity_currently_delivered
scale: 1000
energy:
source: calc
add:
- source: mqtt
topic: dsmr/reading/electricity_returned
scale: 0.001
- source: mqtt
topic: dsmr/reading/electricity_delivered
scale: -0.001
currents:
- source: calc
add:
- source: mqtt
topic: dsmr/reading/phase_currently_delivered_l1
scale: -1
- source: mqtt
topic: dsmr/reading/phase_currently_returned_l1
- source: calc
add:
- source: mqtt
topic: dsmr/reading/phase_currently_delivered_l2
scale: -1
- source: mqtt
topic: dsmr/reading/phase_currently_returned_l2
- source: calc
add:
- source: mqtt
topic: dsmr/reading/phase_currently_delivered_l3
scale: -1
- source: mqtt
topic: dsmr/reading/phase_currently_returned_l3
influx:
url: http://influx:8086
database: Car
token: H7m068KDh84kcmmkz3fy-dEsKoeYv90rnNXIidPZoBy240Jzdbr2uDtGveiuDz4rGK4jmMI8J00zVwgIBYJxXA==
org: milvert
mqtt:
broker: mqtt:1883
user: simon
password: bajsa123
topic: evcc

BIN
evcc/evcc/evcc.db Normal file

Binary file not shown.

View File

@ -0,0 +1,18 @@
appdaemon:
latitude: 0
longitude: 0
elevation: 30
time_zone: Europe/Berlin
plugins:
HASS:
type: hass
ha_url: http://ha:8123
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmZmM0YTI1ZjVlYWM0NGY5OTA3OGFmOWJiMTJmYmUzZCIsImlhdCI6MTY5MzczMDQwNSwiZXhwIjoyMDA5MDkwNDA1fQ.YVH8WhH6FMvTkecJ-taCACP6kVG9is2hHmTR3tk3cns
cert_verify: False
loglevel: DEBUG
module_debug:
http:
url: http://appdaemon:5050
admin:
api:
hadashboard:

View File

@ -0,0 +1,3 @@
hello_world:
module: hello
class: HelloWorld

View File

@ -0,0 +1,3 @@
hello_world:
module: hello
class: HelloWorld

View File

@ -0,0 +1,13 @@
import hassapi as hass
#
# Hello World App
#
# Args:
#
class HelloWorld(hass.Hass):
def initialize(self):
self.log("Hello from AppDaemon")
self.log("You are now ready to run Apps!")

View File

@ -0,0 +1,240 @@
html {
font-size: 100%;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
padding: 0;
}
body {
margin: 0;
background-color: #222;
font-size: 15px;
color: #fff;
padding: 0;
line-height: 1;
font-family: 'Helvetica Neue', 'Helvetica', 'Open Sans', 'Arial'
}
b, strong {
font-weight: bold;
}
a {
text-decoration: none;
color: inherit;
}
img {
border: 0;
-ms-interpolation-mode: bicubic;
vertical-align: middle;
}
img, object {
max-width: 100%;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;}
iframe {
max-width: 100%;
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
td {
vertical-align: middle;
}
ul, ol {
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, p {
padding: 0;
margin: 0;
}
h1 {
margin-bottom: 6px;
text-align: center;
font-size: 100%;
font-weight: 200;
}
h2 {
font-size: 300%;
font-weight: 400;
color: #fff;
}
h3 {
font-size: 125%;
font-weight: 300;
color: #fff;
}
input {
background-color: #444;
border: none;
}
.dashboard_main {
margin: 0px auto;
}
.gridster {
margin: 0px auto;
}
.icon-background {
pointer-events: none;
width: 100%!important;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: 0.1;
font-size: 1375%;
text-align: center;
margin-top: 82px;
}
.list-nostyle {
list-style: none;
}
.gridster ul {
list-style: none;
}
.gs-w {
width: 100%;
display: table;
cursor: pointer;
z-index: auto !important;
}
.iframe {
position: relative;
overflow: hidden;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;}
.widget {
padding: 0px 0px;
text-align: center;
width: 100%;
display: table-cell;
vertical-align: middle;
background-color: #444444;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;}
.title {
color: #fff;
}
.icon-inactive {
color: #888;
}
.icon-active {
color: #aaff00;
}
#container {
padding-top: 0px;
}
.modalDialog {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0,0,0,0.8);
z-index: 9999;
opacity:0;
-webkit-transition: opacity 400ms ease-in;
-moz-transition: opacity 400ms ease-in;
transition: opacity 400ms ease-in;
pointer-events: none;
}
.modalDialogOpen {
opacity:0.95;
pointer-events: auto;
}
.modalDialogClose {
opacity:0;
pointer-events: none;
}
.modalDialog > div {
width: 275px;
position: relative;
margin: 3% auto;
padding: 5px 20px 13px 20px;
border-radius: 10px;
}
.modalDialogCloseButton {
line-height: 50px;
position: absolute;
right: -25px;
text-align: center;
top: -20px;
width: 50px;
text-decoration: none;
font-weight: bold;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
}
.modalDialogCloseButton:hover { background: #444; }
.widget-basedisplay-default-label .unit {
font-size: 225%;
font-weight: 400;
display: inline-block;
vertical-align: top;
margin-left: 5px;
margin-top: 5px;
}
.widget-basedisplay-default-label .value {
display: inline-block;
vertical-align: middle;
}
.widget-basedisplay-default-label .valueunit {
width: 100%;
vertical-align: middle;
}
.widget-basedisplay-default-label .title {
position: absolute;
top: 5px;
width: 100%;
}
.widget-basedisplay-default-label .title2 {
position: absolute;
top: 23px;
width: 100%;
}
.widget-basedisplay-default-label .state_text {
position: absolute;
bottom: -3px;
width: 100%;
}

View File

@ -0,0 +1,6 @@
<! body tags ->
<! body tags go here ->

View File

@ -0,0 +1,6 @@
<! head tags ->
<! head tags go here ->

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
var myDeviceID;
$(function(){ //DOM Ready
function navigate(url)
{
window.location.href = url;
}
$(document).attr("title", "Hello Panel");
content_width = (120 + 5) * 8 + 5
$('.gridster').width(content_width)
$(".gridster ul").gridster({
widget_margins: [5, 5],
widget_base_dimensions: [120, 120],
avoid_overlapped_widgets: true,
max_rows: 15,
max_size_x: 8,
shift_widgets_up: false
}).data('gridster').disable();
// Add Widgets
var gridster = $(".gridster ul").gridster().data('gridster');
gridster.add_widget('<li><div data-bind="attr: {style: widget_style}" class="widget widget-basedisplay-default-label" id="default-label"><h1 class="title" data-bind="text: title, attr:{ style: title_style}"></h1><h1 class="title2" data-bind="text: title2, attr:{ style: title2_style}"></h1><div class="valueunit" data-bind="attr:{ style: container_style}"><h2 class="value" data-bind="html: value, attr:{ style: value_style}"></h2><p class="unit" data-bind="html: unit, attr:{ style: unit_style}"></p></div><h1 class="state_text" data-bind="text: state_text, attr: {style: state_text_style}"></h1></div></li>', 2, 2, 1, 1)
var widgets = {}
// Initialize Widgets
widgets["default-label"] = new basedisplay("default-label", "", "default", {'widget_type': 'basedisplay', 'fields': {'title': '', 'title2': '', 'value': 'Hello World', 'unit': '', 'state_text': ''}, 'static_css': {'title_style': 'color: #fff;', 'title2_style': 'color: #fff;', 'unit_style': '', 'value_style': 'color: #fff;', 'state_text_style': 'color: #fff;', 'widget_style': 'background-color: #444;', 'container_style': ''}, 'css': {}, 'icons': [], 'static_icons': [], 'namespace': 'default'})
// Setup click handler to cancel timeout navigations
$( ".gridster" ).click(function(){
clearTimeout(myTimeout);
if (myTimeoutSticky) {
myTimeout = setTimeout(function() { navigate(myTimeoutUrl); }, myTimeoutDelay);
}
});
// Set up timeout
var myTimeout;
var myTimeoutUrl;
var myTimeoutDelay;
var myTimeoutSticky = 0;
if (location.search != "")
{
console.log("begin")
var query = location.search.substr(1);
var result = {};
query.split("&").forEach(function(part) {
var item = part.split("=");
result[item[0]] = decodeURIComponent(item[1]);
});
if ("deviceid" in result)
{
myDeviceID = result.deviceid;
try
{
setCookie('ADdevID', myDeviceID);
}
catch (e)
{
console.log(e);
}
}
else
{
try
{
myDeviceID = getCookie('ADdevID');
}
catch (e)
{
console.log(e);
myDeviceID = null;
}
}
if ("timeout" in result && "return" in result)
{
url = result.return
argcount = 0
for (arg in result)
{
if (arg != "timeout" && arg != "return" && arg != "sticky")
{
if (argcount == 0)
{
url += "?";
}
else
{
url += "&";
}
argcount ++;
url += arg + "=" + result[arg]
}
}
if ("sticky" in result)
{
myTimeoutSticky = (result.sticky == "1");
}
myTimeoutUrl = url;
myTimeoutDelay = result.timeout * 1000;
myTimeout = setTimeout(function() { navigate(url); }, result.timeout * 1000);
}
}
else
{
try
{
myDeviceID = getCookie('ADdevID');
}
catch (e)
{
console.log(e);
myDeviceID = null;
}
}
// Start listening for AD Events
window.dashstream = new DashStream("ws", location.protocol, document.domain, location.port, "Hello Panel", widgets);
});

View File

@ -0,0 +1,14 @@
#
# Main arguments, all optional
#
title: Hello Panel
widget_dimensions: [120, 120]
widget_margins: [5, 5]
columns: 8
label:
widget_type: label
text: Hello World
layout:
- label(2x2)

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1,55 @@
blueprint:
name: Motion-activated Light
description: Turn on a light when motion is detected.
domain: automation
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/motion_light.yaml
author: Home Assistant
input:
motion_entity:
name: Motion Sensor
selector:
entity:
domain: binary_sensor
device_class: motion
light_target:
name: Light
selector:
target:
entity:
domain: light
no_motion_wait:
name: Wait time
description: Time to leave the light on after last motion is detected.
default: 120
selector:
number:
min: 0
max: 3600
unit_of_measurement: seconds
# If motion is detected within the delay,
# we restart the script.
mode: restart
max_exceeded: silent
trigger:
platform: state
entity_id: !input motion_entity
from: "off"
to: "on"
action:
- alias: "Turn on the light"
service: light.turn_on
target: !input light_target
- alias: "Wait until there is no motion from device"
wait_for_trigger:
platform: state
entity_id: !input motion_entity
from: "on"
to: "off"
- alias: "Wait the number of seconds that has been set"
delay: !input no_motion_wait
- alias: "Turn off the light"
service: light.turn_off
target: !input light_target

View File

@ -0,0 +1,47 @@
blueprint:
name: Zone Notification
description: Send a notification to a device when a person leaves a specific zone.
domain: automation
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/notify_leaving_zone.yaml
author: Home Assistant
input:
person_entity:
name: Person
selector:
entity:
domain: person
zone_entity:
name: Zone
selector:
entity:
domain: zone
notify_device:
name: Device to notify
description: Device needs to run the official Home Assistant app to receive notifications.
selector:
device:
integration: mobile_app
trigger:
platform: state
entity_id: !input person_entity
variables:
zone_entity: !input zone_entity
# This is the state of the person when it's in this zone.
zone_state: "{{ states[zone_entity].name }}"
person_entity: !input person_entity
person_name: "{{ states[person_entity].name }}"
condition:
condition: template
# The first case handles leaving the Home zone which has a special state when zoning called 'home'.
# The second case handles leaving all other zones.
value_template: "{{ zone_entity == 'zone.home' and trigger.from_state.state == 'home' and trigger.to_state.state != 'home' or trigger.from_state.state == zone_state and trigger.to_state.state != zone_state }}"
action:
- alias: "Notify that a person has left the zone"
domain: mobile_app
type: notify
device_id: !input notify_device
message: "{{ person_name }} has left {{ zone_state }}"

View File

@ -0,0 +1,85 @@
blueprint:
name: Confirmable Notification
description: >-
A script that sends an actionable notification with a confirmation before
running the specified action.
domain: script
source_url: https://github.com/home-assistant/core/blob/master/homeassistant/components/script/blueprints/confirmable_notification.yaml
author: Home Assistant
input:
notify_device:
name: Device to notify
description: Device needs to run the official Home Assistant app to receive notifications.
selector:
device:
integration: mobile_app
title:
name: "Title"
description: "The title of the button shown in the notification."
default: ""
selector:
text:
message:
name: "Message"
description: "The message body"
selector:
text:
confirm_text:
name: "Confirmation Text"
description: "Text to show on the confirmation button"
default: "Confirm"
selector:
text:
confirm_action:
name: "Confirmation Action"
description: "Action to run when notification is confirmed"
default: []
selector:
action:
dismiss_text:
name: "Dismiss Text"
description: "Text to show on the dismiss button"
default: "Dismiss"
selector:
text:
dismiss_action:
name: "Dismiss Action"
description: "Action to run when notification is dismissed"
default: []
selector:
action:
mode: restart
sequence:
- alias: "Set up variables"
variables:
action_confirm: "{{ 'CONFIRM_' ~ context.id }}"
action_dismiss: "{{ 'DISMISS_' ~ context.id }}"
- alias: "Send notification"
domain: mobile_app
type: notify
device_id: !input notify_device
title: !input title
message: !input message
data:
actions:
- action: "{{ action_confirm }}"
title: !input confirm_text
- action: "{{ action_dismiss }}"
title: !input dismiss_text
- alias: "Awaiting response"
wait_for_trigger:
- platform: event
event_type: mobile_app_notification_action
event_data:
action: "{{ action_confirm }}"
- platform: event
event_type: mobile_app_notification_action
event_data:
action: "{{ action_dismiss }}"
- choose:
- conditions: "{{ wait.trigger.event.data.action == action_confirm }}"
sequence: !input confirm_action
- conditions: "{{ wait.trigger.event.data.action == action_dismiss }}"
sequence: !input dismiss_action

View File

@ -0,0 +1,35 @@
# Loads default set of integrations. Do not remove.
default_config:
# Load frontend themes from the themes folder
frontend:
themes: !include_dir_merge_named themes
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
homeassistant:
external_url: https://ha.milvert.com
auth_providers:
- type: homeassistant
- type: legacy_api_password
api_password: !secret http_password
http:
use_x_forwarded_for: true
ip_ban_enabled: false
trusted_proxies:
- 172.19.0.26
- 10.0.0.223
- 172.19.0.39
panel_iframe:
configurator:
title: Configurator
icon: mdi:wrench
url: http://10.0.0.3:3218
require_admin: true

@ -0,0 +1 @@
Subproject commit 1e383bbca8eac8d3d6d50e291ba4130a3eee4ee9

0
ha/config/scenes.yaml Normal file
View File

0
ha/config/scripts.yaml Normal file
View File

5
ha/config/secrets.yaml Normal file
View File

@ -0,0 +1,5 @@
# Use this file to store secrets like usernames and passwords.
# Learn more at https://www.home-assistant.io/docs/configuration/secrets/
some_password: welcome
http_password: mGwmLFbniCZz7t8JUhGT

View File

@ -0,0 +1,5 @@
{
"BASEPATH": "/hass-config",
"ENFORCE_BASEPATH": true,
"DIRSFIRST": true
}

View File

@ -1,4 +1,4 @@
## Version 2022/08/16 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/nginx.conf.sample
## Version 2023/04/13 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/nginx.conf.sample
### Based on alpine defaults
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.conf?h=3.15-stable
@ -55,7 +55,7 @@ http {
tcp_nopush on;
# all ssl related config moved to ssl.conf
include /config/nginx/ssl.conf;
# included in server blocks where listen 443 is defined
# Enable gzipping of responses.
#gzip on;

View File

@ -1,4 +1,4 @@
## Version 2022/10/04 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/site-confs/default.conf.sample
## Version 2023/04/13 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/site-confs/default.conf.sample
server {
listen 80 default_server;
@ -9,6 +9,8 @@ server {
server_name _;
include /config/nginx/ssl.conf;
set $root /app/www/public;
if (!-d /app/www/public) {
set $root /config/www;

View File

@ -1,8 +1,8 @@
## Version 2022/08/20 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/ssl.conf.sample
## Version 2023/06/24 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/ssl.conf.sample
### Mozilla Recommendations
# generated 2022-08-05, Mozilla Guideline v5.6, nginx 1.17.7, OpenSSL 1.1.1k, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&guideline=5.6
# generated 2023-06-25, Mozilla Guideline v5.7, nginx 1.24.0, OpenSSL 3.1.1, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.24.0&config=intermediate&openssl=3.1.1&guideline=5.7
ssl_certificate /config/keys/cert.crt;
ssl_certificate_key /config/keys/cert.key;
@ -15,7 +15,7 @@ ssl_dhparam /config/nginx/dhparams.pem;
# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
@ -30,8 +30,8 @@ ssl_prefer_server_ciphers off;
# Optional additional headers
#add_header Cache-Control "no-transform" always;
#add_header Content-Security-Policy "upgrade-insecure-requests; frame-ancestors 'self'";
#add_header Permissions-Policy "interest-cohort=()";
#add_header Content-Security-Policy "upgrade-insecure-requests; frame-ancestors 'self'" always;
#add_header Permissions-Policy "interest-cohort=()" always;
#add_header Referrer-Policy "same-origin" always;
#add_header X-Content-Type-Options "nosniff" always;
#add_header X-Frame-Options "SAMEORIGIN" always;

View File

@ -49,7 +49,7 @@ http:
landet_zigbee-service:
loadBalancer:
servers:
- url: "http://10.1.0.4:8082"
- url: "http://10.0.10.2:8082"
lampa-service:
loadBalancer:
servers:

View File

@ -1,10 +1,10 @@
http:
routers:
landet_zigbee-router:
rule: "Host(`zig3.milvert.com`)"
service: landet_zigbee-service
landet-router:
rule: "Host(`landet.milvert.com`)"
service: landet-service
middlewares:
- auth
- chain-no-auth
entryPoints:
- web-secure
tls:
@ -46,10 +46,10 @@ http:
priority: 1
services:
landet_zigbee-service:
landet-service:
loadBalancer:
servers:
- url: "http://10.1.0.4:8082"
- url: "http://10.0.10.3:8123"
lampa-service:
loadBalancer:
servers:

View File

@ -1,4 +1,4 @@
homeassistant: false
homeassistant: true
permit_join: false
mqtt:
base_topic: zigbee2mqtt
@ -73,10 +73,6 @@ devices:
friendly_name: '0x0017880106fc9e16'
'0x00158d0004889e4a':
friendly_name: sensor/inne/matrum/th003
'0x00158d0004889e47':
friendly_name: sensor/ute/garage/th004
'0x680ae2fffeb15687':
friendly_name: Garage
'0x588e81fffe14100f':
friendly_name: Ute_soptunna
'0x0017880108c48479':
@ -93,6 +89,10 @@ devices:
friendly_name: sensor/inne/ada/th002
'0x90fd9ffffe6e8fe2':
friendly_name: arum gullampa
'0x847127fffebe9e0d':
friendly_name: '0x847127fffebe9e0d'
'0x5c0272fffe8ab0ce':
friendly_name: Garage_inne_tak
groups:
'1':
friendly_name: Kök_ct

View File

@ -1,4 +1,4 @@
homeassistant: false
homeassistant: true
permit_join: false
mqtt:
base_topic: zigbee_home_2
@ -133,7 +133,23 @@ devices:
'0x040d84fffe8b00b0':
friendly_name: matrum_fönster_2
'0x847127fffebe9e0d':
friendly_name: '0x847127fffebe9e0d'
friendly_name: sensor/ute/uppfart/m003
'0x00124b002a51bd18':
friendly_name: sensor/inne/badrum_nere/th013
'0x00124b002a51c5f1':
friendly_name: sensor/inne/uppe_vrum/th014
'0xa4c138a7ea206c89':
friendly_name: Garage_spot
'0x00158d00076ab301':
friendly_name: sensor/inne/ada/dt004
'0x00158d00076ab041':
friendly_name: sensor/inne/oscar/dt005
'0x00158d00075bdae2':
friendly_name: sensor/inne/uppe_vrum/dt006
'0x9035eafffefd9103':
friendly_name: Ute_woox
'0x00158d0004889e47':
friendly_name: sensor/ute/garage/th004
groups:
'0':
friendly_name: default_0