Internet Printing Protocol (IPP) Integration - Show last know sensor state when Printer is offline?

I’m using the Internet Printing Protocol (IPP) integration to monitor the ink levels in my printer.
This works well when the printer is online, with the following gauge cards (horizontal stack) appearing.
Capture

However, when the printer is switched off I get this.
Capture

Is there any way to override this, so the card is displaying the last known sensor state (excluding unavailable) instead? I just want to be able to see what the ink levels are/were last time the
printer was online.

Here’s the card yaml.

cards:
  - entity: sensor.hp_photosmart_5520_series_cyan_ink
    max: 100
    min: 0
    name: Cyan
    severity:
      green: 25
      red: 0
      yellow: 10
    type: gauge
  - entity: sensor.hp_photosmart_5520_series_magenta_ink
    max: 100
    min: 0
    name: Magenta
    severity:
      green: 25
      red: 0
      yellow: 10
    type: gauge
  - entity: sensor.hp_photosmart_5520_series_yellow_ink
    max: 100
    min: 0
    name: Yellow
    severity:
      green: 25
      red: 0
      yellow: 10
    type: gauge
  - entity: sensor.hp_photosmart_5520_series_black_ink
    max: 100
    min: 0
    name: Black
    severity:
      green: 25
      red: 0
      yellow: 10
    type: gauge
title: Printer Ink
type: horizontal-stack

Many thanks

3 Likes

I’m trying to do exactly the same thing. So far I’m not getting anywhere…

Same here. I really would like it to store the last known values (a bonus would be displaying the time of those values).

Instead, my log file is flooded with those error messages

2020-08-17 22:38:52 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:38:52 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 5 seconds.
2020-08-17 22:39:00 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:39:00 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 10 seconds.
2020-08-17 22:39:14 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:39:14 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 20 seconds.
2020-08-17 22:39:38 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:39:38 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 40 seconds.
2020-08-17 22:40:22 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:40:22 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 80 seconds.
2020-08-17 22:41:46 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:41:46 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 80 seconds.
2020-08-17 22:43:10 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:43:10 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 80 seconds.
2020-08-17 22:44:34 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:44:34 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 80 seconds.
2020-08-17 22:45:58 ERROR (MainThread) [homeassistant.components.ipp] Error fetching ipp data: Invalid response from API: Error occurred while communicating with IPP server.
2020-08-17 22:45:58 WARNING (MainThread) [homeassistant.config_entries] Config entry for ipp not ready yet. Retrying in 80 seconds.

Hi everybody,
I see this is an old thread but I would like to be helpful.

I had the same problem with a Canon printer.
Its sensor become unavailable when it is idle and HA is not able to render the values.

A friend of mine (very very smart, much more than me) gave me a good solution.
You should create some MQTT sensor, one for every ink cartridge and publish every single value when the printer is on.
MQTT sensors remember the values so the printer going idle is not. problem anymore.
You should obviously modify your card pointing to the MQTT sensors …

Below you can find my package

#############################
#  package per la gestione  #
# del livello di inchiostro #
#   delle cartucce Canon    #
#############################
#
### automazioni ###
#
automation:

- alias: INK Retain
  trigger:
  - platform: state
    entity_id: sensor.canon_ts8000_series_black_bk, sensor.canon_ts8000_series_black_pgbk, sensor.canon_ts8000_series_cyan, sensor.canon_ts8000_series_gray, sensor.canon_ts8000_series_magenta, sensor.canon_ts8000_series_yellow
  condition:
    - condition: template
      value_template: "{{ trigger.to_state.state != 'unknown' and trigger.to_state.state != 'unavailable' }}"
  action:
  - service: mqtt.publish
    data_template:
      topic: "ink/{{ trigger.entity_id }}/STATE"
      payload: "{{ trigger.to_state.state }}"
      retain: true
#
#
#### sensori mqtt #####
#
sensor:

  - platform: mqtt
    name: "canon_black_bk_mqtt"
    state_topic: "ink/sensor.canon_ts8000_series_black_bk/STATE"

  - platform: mqtt
    name: "canon_black_pgbk_mqtt"
    state_topic: "ink/sensor.canon_ts8000_series_black_pgbk/STATE"

  - platform: mqtt
    name: "canon_cyan_mqtt"
    state_topic: "ink/sensor.canon_ts8000_series_cyan/STATE"

  - platform: mqtt
    name: "canon_gray_mqtt"
    state_topic: "ink/sensor.canon_ts8000_series_gray/STATE"

  - platform: mqtt
    name: "canon_magenta_mqtt"
    state_topic: "ink/sensor.canon_ts8000_series_magenta/STATE"

  - platform: mqtt
    name: "canon_yellow_mqtt"
    state_topic: "ink/sensor.canon_ts8000_series_yellow/STATE"
