Custom Component: SkyQ Media Player

Hi All

I thought I’d add some info on how I’m using the Scheduled Recording Info that Roger kindly added in the latest release following my request on Github, this might be useful to some particularly around querying the attributes within the “recording” array as the array only exists when the box is actually recording and isn’t a simple state_attr type query and took me a while to get right.

Firstly some code I use on my dashboard to show the status, showing what’s recording if anything, what’s next scheduled to record and when, and the disk space. Obviously change the sensor.sky_q_living_room_schedule sensor to your own sensor name then put the code in a Markdown card (as it allows som basic formatting). I’m not sure what happens to this if no future schedule is set so probably needs some error checking although we’ve always got series links scheduled so I’ve not got the need to handle that scenario.

{% set recordings = state_attr('sensor.skyq_schedule', 'skyq_recordings') %}
{% if recordings is sequence and recordings|length > 0 and recordings[0].skyq_recording_title is defined %}
**Recording Now:** {{recordings[0].skyq_recording_title }}
  {{as_timestamp (recordings[0].skyq_recording_start) | timestamp_custom('**Started:** %H:%M') }}
  {{as_timestamp (recordings[0].skyq_recording_end) | timestamp_custom('**Ends:** %H:%M') }}
{% else %}
**Not Recording**
{% endif %}
**Next Recording:** {{state_attr ('sensor.skyq_schedule', 'skyq_scheduled_title')}}
  {{ as_timestamp(state_attr('sensor.skyq_schedule', 'skyq_scheduled_start')) | timestamp_custom('Starts: %A %dth %H:%M') }} (in {{states ('sensor.minutes_next_sky_recording')}} minutes )
  {{ as_timestamp(state_attr('sensor.skyq_schedule', 'skyq_scheduled_end')) | timestamp_custom('Ends: %A %dth %H:%M') }}

**Disk Capacity Remaining:** {{states ('sensor.skyq_used_storage')}}Gb ( {{state_attr ('sensor.skyq_used_storage', 'skyq_storage_percent')}}% )

I also added the following 3 sensors in my sensor.yaml so I can trigger automations based on the recording status of the main box and mini, turning it off overnight via a smart switch when not recording and the box or our mini isn’t active, and turn back on when the time to next recording is less than 10 minutes for example.

      skyq_minutes_next_recording:
      friendly_name: "Minutes until Next Sky Q Recording"
      unit_of_measurement: "m"
       value_template: >-
         {{((state_attr('sensor.skyq_schedule', 'skyq_scheduled_start')|as_timestamp|int - 
now()|as_timestamp|int)/60)|int}}
     skyq_recording_status:
      friendly_name: "Sky Q Main Box is Recording"
       value_template: >
         {{state_attr('sensor.skyq_schedule', 'recordings') is not none}}
     skyq_in_use:
       friendly_name: "Sky Q in use"
       value_template: >
         {{is_state('media_player.sky_q_living_room', 'playing')
           or is_state('media_player.sky_q_mini_kitchen', 'playing')
           or is_state('media_player.sky_q_living_room', 'paused')
           or is_state('media_player.sky_q_mini_kitchen', 'paused')}}        

Hope this helps someone

cheers

Edited to update formatting

1 Like

I tried to use this sensor, but i get the following error:

TemplateSyntaxError: unexpected '>'

I am not so able about templates so i am not able to fix this error… can you help me?
And about the markdown i get:

TemplateSyntaxError: expected token ',', got 'Ends'

This uses the template integration which I believe is the correct way of creating template sensors. It also avoids an error being generated at startup

template:
  - sensor:
      - name: SkyQ minutes to next recording
        unit_of_measurement: "min"
        state: >-
          {% if is_state('sensor.sky_q_schedule', 'Scheduled') %}
            {{((state_attr('sensor.sky_q_schedule', 'skyq_scheduled_start')|as_timestamp|int - now()|as_timestamp|int)/60)|int}}
          {% else %}
            0
          {% endif %}
1 Like

Sorry for the (maybe) stupid question.
This goes inside configuration.yaml and not inside sensor.yaml, exact?

Unless I know how you have setup your config files, I couldn’t answer that. For me it will go in any of my config files, for you probably in configuration.yaml.

1 Like

Sorry yes I forgot mine is only in sensor.yaml because I split out things like sensors, binary sensors and groups into their own files rather than bloating the configuration.yaml with loads of stuff.

