pantherale0 / ha-nintendoparentalcontrols

Home Assistant integration for Nintendo Switch Parental Controls
MIT License
90 stars 7 forks source link

Bonus Time only for the current day #61

Closed JokerGermany closed 10 months ago

JokerGermany commented 11 months ago

Checklist

Is your feature request related to a problem? Please describe.

Sorry for the mass feature request, but your https://github.com/pantherale0/ha-nintendoparentalcontrols/issues/59#issuecomment-1879862959

I never implemented it because I replaced the whole app with Home Assistant, so that takes care of setting the time entity on a per day basis.

inspired me to make a new one^

At the moment we only use the Nintendo switch App. We have Times for Weekends/holidays and workdays. Sometimes it would be nice to be able to add bonus time (like in family link from google[Sadly there is no integration for that ;) ]) At the moment we change the time for the day and shouldn't forget to set it back later..

Describe the solution you'd like

Add a possibility to set a Bonus Time (time.bonus) The Bonus time is added to the time of the current day and is changed back when the day past.

Describe alternatives you've considered

Doing automations for that.

pantherale0 commented 11 months ago

love the feature requests, I just put a comment in the HA discord how I prefer working on this stuff over my day job (which actually isn't far off this kind of thing anyway haha).

I'm sure I can figure something out for this one too, will try and implement something for next month. Currently I use an automation to reset the time entity back to a "default" value at midnight which allows me to add bonus time during the day.

Also I started to take a look at Family Link, but think I need to get a group of developers together who are interested to help reverse engineer the protobuf responses and figure out how to generate the auth cookies.

seanmccabe commented 10 months ago

love the feature requests, I just put a comment in the HA discord how I prefer working on this stuff over my day job (which actually isn't far off this kind of thing anyway haha).

I'm sure I can figure something out for this one too, will try and implement something for next month. Currently I use an automation to reset the time entity back to a "default" value at midnight which allows me to add bonus time during the day.

Also I started to take a look at Family Link, but think I need to get a group of developers together who are interested to help reverse engineer the protobuf responses and figure out how to generate the auth cookies.

Would you be able to share some of the automations you have around this? I'm setting something up for this at the moment, using NFC to start the timers etc.

pantherale0 commented 10 months ago

Bonus time support is added in 2024.1.0b0, its in an experimental phase as its not something that Nintendo actually support themselves so instead its stored in memory.

It comes at a risk, if Home Assistant is restarted, the value is not preserved and will reset back to 0:00.

pantherale0 commented 10 months ago

Would you be able to share some of the automations you have around this? I'm setting something up for this at the moment, using NFC to start the timers etc.

Mine are generally based around a schedule (https://www.home-assistant.io/integrations/schedule/), Google Calendar, and a bunch of helpers to store the total allowed screen time to sync across to other devices.

Theres a few issues though at the moment that I need to sort out before sharing. But will do at some point :+1:

JokerGermany commented 10 months ago

Will the Bonus Time, postpone the bedtime-alarm?

e.g. bedtime Alarm is 21:00 I set at 20:30 an Bonus of 1 hour, will then the bedtime Alarm changed to 21:30?

pantherale0 commented 10 months ago

Will the Bonus Time, postpone the bedtime-alarm?

e.g. bedtime Alarm is 21:00 I set at 20:30 an Bonus of 1 hour, will then the bedtime Alarm changed to 21:30?

Not currently, it only adds an offset to the play time. So if you set a bonus time of 30 minutes for example it adds an additional 30 minutes to the Play Time Limit entity. Everytime you set the bonus time after this, its treated as an increase, so if you set the bonus time to 15 minutes, it would then add an additional 15 minutes to the existing 30 minutes of bonus time.

At roughly midnight, it will reset itself back to 0 minutes.

JokerGermany commented 10 months ago

To be honest, I don't need the bonus time anymore, because I had to create my own one. I hope someone else is using it...

evilmumi commented 10 months ago

To be honest, I don't need the bonus time anymore, because I had to create my own one. I hope someone else is using it...

How did you code it?

JokerGermany commented 10 months ago

To be honest, I don't need the bonus time anymore, because I had to create my own one. I hope someone else is using it...

How did you code it?

  1. Created a helper with the type input_datetime
  2. Created an automation:
    alias: xyz BonusZeit
    description: ""
    trigger:
    - platform: state
    entity_id:
    - input_datetime.xyz_bonuszeit
    condition:
    - condition: numeric_state
    entity_id: input_datetime.xyz_bonuszeit
    above: 0
    attribute: timestamp
    action:
    - service: input_number.set_value
    metadata: {}
    data:
    value: >-
    {{(states.input_number.ursprungszeit.state|float+(state_attr('input_datetime.xyz_bonuszeit',
    'timestamp')/60)/60)|float}}
    target:
    entity_id: input_number.ursprungszeit
    - service: time.set_value
    metadata: {}
    data:
    time: >-
    {{((states('sensor.used_screen_time')|int)+(state_attr('input_datetime.xyz_bonuszeit',
    'timestamp')/60))/60}}
    target:
    entity_id: time.play_time_limit
    mode: single

    ( ursprungszeit is a helper with the type input_number, which is updated once in the night, to know which play time was originally set ) It's an skript which is executed at midnight:

    alias: xyz Spielzeit
    sequence:
    - alias: Spielzeit einstellen
    if:
    - condition: or
    conditions:
    - condition: state
    entity_id: binary_sensor.arbeitstag_heute_sensor
    state: "off"
    then:
    - service: time.set_value
    metadata: {}
    data:
    time: "05:00:00"
    target:
    entity_id: time.play_time_limit
    else:
    - service: time.set_value
    metadata: {}
    data:
    time: "02:30:00"
    target:
    entity_id: time.play_time_limit
    - service: input_number.set_value
    metadata: {}
    data:
    value: >-
    {{(states('time.play_time_limit').split(':')[0]|int+(states('time.play_time_limit').split(':')[1]|int)/60)|float}}
    target:
    entity_id: input_number.ursprungszeit
    - service: input_datetime.set_datetime
    metadata: {}
    data:
    time: "00:00:00"
    target:
    entity_id: input_datetime.xyz_bonuszeit
    - alias: Gute-Nacht-Alarm
    if:
    - condition: or
    conditions:
    - condition: state
    entity_id: binary_sensor.arbeitstag_morgen_sensor
    state: "off"
    then:
    - service: time.set_value
    metadata: {}
    data:
    time: "22:00:00"
    target:
    entity_id:
    - time.bedtime_alarm
    else:
    - service: time.set_value
    metadata: {}
    data:
    time: "21:00:00"
    target:
    entity_id:
    - time.bedtime_alarm
    mode: single

I need it because I want to restrict the time the tv is used and "sync" this time to the switch:

alias: Fernseher xyz
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.time_remaining
    to: "0.0"
    id: ZeitWeg
  - platform: numeric_state
    entity_id:
      - sensor.time_remaining
    above: 0
    id: ZeitDa
  - platform: time
    at: "06:00:00"
    id: ZeitDa
  - alias: Gute-Nacht-Alarm ist jetzt
    platform: template
    value_template: >-
      {{ states('time.bedtime_alarm') < now().timestamp() |
      timestamp_custom('%H:%M:%S') }}
    id: ZeitWeg
  - alias: Fernseher Laufzeit größer als Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+9/60}}
    id: ZeitWeg
  - platform: state
    entity_id:
      - time.bedtime_alarm
    id: ZeitDa
  - platform: state
    entity_id:
      - binary_sensor.fernseher_xyz
    to: "off"
    id: Zeitberechnung
  - alias: Neuberechnung 60 Minuten vor ablauf der Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+(9-60)/60}}
    id: Zeitberechnung
  - alias: Neuberechnung 45 Minuten vor ablauf der Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+(9-45)/60}}
    id: Zeitberechnung
  - alias: Neuberechnung 30 Minuten vor ablauf der Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+(9-30)/60}}
    id: Zeitberechnung
  - alias: Neuberechnung 15 Minuten vor ablauf der Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+(9-15)/60}}
    id: Zeitberechnung
  - alias: Neuberechnung 10 Minuten vor ablauf der Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+(9-10)/60}}
    id: Zeitberechnung
  - alias: Neuberechnung 5 Minuten vor ablauf der Spielzeit
    platform: template
    value_template: >-
      {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+(9-5)/60}}
    id: Zeitberechnung
  - platform: state
    entity_id:
      - sensor.time_remaining
    for:
      hours: 0
      minutes: 30
      seconds: 0
    id: Zeitberechnung
  - platform: state
    entity_id:
      - switch.alarms_enabled_today
    to: "on"
    id: ZeitWeg
  - platform: state
    entity_id:
      - switch.alarms_enabled_today
    to: "off"
    id: ZeitDa
