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 {
|
||||
|
||||
imports = [
|
||||
#./home-assistant/chaospott.nix
|
||||
#./home-assistant/mpd.nix
|
||||
#./home-assistant/timer.nix
|
||||
./home-assistant/chaospott.nix
|
||||
./home-assistant/kodi.nix
|
||||
./home-assistant/mqtt.nix
|
||||
./home-assistant/sonoff.nix
|
||||
./home-assistant/stocks.nix
|
||||
./home-assistant/weather.nix
|
||||
./home-assistant/workday.nix
|
||||
./home-assistant/zigbee2mqtt.nix
|
||||
|
@ -37,7 +38,14 @@ in {
|
|||
# ------------
|
||||
input_select.situation = {
|
||||
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.situation_toggle.icon = "mdi:toggle-switch";
|
||||
|
@ -45,10 +53,19 @@ in {
|
|||
automation = let
|
||||
|
||||
# todo : at night only turn trigger essential groups
|
||||
roomPresents = { roomGroup, roomOffGroup ? roomGroup, presentsGroup
|
||||
, situation, brightness ? 255 }: [
|
||||
roomPresents = {
|
||||
# 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 = {
|
||||
platform = "state";
|
||||
entity_id = "group.${presentsGroup}";
|
||||
|
@ -75,13 +92,19 @@ in {
|
|||
];
|
||||
}
|
||||
{
|
||||
alias = "absents -> turn off ${roomOffGroup} lights";
|
||||
alias =
|
||||
"absents -> turn off ${roomOffGroup} lights in ${situation}";
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "group.${presentsGroup}";
|
||||
from = "on";
|
||||
to = "off";
|
||||
};
|
||||
condition = {
|
||||
condition = "state";
|
||||
entity_id = "input_select.situation";
|
||||
state = situation;
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "switch.turn_off";
|
||||
|
@ -98,7 +121,7 @@ in {
|
|||
{
|
||||
roomGroup = "${name}_lights";
|
||||
presentsGroup = "${name}_present";
|
||||
situation = "on";
|
||||
situation = "dark";
|
||||
}
|
||||
{
|
||||
roomGroup = "${name}_essential";
|
||||
|
@ -107,7 +130,10 @@ in {
|
|||
situation = "essential";
|
||||
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";
|
||||
trigger = {
|
||||
|
@ -136,7 +162,7 @@ in {
|
|||
service = "input_select.select_option";
|
||||
data = {
|
||||
entity_id = "input_select.situation";
|
||||
option = "on";
|
||||
option = "dark";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -291,7 +317,9 @@ in {
|
|||
# maintainers = with maintainers; [ mrVanDalo ];
|
||||
# };
|
||||
#})
|
||||
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -59,15 +59,14 @@ in {
|
|||
Type = "oneshot";
|
||||
};
|
||||
description = "set ${name} for homeassistant";
|
||||
script = # sh
|
||||
''
|
||||
${pkgs.curl}/bin/curl -Ls https://status.chaospott.de/api \
|
||||
| ${pkgs.jq}/bin/jq --compact-output \
|
||||
'.sensors.door_locked |
|
||||
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
|
||||
reduce .[] as $item ({}; . + $item) ' \
|
||||
>> ${filePath}
|
||||
'';
|
||||
script = ''
|
||||
${pkgs.curl}/bin/curl --location --silent https://status.chaospott.de/api \
|
||||
| ${pkgs.jq}/bin/jq --compact-output \
|
||||
'.sensors.door_locked |
|
||||
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
|
||||
reduce .[] as $item ({}; . + $item) ' \
|
||||
>> ${filePath}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.timers."${name}" = {
|
||||
|
|
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
|
||||
allDevices = {
|
||||
"door_sensor_1" = { id = "0x00158d000312dc52"; };
|
||||
"door_sensor_1" = {
|
||||
id = "0x00158d000312dc52";
|
||||
groups = [ "living_room" ];
|
||||
};
|
||||
"door_sensor_2" = {
|
||||
id = "0x00158d000316d5bf";
|
||||
groups = [ "floor_room" "floor_room_present" ];
|
||||
};
|
||||
"door_sensor_3" = { id = "0x00158d0002f9516f"; };
|
||||
"door_sensor_3" = {
|
||||
id = "0x00158d0002f9516f";
|
||||
groups = [ "kitchen_room" ];
|
||||
};
|
||||
"door_sensor_4" = {
|
||||
id = "0x00158d00031383b9";
|
||||
groups = [ "floor_room" "floor_room_present" ];
|
||||
};
|
||||
"door_sensor_5" = { id = "0x00158d0003120d3e"; };
|
||||
"door_sensor_5" = {
|
||||
id = "0x00158d0003120d3e";
|
||||
groups = [ "bath_room" ];
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
|
|
Loading…
Reference in a new issue