You can add it all to your Configuration.yaml or if you want to do something similar to the above just add

sensor: !include sensor.yaml

to your configuration.yaml and then create a separate file called sensor.yaml in the same folder with all your sensor code in, with this on the first two lines.

- platform: template
 sensors:

then add the code for each sensor you want to create

1 Like

It’s worth having a look at how packages work, then you can group by function (such as SkyQ) rather than by entity type.

This is my complete configuration.yaml

homeassistant:
  packages: !include_dir_named packages/ 

1 Like

Thanks, not come across that before

This needed tweaking to work for me Roger because as soon as the Sky box turns off the schedule state goes to “Scheduled - Off”, the sensor state is no longer “Scheduled” so reverts to the else statement and gets zero’d, my power on automation script then sees minutes until next recording is now below 10 and turns it back on again ready to record, at which point the schedule state goes back to Scheduled, updates that the next schedule isn’t until tomorrow night so 1000 minutes or whatever so it then turns off again, then continues in that loop indefinitely :smile:

This tweak seems to work though

          {% if 'Scheduled' in states('sensor.skyq_schedule') %}
            {{((state_attr('sensor.skyq_schedule', 'skyq_scheduled_start')|as_timestamp|int - now()|as_timestamp|int)/60)|int}}
          {% else %}
            9999
          {% endif %}

So now the if statement is basically looking for the word “Scheduled” as a wildcard so finds both “Scheduled” and “Scheduled - Off”.

Also I’ve set the else option to 9999 rather than 0 as my automation set to turn the device back prior to a recording needing to start will get triggered by a low number so if there’s nothing scheduled it will end up in the same on-off-on loop as above.

Edit: actually that still doesn’t give 100% failsafe because I’ve just seen the schedule attribute go to “unavailable” during a power up cycle which would also reset the counter to 9999 or whatever you set the else statement to, so it could then miss a recording if it doesn’t subsequently update to the correct value. Too late to think about it any more tonight though :slight_smile:

1 Like

I’m looking to change this to make it slightly easier.

State will be:

  • none - Nothing going on
  • scheduled - Recording is scheduled in the future
  • recording - Recording going on now

There will be a new attribute skyq_box_state:

  • on - box is powered on
  • off - box is powered off

I also noted a bug in startup where state wasn’t being recovered from storage, so the state should be set quicker with the new release.

Also I have renamed the attribute recordings to skyq_recordings.

1 Like

With latest version, this should work:

template:
  - sensor:
      - name: SkyQ minutes to next recording
        unit_of_measurement: "min"
        state: >-
          {% if is_state('sensor.sky_q_schedule', 'scheduled') %}
            {{((state_attr('sensor.sky_q_schedule', 'skyq_scheduled_start')|as_timestamp|int - now()|as_timestamp|int)/60)|int}}
          {% elif  is_state('sensor.sky_q_schedule', 'unavailable') %}
            unavailable
          {% else %}
            9999
          {% endif %}
1 Like

Can you tell me how to change accordingly also the markdown card posted from @Locoblade ?

Sorry, I don’t use Markdown card.

Give this a go @maurizio53

{% set recordings = state_attr('sensor.skyq_schedule', 'skyq_recordings') %}
{% if recordings is sequence and recordings|length > 0 and recordings[0].skyq_recording_title is defined %}
**Recording Now:** {{recordings[0].skyq_recording_title }}
  {{as_timestamp (recordings[0].skyq_recording_start) | timestamp_custom('**Started:** %H:%M') }}
  {{as_timestamp (recordings[0].skyq_recording_end) | timestamp_custom('**Ends:** %H:%M') }}
{% else %}
**Not Recording**
{% endif %}
**Next Recording:** {{state_attr ('sensor.skyq_schedule', 'skyq_scheduled_title')}}
  {{ as_timestamp(state_attr('sensor.skyq_schedule', 'skyq_scheduled_start')) | timestamp_custom('Starts: %A %dth %H:%M') }} (in {{states ('sensor.minutes_next_sky_recording')}} minutes )
  {{ as_timestamp(state_attr('sensor.skyq_schedule', 'skyq_scheduled_end')) | timestamp_custom('Ends: %A %dth %H:%M') }}

**Disk Capacity Remaining:** {{states ('sensor.skyq_used_storage')}}Gb ( {{state_attr ('sensor.skyq_used_storage', 'skyq_storage_percent')}}% )

