pepe: add stocks to home-assistant
This commit is contained in:
parent
ddccee53cc
commit
c1fe743fc4
4 changed files with 237 additions and 21 deletions
|
@ -3,12 +3,13 @@ let unstablePkgs = import <nixpkgs-unstable> { };
|
||||||
in {
|
in {
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
#./home-assistant/chaospott.nix
|
|
||||||
#./home-assistant/mpd.nix
|
#./home-assistant/mpd.nix
|
||||||
#./home-assistant/timer.nix
|
#./home-assistant/timer.nix
|
||||||
|
./home-assistant/chaospott.nix
|
||||||
./home-assistant/kodi.nix
|
./home-assistant/kodi.nix
|
||||||
./home-assistant/mqtt.nix
|
./home-assistant/mqtt.nix
|
||||||
./home-assistant/sonoff.nix
|
./home-assistant/sonoff.nix
|
||||||
|
./home-assistant/stocks.nix
|
||||||
./home-assistant/weather.nix
|
./home-assistant/weather.nix
|
||||||
./home-assistant/workday.nix
|
./home-assistant/workday.nix
|
||||||
./home-assistant/zigbee2mqtt.nix
|
./home-assistant/zigbee2mqtt.nix
|
||||||
|
@ -37,7 +38,14 @@ in {
|
||||||
# ------------
|
# ------------
|
||||||
input_select.situation = {
|
input_select.situation = {
|
||||||
icon = "mdi:brightness-auto";
|
icon = "mdi:brightness-auto";
|
||||||
options = [ "on" "off" "essential" ];
|
options = [
|
||||||
|
# it is dark outside and I want it to be bright inside
|
||||||
|
"dark"
|
||||||
|
# it is bright outside, so no need to be bright inside
|
||||||
|
"bright"
|
||||||
|
# it is dark ouside, but I don't want it bright inside
|
||||||
|
"essential"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
input_boolean.bed_room_buttons.icon = "mdi:toggle-switch";
|
input_boolean.bed_room_buttons.icon = "mdi:toggle-switch";
|
||||||
input_boolean.situation_toggle.icon = "mdi:toggle-switch";
|
input_boolean.situation_toggle.icon = "mdi:toggle-switch";
|
||||||
|
@ -45,10 +53,19 @@ in {
|
||||||
automation = let
|
automation = let
|
||||||
|
|
||||||
# todo : at night only turn trigger essential groups
|
# todo : at night only turn trigger essential groups
|
||||||
roomPresents = { roomGroup, roomOffGroup ? roomGroup, presentsGroup
|
roomPresents = {
|
||||||
, situation, brightness ? 255 }: [
|
# group of the room that should be turned on
|
||||||
|
roomGroup,
|
||||||
|
# group of the room that should be turned off
|
||||||
|
roomOffGroup ? roomGroup,
|
||||||
|
# group of the room that that indicates presents in the room
|
||||||
|
presentsGroup,
|
||||||
|
# global situation
|
||||||
|
situation,
|
||||||
|
# brightness for dimable lights
|
||||||
|
brightness ? 255 }: [
|
||||||
{
|
{
|
||||||
alias = "presents -> turn on ${roomGroup} lights";
|
alias = "presents -> turn on ${roomGroup} lights in ${situation}";
|
||||||
trigger = {
|
trigger = {
|
||||||
platform = "state";
|
platform = "state";
|
||||||
entity_id = "group.${presentsGroup}";
|
entity_id = "group.${presentsGroup}";
|
||||||
|
@ -75,13 +92,19 @@ in {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
alias = "absents -> turn off ${roomOffGroup} lights";
|
alias =
|
||||||
|
"absents -> turn off ${roomOffGroup} lights in ${situation}";
|
||||||
trigger = {
|
trigger = {
|
||||||
platform = "state";
|
platform = "state";
|
||||||
entity_id = "group.${presentsGroup}";
|
entity_id = "group.${presentsGroup}";
|
||||||
from = "on";
|
from = "on";
|
||||||
to = "off";
|
to = "off";
|
||||||
};
|
};
|
||||||
|
condition = {
|
||||||
|
condition = "state";
|
||||||
|
entity_id = "input_select.situation";
|
||||||
|
state = situation;
|
||||||
|
};
|
||||||
action = [
|
action = [
|
||||||
{
|
{
|
||||||
service = "switch.turn_off";
|
service = "switch.turn_off";
|
||||||
|
@ -98,7 +121,7 @@ in {
|
||||||
{
|
{
|
||||||
roomGroup = "${name}_lights";
|
roomGroup = "${name}_lights";
|
||||||
presentsGroup = "${name}_present";
|
presentsGroup = "${name}_present";
|
||||||
situation = "on";
|
situation = "dark";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
roomGroup = "${name}_essential";
|
roomGroup = "${name}_essential";
|
||||||
|
@ -107,7 +130,10 @@ in {
|
||||||
situation = "essential";
|
situation = "essential";
|
||||||
brightness = 30;
|
brightness = 30;
|
||||||
}
|
}
|
||||||
]) [ "living_room" "floor_room" "bath_room" "bed_room" "kitchen_room" ]))) ++ [
|
]) [ "living_room" "floor_room" "bath_room" "bed_room" "kitchen_room" ])))
|
||||||
|
++ [
|
||||||
|
|
||||||
|
# control situation with buttons
|
||||||
{
|
{
|
||||||
alias = "set essential";
|
alias = "set essential";
|
||||||
trigger = {
|
trigger = {
|
||||||
|
@ -136,7 +162,7 @@ in {
|
||||||
service = "input_select.select_option";
|
service = "input_select.select_option";
|
||||||
data = {
|
data = {
|
||||||
entity_id = "input_select.situation";
|
entity_id = "input_select.situation";
|
||||||
option = "on";
|
option = "dark";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -291,7 +317,9 @@ in {
|
||||||
# maintainers = with maintainers; [ mrVanDalo ];
|
# maintainers = with maintainers; [ mrVanDalo ];
|
||||||
# };
|
# };
|
||||||
#})
|
#})
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,9 +59,8 @@ in {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
};
|
};
|
||||||
description = "set ${name} for homeassistant";
|
description = "set ${name} for homeassistant";
|
||||||
script = # sh
|
script = ''
|
||||||
''
|
${pkgs.curl}/bin/curl --location --silent https://status.chaospott.de/api \
|
||||||
${pkgs.curl}/bin/curl -Ls https://status.chaospott.de/api \
|
|
||||||
| ${pkgs.jq}/bin/jq --compact-output \
|
| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
'.sensors.door_locked |
|
'.sensors.door_locked |
|
||||||
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
|
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
|
||||||
|
|
180
configs/pepe/home-assistant/stocks.nix
Normal file
180
configs/pepe/home-assistant/stocks.nix
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
{ lib, config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
folderPath = config.services.home-assistant.configDir;
|
||||||
|
|
||||||
|
# find symbols with
|
||||||
|
# https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=<keywords>&apikey=<api_key>
|
||||||
|
# as described here : https://www.alphavantage.co/documentation/#symbolsearch
|
||||||
|
#
|
||||||
|
# example:
|
||||||
|
# --------
|
||||||
|
# stocks = [
|
||||||
|
# {
|
||||||
|
# symbol = "GOOGL";
|
||||||
|
# name = "google";
|
||||||
|
# friendly_name = "Google";
|
||||||
|
# currency = "$";
|
||||||
|
# # I own 50 and bought at a price of 1000
|
||||||
|
# own = {
|
||||||
|
# pieces = 50;
|
||||||
|
# price = 1000;
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
stocks = import <secrets/home-assistant/stocks>;
|
||||||
|
filePath = name: "${folderPath}/stock_${name}.json";
|
||||||
|
|
||||||
|
cleanup_list = list: lib.filter (entry: entry != { }) (lib.flatten list);
|
||||||
|
|
||||||
|
in {
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
sensor = cleanup_list (map ({ name, currency, own ? { }, ... }: [
|
||||||
|
{
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.price}} ${currency}";
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}_change";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.change}} ${currency}";
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}_change_percent";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.change_percent}} %";
|
||||||
|
}
|
||||||
|
(lib.optionalAttrs (own != { }) {
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}_profit";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = ''
|
||||||
|
{{ "{:,.2f}".format( value_json.price * ${toString own.pieces} - ${
|
||||||
|
toString (own.pieces * own.price)
|
||||||
|
} ) }} ${currency}'';
|
||||||
|
})
|
||||||
|
]) stocks);
|
||||||
|
|
||||||
|
homeassistant = {
|
||||||
|
whitelist_external_dirs = [ folderPath ];
|
||||||
|
customize = builtins.listToAttrs (cleanup_list (map
|
||||||
|
({ name, own ? { }, ... }: [
|
||||||
|
{
|
||||||
|
name = "sensor.stock_${name}";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:cash-usd-outline";
|
||||||
|
friendly_name = "Price";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sensor.stock_${name}_change";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:radar";
|
||||||
|
friendly_name = "Difference";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sensor.stock_${name}_change_percent";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:radar";
|
||||||
|
friendly_name = "Percent";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(lib.optionalAttrs (own != { }) {
|
||||||
|
name = "sensor.stock_${name}_profit";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:radar";
|
||||||
|
friendly_name = "Profit";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]) stocks));
|
||||||
|
};
|
||||||
|
|
||||||
|
group = {
|
||||||
|
"stocks" = {
|
||||||
|
name = "Aktien";
|
||||||
|
view = true;
|
||||||
|
control = "hidden";
|
||||||
|
entities = map ({ name, ... }: "group.stock_${name}") stocks;
|
||||||
|
};
|
||||||
|
} // (builtins.listToAttrs (map ({ name, friendly_name, own ? { }, ... }: {
|
||||||
|
name = "stock_${name}";
|
||||||
|
value = {
|
||||||
|
name = friendly_name;
|
||||||
|
control = "hidden";
|
||||||
|
entities = [
|
||||||
|
"sensor.stock_${name}"
|
||||||
|
"sensor.stock_${name}_change"
|
||||||
|
"sensor.stock_${name}_change_percent"
|
||||||
|
] ++ (lib.optional (own != { }) "sensor.stock_${name}_profit");
|
||||||
|
};
|
||||||
|
}) stocks));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services = let
|
||||||
|
pullService = { name, symbol, currency, ... }: {
|
||||||
|
name = "pull_stock_${name}";
|
||||||
|
value = {
|
||||||
|
enable = true;
|
||||||
|
before = [ "home-assistant.service" ];
|
||||||
|
wantedBy = [ "home-assistant.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
User = "hass";
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
description = "pull stock_${name} for homeassistant";
|
||||||
|
script = ''
|
||||||
|
SYMBOL="${symbol}"
|
||||||
|
CURRENCY="${currency}"
|
||||||
|
APIKEY=${
|
||||||
|
lib.fileContents <secrets/home-assistant/alphavantage/apikey>
|
||||||
|
}
|
||||||
|
|
||||||
|
${pkgs.curl}/bin/curl --location --silent \
|
||||||
|
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
||||||
|
| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
|
'.["Global Quote"] |
|
||||||
|
{
|
||||||
|
price: .["05. price"] | tonumber,
|
||||||
|
currency: "'$CURRENCY'",
|
||||||
|
change_percent: .["10. change percent"] | .[0:-1] | tonumber,
|
||||||
|
change: .["09. change"] | tonumber,
|
||||||
|
last_date: .["07. latest trading day"],
|
||||||
|
}' \
|
||||||
|
>> ${filePath name}
|
||||||
|
|
||||||
|
# old and stupid
|
||||||
|
#${pkgs.curl}/bin/curl --location --silent \
|
||||||
|
#"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=$SYMBOL&interval=5min&apikey=$APIKEY" \
|
||||||
|
#| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
|
# '.["Time Series (5min)"] | to_entries | [ .[]
|
||||||
|
# | { date : .key , value : .value["4. close"], currency: "'$CURRENCY'" } ]
|
||||||
|
# | sort_by(.date) | reverse | .[0]' \
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in builtins.listToAttrs (map pullService stocks);
|
||||||
|
|
||||||
|
systemd.timers = let
|
||||||
|
pullTimer = { name, ... }: {
|
||||||
|
name = "pull_stock_${name}";
|
||||||
|
value = {
|
||||||
|
enable = true;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "hourly";
|
||||||
|
Persistent = "true";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in builtins.listToAttrs (map pullTimer stocks);
|
||||||
|
|
||||||
|
}
|
|
@ -3,17 +3,26 @@ let
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
|
# https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
|
||||||
allDevices = {
|
allDevices = {
|
||||||
"door_sensor_1" = { id = "0x00158d000312dc52"; };
|
"door_sensor_1" = {
|
||||||
|
id = "0x00158d000312dc52";
|
||||||
|
groups = [ "living_room" ];
|
||||||
|
};
|
||||||
"door_sensor_2" = {
|
"door_sensor_2" = {
|
||||||
id = "0x00158d000316d5bf";
|
id = "0x00158d000316d5bf";
|
||||||
groups = [ "floor_room" "floor_room_present" ];
|
groups = [ "floor_room" "floor_room_present" ];
|
||||||
};
|
};
|
||||||
"door_sensor_3" = { id = "0x00158d0002f9516f"; };
|
"door_sensor_3" = {
|
||||||
|
id = "0x00158d0002f9516f";
|
||||||
|
groups = [ "kitchen_room" ];
|
||||||
|
};
|
||||||
"door_sensor_4" = {
|
"door_sensor_4" = {
|
||||||
id = "0x00158d00031383b9";
|
id = "0x00158d00031383b9";
|
||||||
groups = [ "floor_room" "floor_room_present" ];
|
groups = [ "floor_room" "floor_room_present" ];
|
||||||
};
|
};
|
||||||
"door_sensor_5" = { id = "0x00158d0003120d3e"; };
|
"door_sensor_5" = {
|
||||||
|
id = "0x00158d0003120d3e";
|
||||||
|
groups = [ "bath_room" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in {
|
||||||
|
|
Loading…
Reference in a new issue