#
#
# end of file #

I hope this can help…

Thanks to liuk4friends, but I did try MQTT and found it still wasn’t persisting. Anyway, I eventually solved this by creating a series of automations (one per colour) to store the values within text files. The I created four template sensors to read the values from these text files. As the text files obviously persist over a restart, so the values are always available.

# RETAINED PRINTER INK LEVELS
  - platform: template
    sensors:
      ink_level_black:
        friendly_name: "Ink Level Black"
        unit_of_measurement: '%'
        value_template: >
          {% if is_state('sensor.hp_photosmart_5520_series_black_ink', 'unavailable') %}
            {{ states('input_text.text1') }}
          {% else %}
            {{ states('sensor.hp_photosmart_5520_series_black_ink') }}
          {% endif %}
  - platform: template
    sensors:
      ink_level_cyan:
        friendly_name: "Ink Level Cyan"
        unit_of_measurement: '%'
        value_template: >
          {% if is_state('sensor.hp_photosmart_5520_series_cyan_ink', 'unavailable') %}
            {{ states('input_text.text2') }}
          {% else %}
            {{ states('sensor.hp_photosmart_5520_series_cyan_ink') }}
          {% endif %}
  - platform: template
    sensors:
      ink_level_magenta:
        friendly_name: "Ink Level Magenta"
        unit_of_measurement: '%'
        value_template: >
          {% if is_state('sensor.hp_photosmart_5520_series_magenta_ink', 'unavailable') %}
            {{ states('input_text.text3') }}
          {% else %}
            {{ states('sensor.hp_photosmart_5520_series_magenta_ink') }}
          {% endif %}
  - platform: template
    sensors:
      ink_level_yellow:
        friendly_name: "Ink Level Yellow"
        unit_of_measurement: '%'
        value_template: >
          {% if is_state('sensor.hp_photosmart_5520_series_yellow_ink', 'unavailable') %}
            {{ states('input_text.text4') }}
          {% else %}
            {{ states('sensor.hp_photosmart_5520_series_yellow_ink') }}
          {% endif %}

This required that I also created the below input text entries in my config.yaml.

input_text:
  text1:
    name: Ink Level - Black
  text2:
    name: Ink Level - Cyan
  text3:
    name: Ink Level - Magenta
  text4:
    name: Ink Level - Yellow

And here’s the automations which tie the 2 parts together.

- id: Black Ink
  alias: Record Black Ink Level
  trigger:
    platform: state
    entity_id: sensor.hp_photosmart_5520_series_black_ink
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state not in [trigger.from_state.state, ''unavailable'']
      }}

      '
  action:
    service: input_text.set_value
    entity_id: input_text.text1
    data_template:
      value: '{{ trigger.to_state.state }}'
- id: Cyan Ink
  alias: Record Cyan Ink Level
  trigger:
    platform: state
    entity_id: sensor.hp_photosmart_5520_series_cyan_ink
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state not in [trigger.from_state.state, ''unavailable'']
      }}

      '
  action:
    service: input_text.set_value
    entity_id: input_text.text2
    data_template:
      value: '{{ trigger.to_state.state }}'
- id: Magenta Ink
  alias: Record Magenta Ink Level
  trigger:
    platform: state
    entity_id: sensor.hp_photosmart_5520_series_magenta_ink
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state not in [trigger.from_state.state, ''unavailable'']
      }}

      '
  action:
    service: input_text.set_value
    entity_id: input_text.text3
    data_template:
      value: '{{ trigger.to_state.state }}'
- id: Yellow Ink
  alias: Record Yellow Ink Level
  trigger:
    platform: state
    entity_id: sensor.hp_photosmart_5520_series_yellow_ink
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state not in [trigger.from_state.state, ''unavailable'']
      }}

      '
  action:
    service: input_text.set_value
    entity_id: input_text.text4
    data_template:
      value: '{{ trigger.to_state.state }}'

I recently replaced most of my automations with equivalents in Node Red. So here’s the flow for these too.