Hi Roger

Can I suggest this alternate template sensor below that looks directly for the skyq_scheduled_start attribute then there’s no need to worry about the sensor.skyq_schedule “unavailable” state at all I don’t think? Also as my automations use numerical state as triggers / conditions this ensures it always has a numerical value for them to work with.

template:
  - sensor:
      - name: SkyQ minutes to next recording
        unit_of_measurement: "min"
        state: >-
          {% if not is_state_attr('sensor.skyq_schedule', 'skyq_scheduled_start', none) %}
            {{((state_attr('sensor.skyq_schedule', 'skyq_scheduled_start')|as_timestamp|int - now()|as_timestamp|int)/60)|int}}
          {% else %}
            9999
          {% endif %}

That should work. The important thing was to use is_state... to check for existence to avoid errors.

About the markdown i set it to this:

          - type: markdown 
            content: >-
              {% set recordings = state_attr('sensor.sky_q_schedule', 'skyq_recordings') %}
              {% if recordings is sequence and recordings|length > 0 and recordings[0].skyq_recording_title is defined %}

              **Recording Now:** {{ recordings[0].skyq_recording_title }}              
                {{as_timestamp (recordings[0].skyq_recording_start) | timestamp_custom('**Started:** %H:%M') }}
                {{as_timestamp (recordings[0].skyq_recording_end) | timestamp_custom('**Ends:** %H:%M') }}
                {% else %}
              **Not Recording**
                {% endif %}

              **Next Recording:** {{state_attr ('sensor.sky_q_schedule', 'skyq_recording_title')}}
                {{ as_timestamp(state_attr('sensor.sky_q_schedule', 'skyq_scheduled_start')) | timestamp_custom('Starts: %A %dth %H:%M') }} (in {{states ('sensor.minutes_next_sky_recording')}} minutes)
                {{ as_timestamp(state_attr('sensor.sky_q_schedule', 'skyq_scheduled_end')) | timestamp_custom('Ends: %A %dth %H:%M') }}

              **Disk Capacity Remaining:** {{states ('sensor.sky_q_used_storage')}}Gb ( {{state_attr ('sensor.sky_q_used_storage', 'skyq_storage_percent')}}% )

But i get nothing in the frontend and if i try it in the developers/models i always get the following error:

`TemplateSyntaxError: Encountered unknown tag 'else'

Can you tell me where i am wrong? And how to fix this?

EDIT: I found that the error lies in the ‘Next Recording’ section as if i disable this i get the markdown card related to ‘Recording Now’ shown in the proper way.
I am not so able with templates so i really need to understand where is the error…

Have you got the sensor “minutes_next_sky_recording” configured as per my previous post a couple of days ago

template:
  - sensor:
      - name: SkyQ minutes to next recording
        unit_of_measurement: "min"
        state: >-
          {% if not is_state_attr('sensor.skyq_schedule', 'skyq_scheduled_start', none) %}
            {{((state_attr('sensor.skyq_schedule', 'skyq_scheduled_start')|as_timestamp|int - now()|as_timestamp|int)/60)|int}}
          {% else %}
            9999
          {% endif %}

Other than that I’m not sure to be honest, I copied your code above, modified the schedule sensor name (as I named mine slightly differently) and it works fine. If the above doesn’t fix it try omitting each of the three lines in the Next Recording section one by one to see which one is triggering the error.

I Have this as copied from your post:

  - sensor:
      - name: SkyQ minutes to next recording
        unique_id: sky_q_recording_minutes
        unit_of_measurement: "min"
        state: >-
          {% if is_state('sensor.sky_q_schedule', 'scheduled') %}
            {{((state_attr('sensor.sky_q_schedule', 'skyq_scheduled_start')|as_timestamp|int - now()|as_timestamp|int)/60)|int}}
          {% elif  is_state('sensor.sky_q_schedule', 'unavailable') %}
            unavailable
          {% else %}
            9999
          {% endif %}

Now i’ll change it according to your actual post and see if it works…
Thanks for support!

I’ve just noticed that on this line of your previous post

 **Next Recording:** {{state_attr ('sensor.sky_q_schedule', 'skyq_recording_title')}}

You’ve got ‘skyq_recording_title’ when it should be ‘skyq_scheduled_title’. That doesn’t seem to cause an error though, just reports “none” for the upcoming program title that’s going to be recorded