Dzień dobry,
Kontynuuję ten wątek z postu, który zainicjowałem w dziale Node-RED, ale teraz dotyczy on wyłącznie templatingu HA (Node-RED nie dał rady…)…
Utknąłem bowiem na próbie konwersji daty na czysty integer…
Buduję następującą templatkę:
{% set today = now() %}
{% set birthday = state_attr('sensor.anniversary_urodziny_aga', 'date') %}
{% set days = (today - birthday) %}
{{today}}
{{birthday}}
{{days}}
Teraz muszę przeprowadzić matetmatyczne obliczenia wykorzystując zmienną days jako parametr numeryczny w funkcji sin(x), np. sin (17771) = 0.8358291413129607.
Niestety, kod: {{ sin (days) }} wywala następujący błąd: ValueError: Template error: sin got invalid input '17771 days, 11:59:00.140739' when rendering template.
Próbowałem wielu różnych funkcji i metod konwersji obiektu 17771 days, 11:59:00.140739 na czysty integer 17771 , ale żadna z nich nie zwraca oczekiwanego wyniku.
Normalnie w każdym języku programowania podobne problemy rozwiązuje się operując na znaczniku czasu (timestamp - TS).
Dwie daty konwertujesz na znacznik, który jest unikatową liczbą.
Wszystkie operacje robisz jak na zwykłych liczbach.
W przypadku biorytmu:
Delta = TSdzis - TSurodz - wyrażone w sek lub msek.
Dni = Delta / ilośćjednostekczasunadobę
Faza = sin(Dni)
sensor:
# Minimal configuration of the standard time and date sensor
- platform: time_date
display_options:
- 'date_time_iso'
# Build on the standard sensor to produce one that can be customized
template:
- sensor:
- name: "Date and time"
state: "{{ as_timestamp(states('sensor.date_time_iso')) | timestamp_custom('%A %B %-d, %I:%M %p') }}"
icon: "mdi:calendar-clock"
Ta notacja {% set days = (today - birthday).days %} bardzo pomogła!
Teraz days jest liczbą, a przecież o to właśnie chodziło.
Bardzo dziękuję za ten pomysł … i jadę dalej z pełnym algorytmem.
EDIT:
Temat pięknie ogarnięty. Ostatecznie templatka wygląda tak (sensor przechowuje w swoich atrybutach dane biorytmiczne dla każdego z czterech cykli):
sensor:
- name: Biorytm Aga
state: "{{ (state_attr('sensor.anniversary_urodziny_aga', 'date')) }}"
attributes:
Biorytm fizyczny: >
{% set today = now() %}
{% set birthday = (state_attr('sensor.anniversary_urodziny_aga', 'date')) %}
{% set days = (today - birthday).days %}
{% set cycle_days = 23 %}
{% set fiz = sin ( 2 * pi * days / cycle_days) %}
{{ fiz | float () }}
Biorytm emocjonalny: >
{% set today = now() %}
{% set birthday = (state_attr('sensor.anniversary_urodziny_aga', 'date')) %}
{% set days = (today - birthday).days %}
{% set cycle_days = 28 %}
{% set emo = sin ( 2 * pi * days / cycle_days) %}
{{ emo | float() }}
Biorytm intelektualny: >
{% set today = now() %}
{% set birthday = (state_attr('sensor.anniversary_urodziny_aga', 'date')) %}
{% set days = (today - birthday).days %}
{% set cycle_days = 33 %}
{% set inl = sin ( 2 * pi * days / cycle_days) %}
{{ inl | float () }}
Biorytm intuicyjny: >
{% set today = now() %}
{% set birthday = (state_attr('sensor.anniversary_urodziny_aga', 'date')) %}
{% set days = (today - birthday).days %}
{% set cycle_days = 38 %}
{% set inc = sin ( 2 * pi * days / cycle_days) %}
{{ inc | float () }}
Wykres biorytmu właśnie zaczął się tworzyć od dnia dzisiejszego, teraz musi minąć klika dni zanim na wykresie pojawią się wartości historyczne.
Chciałbym teraz pójść o krok dalej… Skoro sin(x) jest funkcją okresową, to jej wartość jest znana dla każdej daty z przeszłości i przyszłości. Fajnie byłoby widzieć taki wykres:
Na razie nie mam pomysłu jak zbudować wykres dla przedziału dat [dzisiaj-15dni, dzisiaj+15dni] na karcie custom:mini-graph-card, bo sama karta korzysta tylko z bieżących wartości sensorów z templatki… a nie widzę sensu stworzenia 30-tu nowych, osobnych sensorów (dla każdej daty z przedziału) dla każdego cyklu, skoro wszystkie wartości oblicza ta sama funkcja okresowa, której jedynym parametrem zmiennym jest data urodzin, czyli ilość przeżytych dni…
Mam wrażenie, że wpadłem na pomysł jak stworzyć wykres biorytmu dla przedziału [dziś-15, dziś+15].
Prawdopodobnie wystarczy:
przedefiniować templatkę sensora, dodając zmienną zakres w następujący sposób:
sensor:
- name: Biorytm Aga
state: "{{ (state_attr('sensor.anniversary_urodziny_aga', 'date')) }}"
attributes:
Biorytm fizyczny: >
{% set today = now() %}
{% set birthday = (state_attr('sensor.anniversary_urodziny_aga', 'date')) %}
{% set zakres = states('input_number.biorytmy_zakres').state %} #// szerokość przedziału wyrażona liczbą dni
{% set days = (today - birthday).days + zakres / 2 | int() %}
{% set cycle_days = 23 %}
{% set fiz = sin ( 2 * pi * days / cycle_days) %}
{{ fiz | float () }}
...
w kodzie karty custom:mini-graph-card wystarczy - o ile to się uda - odpowiednio zdefiniować parametr show_hours: ustawiając go na wartość zmiennej z numerycznego sensora pomocniczego (states['input_number.biorytmy_zakres'].state * 24), (np. 30, co daje 30 * 24 = 720 godzin).
Wartość parametru zakres (np. 30) w templatce powinna spowodować ‘wyprzedzenie w czasie’ wartości na wykresie o połowę tej wartości (np. dla 30 mamy: 30 / 2 = 15 dni). Zatem w rzeczywistości ilość dni days jest dodatkowo zwiększana o połowę szerokości przedziału, aby w dniu bieżącym przebieg wykresu zaczynał się od dnia dziś+15.
Dzięki temu, (niestety dopiero za miesiąc) powinienem otrzymać upragniony wykres dla zakresu dat: (-15dni <= dziś => +15dni).
Mam nadzieję, że intuicja mnie nie zawiedzie… Zobaczymy!
Z ostatniej chwili…
Właśnie rozkminiłem, jak sparametryzować wartość opcji show_hours w karcie custom:mini-graph-card. Należy w tym celu posłużyć się nadrzędną kartą custom:config-template-card, która umożliwia zamianę zakodowanej na sztywno wartości parametru w karcie podrzędnej na wartość dowolnej encji. Wystarczy jedynie zdefiniować zmienną w definicji karty nadrzędnej custom:config-template-card i odwołać się do niej jako wartości parametru show_hours w karcie podrzędnej custom:mini-graph-card
Fragment kodu karty wyglądałby tak:
type: custom:config-template-card
variables:
biorytmy_zakres: 24 * states['input_number.biorytmy_zakres'].state
# w celu zachowania wymaganej jednostki (h) mnożę zakres wyrażony w dniach przez ilość godzin w dniu (24)
entities:
- input_number.biorytmy_zakres
card:
type: custom:mini-graph-card
name: Biorytm Aga
...
hours_to_show: '${biorytmy_zakres}'
Kartą custom:config-template-card można zatem posługiwać się np. wszędzie tam, gdzie chcemy w jakikolwiek sposób ‘uzmienniać’ wartości parametrów innych kart.