Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework and Refinements to 'custom_card_sisimomo_printer' #1223

Merged
merged 8 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 61 additions & 10 deletions custom_cards/custom_card_sisimomo_printer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,59 @@ The card has support any number of ink sensors under the state of the printer. T
Author: [Sisimomo](https://github.com/sisimomo) (based on [hiddevanbrussel pictures](https://community.home-assistant.io/t/lovelace-ui-minimalist/322687/203))
Version: 0.1.0

Contributors:

- [ByteFloater](https://github.com/bytefloater) Version 0.2.0

## Changelog

<details>
<summary>0.1.0</summary>
Initial release.
<details open>
<summary>0.1.0 - Initial Release</summary>

- Initial release

</details>
<details open>
<summary>0.2.0 - Added additional cases</summary>

- 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 styling

</details>

## Card options

| Options | Required | Notes |
| Options | Required | Description |
|--------------|------------------|----------------|
| entity | :material-check: | The entity_id for the large card |

## Variables

| Variable | Required | Notes |
| Variable | Required | Description |
|----------------------------------------|------------------|----------------|
| printer_name | :material-close: | If not provide, will use the friendly name of the provided entity |
| cartridges | :material-close: | A list of `Cartridge entity` object (see below) |
| printer_name | :material-close: | The chosen display name of the printer. <br> If not provided, will use the friendly name of the provided entity. |
| cartridges | :material-close: | A list of `Cartridge entity` objects. (See below) |

## Cartridge entity

| Variable | Required | Notes | Requirement |
| Variable | Required | Description | Requirement |
|------------|------------------|----------------|-------------|
| label | :material-check: | The label for the ink sensor. For better aesthetic, keep this string short eg: "BK", "Y", "M", "C", "PB" | |
| entity_id | :material-check: | The entity_id of the ink sensor | Must be a value between 0-100 (percentage) |
| color | :material-close: | The color of the ink bar | Must be a [CSS Legal Color Value](https://www.w3schools.com/cssref/css_colors_legal.asp). |
| entity_id | :material-check: | The entity_id of the ink sensor | Must be a value between 0-100 (percentage). |
| type | :material-close: | The type of cartridge associated with the ink sensor | Must be either 'unicolor' or 'tricolor'. <br> If not provided, 'unicolor' is assumed for backwards compatibility. |
| color | :material-check: | The color of the ink bar | For unicolor cartridges, must be a single [CSS Legal Color Value](https://www.w3schools.com/cssref/css_colors_legal.asp). For tricolor cartridges, 3 colours are required. (See usage for more info) |

## Usage

### Unicolor Printers

```yaml
- type: "custom:button-card"
template: "custom_card_sisimomo_printer"
Expand All @@ -56,24 +79,52 @@ Version: 0.1.0
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

```yaml
- 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

??? note "Template Code"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
---
custom_card_sisimomo_printer:
template: "ulm_language_variables"
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
Expand All @@ -24,18 +29,24 @@ custom_card_sisimomo_printer:
type: "custom:button-card"
template: |
[[[
return entity.state.toLowerCase() != variables.ulm_idle && entity.state.toLowerCase() != variables.ulm_unavailable ? [ "icon_info", "blue_no_state" ] : [ "icon_info" ];
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 !== undefined ? variables.printer_name : entity.attributes.friendly_name; ]]]"
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
Expand All @@ -45,55 +56,115 @@ custom_card_sisimomo_printer:
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 the color is provided and is a valid color css.
if (cartridge.color === undefined) {

// 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.`);
} else if (!isColor(cartridge.color)) {
errorArray.push(`cartridges.[${index}].color: You must provide a valid css color 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 style="padding: 1em;background-color: rgba(219, 68, 55, 0.75);white-space: normal;">
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
<ul style="list-style: none;padding-left: 0;">
${errorArray.map(error => `<li style="margin-top: 0.5em;">${error}</li>`).join("")}
return `<div class="error-container">
<b>Configuration Error:</b>
<ul>
${errorArray.map(error => `<li>${error}</li>`).join("")}
</ul>
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
</div>`;
}

return '<div class="wrapper">' +
variables.cartridges.map(cartridge => {
return `<div class="label">${cartridge.label}</div>
<div class="container-bar">
<div class="bar" style="background-color: ${cartridge.color};width: ${states[cartridge.entity_id].state}%;"></div>
</div>
<div class="state">${states[cartridge.entity_id].state}%</div>`;
}).join("") +
'</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 {

}
]]]
style: |
/* Cartridge CSS */
div#cartridges .wrapper {
display: grid;
grid-template-columns: auto 1fr auto;
Expand All @@ -120,3 +191,32 @@ custom_card_sisimomo_printer:
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%;
}