condition:
  - condition: or
    conditions:
      - condition: and
        conditions:
          - condition: trigger
            id:
              - ZeitWeg
          - condition: state
            entity_id: switch.alarms_enabled_today
            state: "on"
          - condition: or
            conditions:
              - condition: template
                value_template: >-
                  {{ states('time.bedtime_alarm') < now().timestamp() |
                  timestamp_custom('%H:%M:%S') }}
                alias: Gute Nacht Alarm überschritten
              - condition: state
                entity_id: sensor.time_remaining
                state: "0.0"
              - condition: template
                value_template: >-
                  {{states.sensor.fernseher_xyz_laufzeit.state|float>states.input_number.ursprungszeit.state|float+9/60}}
                alias: Fernseher Laufzeit größer als Spielzeit
      - condition: and
        conditions:
          - condition: trigger
            id:
              - ZeitDa
          - condition: or
            conditions:
              - condition: and
                conditions:
                  - condition: time
                    after: "06:00:00"
                  - condition: numeric_state
                    entity_id: sensor.time_remaining
                    above: 0
                  - condition: template
                    value_template: >-
                      {{ states('time.bedtime_alarm') > now().timestamp() |
                      timestamp_custom('%H:%M:%S') }}
                    alias: Gute Nacht Alarm ist noch nicht
              - condition: state
                entity_id: switch.alarms_enabled_today
                state: "off"
      - condition: and
        conditions:
          - condition: trigger
            id:
              - Zeitberechnung
          - condition: or
            conditions:
              - condition: template
                value_template: >-
                  {{states.sensor.fernseher_xyz_laufzeit.state|float>(states('sensor.used_screen_time')|int+9+15)/60+states.input_number.abgleichfernseherswitch.state}}
              - condition: and
                conditions:
                  - condition: state
                    entity_id: sensor.time_remaining
                    for:
                      hours: 0
                      minutes: 30
                      seconds: 0
                    state: ""
                  - condition: template
                    value_template: >-
                      {{states.sensor.fernseher_xyz_laufzeit.state|float>(states('sensor.used_screen_time')|int+9)/60+states.input_number.abgleichfernseherswitch.state}}
action:
  - if:
      - condition: trigger
        id:
          - ZeitWeg
    then:
      - if:
          - condition: template
            value_template: >-
              {{states.sensor.fernseher_xyz_laufzeit.state|float>states('time.play_time_limit').split(':')[0]|int+(states('time.play_time_limit').split(':')[1]|int+9)/60}}
            alias: Fernseher Laufzeit größer als Spielzeit
        then:
          - service: time.set_value
            metadata: {}
            data:
              time: "00:00:00"
            target:
              entity_id: time.play_time_limit
          - service: notify.matrix_xyz_log
            data:
              message: >-
                Fernseher lief länger als die heutige erlaubte Spielzeit, daher
                Fernseher ausgeschaltet und Spielzeit auf 0 gesetzt
      - type: turn_off
        device_id: 7bf17e809693585372f655e2056c2995
        entity_id: 22a45935c24a2e087713ba1306c0d062
        domain: switch
    else:
      - if:
          - condition: trigger
            id:
              - ZeitDa
        then:
          - type: turn_on
            device_id: 7bf17e809693585372f655e2056c2995
            entity_id: 22a45935c24a2e087713ba1306c0d062
            domain: switch
        else:
          - if:
              - condition: trigger
                id:
                  - Zeitberechnung
            then:
              - if:
                  - condition: state
                    entity_id: sensor.time_remaining
                    for:
                      hours: 0
                      minutes: 30
                      seconds: 0
                    state: ""
                then:
                  - service: input_number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {{states.sensor.fernseher_xyz_laufzeit.state|float-(states('sensor.used_screen_time')|int+9)/60}}
                    target:
                      entity_id: input_number.abgleichfernseherswitch
                else:
                  - service: input_number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {{states.sensor.fernseher_xyz_laufzeit.state|float-(states('sensor.used_screen_time')|int+15+9)/60}}
                    target:
                      entity_id: input_number.abgleichfernseherswitch
              - service: time.set_value
                metadata: {}
                data:
                  time: >-
                    {{
                    timedelta(float(states.input_number.ursprungszeit.state|float-states.input_number.abgleichfernseherswitch.state|float)
                    / 24) }}
                target:
                  entity_id: time.play_time_limit
              - service: notify.matrix_xyz_log
                data:
                  message: ""
mode: single

It escalated a bit XD

The Zeitberechnung part is coded yesterday => not tested now Zeitberechnung = Time calculation It was a consideration between showing the correct time on the switch and take into account that the remaining time / screen used sensor isn't realtime (+15 Minutes)

(the +9 is because when the tv outlet is turned out, it consumes so much energy that home assistant thinks the device is running)

BTW: If you are wondering about the or with only one option in xyz Spielzeit: At the moment the holidays are missing, which needs to be implemented...