Capture

[{"id":"5c573fe4.d4ebb","type":"server-state-changed","z":"4427d2af.513fec","name":"Record Black Ink Level","server":"6009dbec.e68c94","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.hp_photosmart_5520_series_black_ink","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"unavailable","halt_if_type":"str","halt_if_compare":"is_not","outputs":2,"output_only_on_state_change":true,"x":140,"y":720,"wires":[["db080e61.fec17"],[]]},{"id":"db080e61.fec17","type":"api-call-service","z":"4427d2af.513fec","name":"Store Black Ink Level","server":"6009dbec.e68c94","version":1,"debugenabled":true,"service_domain":"input_text","service":"set_value","entityId":"input_text.text1","data":"{\"value\":\"{{payload}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":420,"y":720,"wires":[[]]},{"id":"211e314d.61686e","type":"server-state-changed","z":"4427d2af.513fec","name":"Record Cyan Ink Level","server":"6009dbec.e68c94","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.hp_photosmart_5520_series_cyan_ink","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"unavailable","halt_if_type":"str","halt_if_compare":"is_not","outputs":2,"output_only_on_state_change":true,"x":140,"y":780,"wires":[["f4cde81d.c28678"],[]]},{"id":"f4cde81d.c28678","type":"api-call-service","z":"4427d2af.513fec","name":"Store Cyan Ink Level","server":"6009dbec.e68c94","version":1,"debugenabled":false,"service_domain":"input_text","service":"set_value","entityId":"input_text.text2","data":"{\"value\":\"{{payload}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":400,"y":780,"wires":[[]]},{"id":"9cc7c692.8c2258","type":"server-state-changed","z":"4427d2af.513fec","name":"Record Magenta Ink Level","server":"6009dbec.e68c94","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.hp_photosmart_5520_series_magenta_ink","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"unavailable","halt_if_type":"str","halt_if_compare":"is_not","outputs":2,"output_only_on_state_change":true,"x":150,"y":840,"wires":[["71a49633.eb7498"],[]]},{"id":"71a49633.eb7498","type":"api-call-service","z":"4427d2af.513fec","name":"Store Magenta Ink Level","server":"6009dbec.e68c94","version":1,"debugenabled":false,"service_domain":"input_text","service":"set_value","entityId":"input_text.text3","data":"{\"value\":\"{{payload}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":410,"y":840,"wires":[[]]},{"id":"dd6fce60.3c61","type":"server-state-changed","z":"4427d2af.513fec","name":"Record Yellow Ink Level","server":"6009dbec.e68c94","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.hp_photosmart_5520_series_yellow_ink","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"unavailable","halt_if_type":"str","halt_if_compare":"is_not","outputs":2,"output_only_on_state_change":true,"x":140,"y":900,"wires":[["35d35a.fd84dca6"],[]]},{"id":"35d35a.fd84dca6","type":"api-call-service","z":"4427d2af.513fec","name":"Store Yellow Ink Level","server":"6009dbec.e68c94","version":1,"debugenabled":false,"service_domain":"input_text","service":"set_value","entityId":"input_text.text4","data":"{\"value\":\"{{payload}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":400,"y":900,"wires":[[]]},{"id":"6009dbec.e68c94","type":"server","z":"","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Now my printer ink levels are retained, even after a restart. :grinning:

NB: This approach would obviously work for any sensor I’d assume.

2 Likes

Thank you @Teleportist,
In the last few days I’ve noticed that also my MQTT ink level sensors weren’t persisting.
I was wondering about some problem related to the breaking changes of 0.115 and 0.116 updates.

Now I’ve tried your solution and it works very well … at least in the last ten minutes! :grin:
thank you again

Ops … I went too fast … when the printer goes into standby all sensors become ‘unknown’

Sorry to hear it didn’t work for you. Maybe try changing ‘unavailable’ to ‘unknown’ in my above code?

1 Like

Hello, same problem solved this way :
I use var addon https://github.com/snarky-snark/home-assistant-variables.
with value_template which says
{%if is_state("sensor....", "unavailable") %} {{states("var.inklevel") }} else {{ states(sensor....") }}

Doing so the variable updates only when sensor is available. Works fine !
Of course the lovelace card shows the variable :wink:

1 Like

Thank you @Teleportist and @phd62 for your kind suggestions.
I think for some time I will try to use the “MQTT” solution
If I still have problems I will try to follow your instructions

Hi @phd62,

Could you explain me more in depth how you did please?

Maybe in the meantime I have found the solution for the MQTT strategy.
At the end of the automation I’ve put the command below

  mode: queued

New sensors have been updated and values persisted after HA restart, HA reboot and printer going cyclically from on / off / standby / on

of course, this is my may:
1- in HACS integrations add Variable integration: https://github.com/snarky-snark/home-assistant-variables
2- Declare variable in configuration.yaml

var:
  hp300black:
    tracked_entity_id: sensor.hp_laserjet_300
    value_template: >-
      {% if is_state("sensor.hp_laserjet_300" , "unavailable")  %}
         {{ states("var.hp300black") }}
      {% else %}
         {{ states("sensor.hp_laserjet_300") }}
      {% endif %} 
    friendly_name: "HP300 Noir"
    unit_of_measurement: "%"

3- use variable in a bar card, for example:

              direction: up
              entities:
                - color: '#333333'
                  entity: var.hp300black
                  name: Black
                - color: '#00FFFF'
                  entity: var.hp300cyan
                  name: Cyan
                - color: '#FF00FF'
                  entity: var.hp300magenta
                  name: Magenta
                - color: '#FFFf00'
                  entity: var.hp300yellow
                  name: Yellow
              entity_config: null
              entity_row: false
              height: 100px
              max: 100
              min: 0
              positions:
                icon: 'off'
                indicator: 'off'
                minmax: 'off'
                value: outside
              stack: horizontal
              type: 'custom:bar-card'

Hope this will be useful

1 Like

I’m doing something wrong. Can you help me.
Variable in HACS installed. Var in the configuration file as shown below.
The same code passed to the development tools shows the correct values, but the card used in HA values for all entries is always unknown.

var:
  epsonblack:
    tracked_entity_id: sensor.epson_wf_3620_series_black_ink
    value_template: >-
      {% if is_state("sensor.epson_wf_3620_series_black_ink" , "unavailable")  %}
         {{ states("var.epsonblack") }}
      {% else %}
         {{ states("sensor.epson_wf_3620_series_black_ink") }}
      {% endif %} 
    friendly_name: "epsonblack"
    unit_of_measurement: "%"
  epsoncyan:
    tracked_entity_id: sensor.epson_wf_3620_series_cyan_ink
    value_template: >-
      {% if is_state("sensor.epson_wf_3620_series_cyan_ink" , "unavailable")  %}
         {{ states("var.epsoncyan") }}
      {% else %}
         {{ states("sensor.epson_wf_3620_series_cyan_ink") }}
      {% endif %} 
    friendly_name: "epsoncyan"
    unit_of_measurement: "%"
  epsonmagenta:
    tracked_entity_id: sensor.epson_wf_3620_series_magenta_ink
    value_template: >-
      {% if is_state("sensor.epson_wf_3620_series_magenta_ink" , "unavailable")  %}
         {{ states("var.epsonmagenta") }}
      {% else %}
         {{ states("sensor.epson_wf_3620_series_magenta_ink") }}
      {% endif %} 
    friendly_name: "epsonmagenta"
    unit_of_measurement: "%"
  epsonyellow:
    tracked_entity_id: sensor.epson_wf_3620_series_yellow_ink
    value_template: >-
      {% if is_state("sensor.epson_wf_3620_series_yellow_ink" , "unavailable")  %}
         {{ states("var.epsonyellow") }}
      {% else %}
         {{ states("sensor.epson_wf_3620_series_yellow_ink") }}
      {% endif %} 
    friendly_name: "epsonyellow"
    unit_of_measurement: "%"
  epsonblack_1:
    tracked_entity_id: sensor.epson_wf_3620_series_black_ink
    value_template: >-
      {% if is_state("sensor.epson_wf_3620_series_black_ink" , "Unavailable")  %}
         {{ states("var.epsonblack_1") }}
      {% else %}
         {{ states("sensor.epson_wf_3620_series_black_ink") }}
      {% endif %}

Dont forget you must get your printer connected at least once, so that var gets a initial numeric value a first time.

Then , “unavailable” in the template is the value of sensors that we want to ignore.
Depending on values returned by your sensor, it could be useful to replace “unavailable” by “Unknown” or “unknown”

(same problem as above )

Thank You phd62. It was problem on my side. Its need for epson longer time to get values.