Time controlled internet access

This Blueprint gives the kids some control over the online time of their game consoles. They can use buttons to start and pause the online time. Parents can add more time if the kids made their shores. Internet access is controlled via the FritzBox.

Required entities

  • 2 datetime (time) helpers for the default time and the additional time the parents can add per klick
  • 3 buttons (play, pause and add)
  • 1 timer
  • 1 fritzbox internet_access switch

The Blueprint

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

blueprint:
  name: Timer based internet access
  description: Turn on and off internet access via FritzBox based on a timer
  domain: automation
  input:
    timer:
      name: Timer
      selector:
        entity:
          filter:
            domain: timer
    default_time:
      name: Default Time
      selector:
        entity:
          filter:
            domain: input_datetime
    add_time:
      name: Additional Time
      selector:
        entity:
          filter:
            domain: input_datetime
    add_button:
      name: add Button
      selector:
        entity:
          filter:
            domain: input_button
    pause_button:
      name: Pause Button
      selector:
        entity:
          filter:
            domain: input_button
    play_button:
      name: Play Button
      selector:
        entity:
          filter:
            domain: input_button
    device:
      name: FritzBox device
      selector:
        entity:
          filter:
            domain: switch
            integration: fritz

mode: single
max_exceeded: silent

trigger:
  - platform: state
    id: add
    entity_id: !input add_button
  - platform: state
    id: pause
    entity_id: !input pause_button
  - platform: state
    id: play
    entity_id: !input play_button
  - platform: event
    id: timer_finished
    event_type: timer.finished
    event_data:
      entity_id: !input timer
  - platform: time
    id: midnight
    at: "00:00:00"

variables:
  input_timer: !input timer
  input_default_time: !input default_time
  input_add_time: !input add_time

action:
  - choose:
      - conditions:
          - condition: trigger
            id: add
        sequence:
          - service: switch.turn_on
            target:
              entity_id: !input device
          - service: timer.start
            target:
              entity_id: !input timer
            data:
              duration: >
                {% set s = states(input_timer) %}
                {% set a = state_attr(input_add_time, 'timestamp') %}
                {% set d = as_timestamp(strptime("1970-01-01 " + state_attr(input_timer, 'duration') + "-0000", '%Y-%m-%d %H:%M:%S%z', 0)) | int(0) %}
                {% set f = 0 if state_attr(input_timer, 'finishes_at') == none else (state_attr(input_timer, 'finishes_at') | as_datetime - now()).total_seconds() | int(0) %}
                {% set r = 0 if state_attr(input_timer, 'remaining') == none else strptime("1970-01-01 " + state_attr(input_timer, 'remaining') + "-0000", '%Y-%m-%d %H:%M:%S%z', 0) | as_timestamp | int(0) %}

                {% if s == 'idle' and d <= 10 %} {{ a }}
                {% elif s == 'idle' %} {{ a + d }}
                {% elif s == 'paused' %} {{ r + a }}
                {% elif s == 'active' %} {{ f + a }}
                {% endif %}

      - conditions:
          - condition: and
            conditions:
              - condition: trigger
                id: pause
        sequence:
          - service: switch.turn_off
            target:
              entity_id: !input device
          - service: timer.pause
            target:
              entity_id: !input timer

      - conditions:
          - condition: and
            conditions:
              - condition: trigger
                id: play
              - condition: template
                value_template: |
                  {% set d = state_attr(input_timer, 'duration') %}
                  {{ as_timestamp(strptime('1970-01-01 ' + d, '%Y-%m-%d %H:%M:%S', 0) + timedelta(hours=1)) > 1 }}
              - condition: not
                conditions:
                  - condition: state
                    entity_id: !input timer
                    state: active
        sequence:
          - service: switch.turn_on
            target:
              entity_id: !input device
          - service: timer.start
            target:
              entity_id: !input timer

      - conditions:
          - condition: trigger
            id: timer_finished
        sequence:
          - service: switch.turn_off
            target:
              entity_id: !input device

      - conditions:
          - condition: trigger
            id: midnight
        sequence:
          - service: timer.start
            target:
              entity_id: !input timer
            data:
              duration: |
                {{ states(input_default_time) | string }}
          - service: timer.pause
            target:
              entity_id: !input timer
5 Likes

How I integrated it into the frontend

Bildschirmfoto von 2022-08-19 17-18-14

I used mushroom cards, layout-card for the layout and state-switch to hide the add button and time helpers from the kids.

