Custom-card "Printer"¶
This is the custom_card_sisimomo_printer
, used to show the state of a printer including, if wanted, ink sensors.
The card has support any number of ink sensors under the state of the printer. These can be configured using custom colors and labels.
Credits¶
Author: Sisimomo (based on hiddevanbrussel pictures) Version: 0.1.0
Contributors:
- ByteFloater Version 0.2.0
Changelog¶
0.1.0 - Initial Release
- Initial release0.2.0 - Added additional cases
- Added support for other cartridge types (tricolor) - Added further error checking for previously uncaught states - Added support for the IPP 'unavailable' state - Added CSS for better theming of error screens - Added card string translation files - Changed `text-transform` of label to capitalize - Changed `ulm_unavailable` to `ulm_translation_unavailable` - Removed some unnecessary inline stylings - Fixed the handling of unavailable and idle state stylingCard options¶
Options | Required | Description |
---|---|---|
entity | The entity_id for the large card |
Variables¶
Variable | Required | Description |
---|---|---|
printer_name | The chosen display name of the printer. If not provided, will use the friendly name of the provided entity. |
|
cartridges | A list of Cartridge entity objects. (See below) |
Cartridge entity¶
Variable | Required | Description | Requirement |
---|---|---|---|
label | The label for the ink sensor. For better aesthetic, keep this string short eg: "BK", "Y", "M", "C", "PB" | ||
entity_id | The entity_id of the ink sensor | Must be a value between 0-100 (percentage). | |
type | The type of cartridge associated with the ink sensor | Must be either 'unicolor' or 'tricolor'. If not provided, 'unicolor' is assumed for backwards compatibility. |
|
color | The color of the ink bar | For unicolor cartridges, must be a single CSS Legal Color Value. For tricolor cartridges, 3 colours are required. (See usage for more info) |
Usage¶
Unicolor Printers¶
- type: "custom:button-card"
template: "custom_card_sisimomo_printer"
entity: sensor.hp_printer_status
variables:
printer_name: HP LaserJet MFP M28w
cartridges:
- label: "BK"
entity_id: sensor.printer_black_ink
type: unicolor
color: "black"
- label: "B"
entity_id: sensor.printer_photo_black_ink
type: unicolor
color: "black"
- label: "Y"
entity_id: sensor.printer_yellow_ink
type: unicolor
color: "rgba(var(--color-yellow), 1)"
- label: "M"
entity_id: sensor.printer_magenta_ink
type: unicolor
color: "#F84B7A"
- label: "C"
entity_id: sensor.printer_cyan_ink
type: unicolor
color: "#427EDE"
- label: "PB"
entity_id: sensor.printer_photo_blue_ink
type: unicolor
color: "#9272BE"
Tricolor Printers¶
- type: "custom:button-card"
template: custom_card_sisimomo_printer
entity: sensor.canon_mg3600_series
variables:
ulm_card_printer_name: Canon MG3650
cartridges:
- label: "Col"
entity_id: sensor.canon_mg3600_series_black
type: tricolor
color:
- cyan
- magenta
- yellow
- label: "BK"
entity_id: sensor.canon_mg3600_series_black
type: unicolor
color: black
Template code¶
Template Code
custom_card_sisimomo_printer.yaml
---
custom_card_sisimomo_printer:
template:
- "ulm_translation_engine"
- "ulm_language_variables"
variables:
printer_name: "[[[ entity.attributes.friendly_name; ]]]"
ulm_idle: "idle"
show_icon: false
show_label: false
show_name: false
triggers_update: "all"
tap_action:
action: ""
styles:
grid:
- grid-template-areas: "'printer_state' 'cartridges'"
- grid-template-columns: "1fr"
- grid-template-rows: "min-content"
card:
- border-radius: "var(--border-radius)"
- box-shadow: "var(--box-shadow)"
- padding: "12px"
- "--mdc-ripple-press-opacity": 0
- cursor: "default"
custom_fields:
printer_state:
card:
type: "custom:button-card"
template: |
[[[
return (
entity.state.toLowerCase() != variables.ulm_idle.toLowerCase()
&& entity.state.toLowerCase() != variables.ulm_translation_unavailable.toLowerCase()
? [ "icon_info", "blue_no_state" ] : [ "icon_info" ]
);
]]]
tap_action:
action: "more-info"
label: "[[[ return entity.state; ]]]"
name: "[[[ return variables.printer_name; ]]]"
entity: "[[[ return entity.entity_id; ]]]"
styles:
card:
- padding: "0"
- "--mdc-ripple-press-opacity": 0.12
- cursor: "pointer"
label:
- text-transform: "capitalize"
cartridges: |
[[[
// Source: https://stackoverflow.com/a/56266358
const isColor = (strColor) => {
const s = new Option().style;
s.color = strColor;
return s.color !== '';
}
let toner_info_available = true;
if (variables.cartridges !== undefined ? Array.isArray(variables.cartridges) && variables.cartridges.length > 0 : false) {
let errorArray = [];
variables.cartridges.forEach(cartridge => {
let index = variables.cartridges.indexOf(cartridge);
let valid_cartridge_types = ['unicolor', 'tricolor']
// Confirm that the label is provided.
if (cartridge.label === undefined) {
errorArray.push(`cartridges.[${index}].label: You must provide a value.`);
}
// Confirm that a valid cartridge type is provided, if not default to 'unicolor'
// for backwards compatibility with older configuration files
if (cartridge.type === undefined) {
cartridge.type = 'unicolor'
} else if (!valid_cartridge_types.includes(cartridge.type)) {
errorArray.push(`cartridges.[${index}].type: You must provide a valid cartridge type`);
}
// Confirm that the color is provided and is valid color css.
if (cartridge.color !== undefined) {
if (cartridge.type === 'unicolor') {
if (typeof cartridge.color === 'string' || cartridge.color instanceof String ? !isColor(cartridge.color) : false) {
errorArray.push(`cartridges.[${index}].color: You must provide a single valid CSS color value.`);
}
} else if (Array.isArray(cartridge.color) && cartridge.color.length === 3 ? cartridge.type === 'tricolor' : false) {
cartridge.color.forEach(color => {
let col_index = cartridge.color.indexOf(color);
if (!isColor(String(color))) {
errorArray.push(`cartridges.[${index}].color.[${col_index}]: You must provide a single valid CSS color value.`);
}
});
} else {
errorArray.push(`cartridges.[${index}].color: Invalid combination of colour and type.`);
}
} else {
errorArray.push(`cartridges.[${index}].color: You must provide a value.`);
}
// Confirm that the entity_id is provided, is a valid entity_id, a integer and a value between 0 and 100 inclusively.
if (cartridge.entity_id === undefined) {
errorArray.push(`cartridges.[${index}].entity_id: You must provide a value.`);
} else if (states[cartridge.entity_id] === undefined) {
errorArray.push(`cartridges.[${index}].entity_id: You must provide a existing entity_id.`);
} else if (String(states[cartridge.entity_id].state).toLowerCase() === String(variables.ulm_translation_unavailable).toLowerCase()) {
toner_info_available = false;
} else if (isNaN(states[cartridge.entity_id].state) || typeof states[cartridge.entity_id].state === "boolean") {
errorArray.push(`cartridges.[${index}].entity_id: You must provide a entity representing an integer.`);
} else if (states[cartridge.entity_id].state < 0 || states[cartridge.entity_id].state > 100) {
errorArray.push(`cartridges.[${index}].entity_id: You must provide a entity representing an integer between 0 and 100 inclusively.`);
}
});
if (errorArray.length > 0) {
return `<div class="error-container">
<b>Configuration Error:</b>
<ul>
${errorArray.map(error => `<li>${error}</li>`).join("")}
</ul>
</div>`;
}
if (toner_info_available) {
return '<div class="wrapper">' +
variables.cartridges.map(cartridge => {
if (cartridge.type === "unicolor") {
cartridge.bar_style = `
background-color: ${cartridge.color};
width: ${states[cartridge.entity_id].state}%;
`;
} else if (cartridge.type === "tricolor") {
cartridge.bar_style = `
background: linear-gradient(
180deg,
${cartridge.color[0]},
${cartridge.color[0]} 33%,
${cartridge.color[1]} 33%,
${cartridge.color[1]} 66%,
${cartridge.color[2]} 66%,
${cartridge.color[2]}
);
width: ${states[cartridge.entity_id].state}%;
`;
}
// Removes unnecessary whitespace from inline CSS
cartridge.bar_style = cartridge.bar_style.replace(/\s{2,}/g, '')
return `
<div class="label">${cartridge.label}</div>
<div class="container-bar">
<div class="bar" style="${cartridge.bar_style}"></div>
</div>
<div class="state">${states[cartridge.entity_id].state}%</div>
`;
}).join("") +
'</div>';
} else {
return `
<div class="info-unavailable">
Toner Information Unavailable
</div>
`;
}
} else {
}
]]]
card_mod:
style: |
/* Cartridge CSS */
div#cartridges .wrapper {
display: grid;
grid-template-columns: auto 1fr auto;
grid-gap: 1rem;
padding: 12px 8px 8px 8px;
}
div#cartridges .wrapper > *:nth-child(3n-2), .wrapper > *:nth-child(3n) {
place-self: center start;
}
div#cartridges .wrapper > .label {
filter: opacity(70%);
font-size: medium;
}
div#cartridges .wrapper > .container-bar {
position: relative;
border-radius: 4px;
border: 0.01rem solid rgba(var(--color-theme),.35);
}
div#cartridges .wrapper > .container-bar .bar {
height: 20px;
border-radius: 4px;
}
div#cartridges .wrapper > .state {
filter: opacity(40%);
font-size: medium;
}
/* Error CSS */
div#cartridges .error-container {
text-align: left;
font-size: 75%;
font-family: var(--code-font-family, monospace);
padding: 10px;
background-color: rgba(219, 68, 55, 0.75);
margin-top:10px;
border-radius:8px;
}
div#cartridges .error-container ul {
list-style: none;
padding: 0;
margin: 0;
overflow-wrap: break-word;
word-wrap: break-word;
white-space: normal !important;
}
div#cartridges .error-container ul li {
margin-top: 0.5em;
}
div#cartridges .info-unavailable {
padding: 1em;
white-space: normal;
margin-top:10px;
border-radius:8px;
opacity: 60%;
}