type: vertical-stack
cards:
  - type: custom:mushroom-template-card
    primary: PS4 Tom
    secondary: >-
      {% set s = states('timer.ps4_tom_timer') %}
      {% set d = state_attr('timer.ps4_tom_timer', 'duration') %}
      {% set di = as_timestamp(strptime("1970-01-01 " + d, '%Y-%m-%d %H:%M:%S',
      0) + timedelta(hours=1)) | int(0) %}
      {% set f = 0 if state_attr('timer.ps4_tom_timer', 'finishes_at') == none
      else (state_attr('timer.ps4_tom_timer', 'finishes_at') | as_timestamp |
      timestamp_custom('%H:%M:%S', local=True)) %}
      {% set r = 0 if state_attr('timer.ps4_tom_timer', 'remaining') == none
      else state_attr('timer.ps4_tom_timer', 'remaining') %}

      {% if s == "idle" and di > 1 %}
       Rest: {{ d }}
      {% elif s == "paused" %}
       Rest: {{ r }}
      {% elif s == "idle" %}
       Das wars fĂĽr heute
      {% elif s == "active" %}
       Aktiv bis {{ f }}
      {% endif %}
    icon: mdi:sony-playstation
    fill_container: false
    layout: horizontal
    hold_action:
      action: none
    double_tap_action:
      action: none
    entity: timer.ps4_tom_timer
    icon_color: ''
    multiline_secondary: true
    tap_action:
      action: none
  - type: horizontal-stack
    cards:
      - type: custom:mushroom-entity-card
        entity: input_button.ps4_tom_play
        name: Play
        tap_action:
          action: toggle
        secondary_info: none
        layout: vertical
      - type: custom:mushroom-entity-card
        entity: input_button.ps4_tom_pause
        name: Pause
        tap_action:
          action: toggle
        secondary_info: none
        layout: vertical
      - type: custom:mushroom-entity-card
        entity: switch.ps4tom_internet_access
        hold_action:
          action: none
        double_tap_action:
          action: none
        layout: vertical
        primary_info: state
        secondary_info: none
        icon: fab:playstation
        tap_action:
          action: none
  - type: custom:state-switch
    entity: '{{ "adult" if (user=="Gerhard" or user=="Tina") else "child" }}'
    states:
      adult:
        type: horizontal-stack
        cards:
          - type: custom:mushroom-entity-card
            entity: input_button.ps4_tom_add
            tap_action:
              action: toggle
            hold_action:
              action: none
            double_tap_action:
              action: none
            layout: vertical
            name: +Zusatzzeit
            secondary_info: none
            fill_container: true
          - type: custom:mushroom-entity-card
            entity: input_datetime.ps4_tom_default_time
            layout: vertical
            name: Standard Zeit
          - type: custom:mushroom-entity-card
            entity: input_datetime.ps4_tom_add_time
            layout: vertical
            name: Zusatzzeit
      child:
        type: custom:gap-card
        height: 10
2 Likes

Brilliant idea!

Can you make this blueprint to use it also with other routers like a experiabox ?

2 Likes

I don’t know anything about the experiabox. Does it and more important it’s hass integration have the ability to en-/disable internet access for individual devices?

What a great automation. Thank you!

Could you please tell me how the timer gets reset for the next day?

I was not able to find that in the code.

Thank you. Of course I can. There is a trigger with the id midnight that triggers at midnight.

- platform: time
  id: midnight
  at: "00:00:00"

And further down there is a condition whose sequence is executed if midnight was triggered. It starts the timer with the default_time and pauses it right after.

- conditions:
    - condition: trigger
      id: midnight
  sequence:
    - service: timer.start
      target:
        entity_id: !input timer
      data:
        duration: |
          {{ states(input_default_time) | string }}
    - service: timer.pause
      target:
        entity_id: !input timer
1 Like

thank you very much, just wondering why i dont see this in the automation

EDIT: forgot I had to look at the code inside the blueprint :slight_smile:

@MeisterBob Hopefully you are still around :slight_smile: I need some help.

I wanted to use this but get the following error. I am not used to blueprints so perhaps am not doing it right ?

I could not get this to work for me so I used NodeRed instead. See here for my post with the details and code snippets.

This looks great.

I have the ssh command to turn the access to Internet ON/OFF on my router.
Could I use it with this blueprint?
I want my daughter to have ON/OFF switch on her HA app so she can use Internet anytime during the day, but only for 3 hours max per day.

If you can trigger the ssh command with home assistant you can use this. You must just change the device input and switch.turn_on/off service calls to whatever you need.

Do you mean to edit the blueprint directly to something like this?

    device:
      name: Firewall switch
      selector:
        command_line:
        - switch:
             name: "Firewall toggle"
             command_on: ssh [email protected] "uci set firewall.@rule[9].enabled=0;fw3 reload;uci commit"
             command_off: ssh [email protected] "uci set firewall.@rule[9].enabled=1;fw3 reload;uci commit"
          multiple: false

I expect it is not going to work like that, I want to make sure that I am on the right path. I was thinking to create a device separately, but I am not sure how to do it plus it would be convenient to implement everything into this blueprint directly if possible.

I didn’t use shell commands so I don’t know exactly, but as I understand the documentation you can create a command_line switch in your configuration.yaml

command_line:
  - switch:
    name: "Firewall toggle"
    command_on: ssh [email protected] "uci set firewall.@rule[9].enabled=0;fw3 reload;uci commit"
    command_off: ssh [email protected] "uci set firewall.@rule[9].enabled=1;fw3 reload;uci commit"

That should create a new switch in your home assistant. You should then be able to use that switch with this blueprint when you remove the integration: fritz filter.

I actually tried exactly that but there is no switch to be found after reboot, so I am confused in terms of what else need to be set to make the switch appear. Might open a new topic for it to get some help. Thank you though once I sort this out hopefully will get to make this blueprint working for my use case.

Hi Bob,

I figured out finally how to make the binary switch working and the blueprint is in action finally! Thanks for this, it is very helpfull!

My wife asked for bit more power so I did slight modifications to your model of control. Made a separate Parental section which displays only for parent and added coule more buttons.
image

One problem I have remaining is to figure out how to make the time reduce button working. Would you be able to help me how to change the code to add it?
I tried to duplicate the portion of the code I believe does the operation, but the reduce button is still “dead” and the time substitution operation won’t be most likely working correctly either.
Here is my current code for the blueprint:

I don’t use it anymore cause my kids learnt their lesson - at least for now :wink:

A first quick look onto your code reveals, that you have two conditions that trigger on reduce and none that triggers on add. Then I copied the magic into the template section in the developer tools, that revealed a syntax error in the set d=... and set r=... lines. We are concatenating strings here, that needs the + operator not -.

Here is the template that might bring the reduce button to work (without the additions that explain the template printout). The if s=="idle" and d<=10 doesn’t make much sense for the reduce case and I don’t remember why I put it there for the add case.

{% set input_timer       = "timer.ps4_ben_timer" %}
{% set input_reduce_time = "input_datetime.ps4_ben_add_time" %}

{% set s = states(input_timer) %}
{% set a = state_attr(input_reduce_time, "timestamp") %}
{% set d = as_timestamp(strptime("1970-01-01 " + state_attr(input_timer, "duration") + "-0000", "%Y-%m-%d %H:%M:%S%z", 0)) | int(0) %}
{% set f = 0 if state_attr(input_timer, "finishes_at") == none else (state_attr(input_timer, "finishes_at") | as_datetime - now()).total_seconds() | int(0) %}
{% set r = 0 if state_attr(input_timer, "remaining") == none else strptime("1970-01-01 " + state_attr(input_timer, "remaining") + "-0000", "%Y-%m-%d %H:%M:%S%z", 0) | as_timestamp | int(0) %}

state of the timer: {{ s }}
time to reduce:                  a = {{ a }} seconds
duration of timer (when idle):   d = {{ d }} seconds
timer finishes at (when active): f = {{ f }} seconds
remaining time (when paused):    r = {{ r }} seconds

new time: 
{%- if s == "idle" and d <= 10 -%}
  (a) {{ a }}
{%- elif s == "idle" -%}
  (d-a) {{ d-a }}
{%- elif s == "paused" -%}
  (r-a) {{ r-a }}
{%- elif s == "active" -%}
  (f-a) {{ f-a }}
{%- endif -%}

I don’t know what a timers does when you give it a negative time, if that makes trouble there is a check required if a is bigger then d, f or a depending on the timer state (s).

Thank you very much for the code, I will try to apply it as soon as I have bit of spare time.

I found one big problem, that the blueprint does not block the Internet after allocated time and there is no message “Das wars für heute”
Instead of it the timer restarts on the same day (instead of after midnight) and you can continue using the Internet.
I initially thought that problem is with my modified version, but I tried to use your version and it does the same thing. The only difference in my blueprint is this code:

   device:
      name: Open WRT Router
      selector:
        entity:
          filter:
          - domain:
            - switch
            integration: template

The cards were done exactly with you code just with different entity names.

Do you have any idea what could be the problem?

I tried to debug the script, unfortunately my yaml knowledge is too poor to be able to do so, but I think the problem might be somewhere here?

    sequence:
    - service: switch.turn_on
      target:
        entity_id: !input device
    - service: timer.start
      target:
        entity_id: !input timer
  - conditions:
    - condition: trigger
      id: timer_finished
    sequence:
    - service: switch.turn_off
      target:
        entity_id: !input device
  - conditions:
    - condition: trigger
      id: midnight
    sequence:
    - service: timer.start
      target:
        entity_id: !input timer
      data:
        duration: '{{ states(input_default_time) | string }}

          '
    - service: timer.pause
      target:
        entity_id: !input timer

This condition does not seem to be working properly or at least it seem like the id: midnight is ignored.

 - conditions:
    - condition: trigger
      id: midnight

For now I have to disable the automation manually every day which is quite annoying as my daughter abuses the situation and goes happily into another counter loop so I have to watch when her time runs out.
EDIT: I managed to workaround using couple of Automation tasks, one disables the automation when timer goes to idle and another one enables it after midnight so I am good for now!

It would be still nice the find out where the problem is and have it resolved within the blueprint.

Let’s hope she uses her hacking skills as a white hat when she grows up :wink:

The trick with the timer is to configure it with a duration of 0, so the timer will reset to 0 when it has finished. At midnight the blueprint starts the timer with the value of default_time and immediately pauses it so it waits to get started with the allowed time.

Now it’s the little hacker’s turn to find a way to overcome the timer again :space_invader: