Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/npm_and_yarn/rollup-plugin-impo…
Browse files Browse the repository at this point in the history
…rt-css-3.4.0
  • Loading branch information
maxwroc authored Feb 11, 2024
2 parents 8dff0e2 + b665109 commit 0b5e24e
Show file tree
Hide file tree
Showing 32 changed files with 900 additions and 178 deletions.
10 changes: 9 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ assignees: ''
**YAML configuration**
```yaml

# please paste here your card config
# please paste here your card config (before backticks below; do not remove them)

```

***Entity debug data***
<!-- Add "debug: true" in your card configuration and paste below entity data from the debug output -->

```json

```

Expand All @@ -32,5 +39,6 @@ assignees: ''
**Version**
<!-- What is the version of the card? -->
<!-- The best and most reliable way to check the version is to look at the Developer Tools Console in your browser (Win-Chrome - F12 key) -->
<!-- The other way to check it is to add "debug: true" in card config and expand debug output - version can be foud there -->

<!-- If regression happened after updating Home assistant please add HA version as well. -->
1 change: 1 addition & 0 deletions .github/workflows/continous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
branches:
- master
- next
- vNext

jobs:
continous_integration:
Expand Down
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ filter:
include:
- name: "attributes.device_class"
value: "battery"
exclude:
- name: "entity_id"
value: "binary_sensor.*"
sort:
by: "state"
collapse: 8
Expand Down Expand Up @@ -104,6 +107,7 @@ These options can be specified both per-entity and at the top level (affecting a
| value_override | [KString](#keyword-string-kstring) | | v3.0.0 | Allows to override the battery level value. Note: when used the `multiplier`, `round`, `state_map` setting is ignored
| non_battery_entity | boolean | `false` | v3.0.0 | Disables default battery state sources e.g. "battery_level" attribute
| default_state_formatting | bollean | `true` | v3.1.0 | Can be used to disable default state formatting e.g. entity display precission setting
| debug | boolean \| string | `false` | v3.2.0 | Whether to show debug otuput (all available entity data). You can use entity_id if you want to debug specific one.

### Keyword string (KString)

Expand Down Expand Up @@ -778,6 +782,93 @@ resources:
type: module
```

## Troubleshooting

You can turn on the debug output via `debug` setting. It can be turned on for all of the entities:

```yaml
debug: true
```

Or single entity by specifying entity_id:
```yaml
debug: sensor.owl_energy_signal_strength
```

![image](https://github.com/maxwroc/battery-state-card/assets/8268674/04a2b1c8-662a-4067-9231-1d8314914ed3)

Note: "Copy to clipboard" is available only if you access your HA via https.

After clicking on show/hide you will see the entity data which is available for the card to process.

<details>
<summary>Click to see example output</summary>

```json
{
"entity_id": "sensor.owl_energy_signal_strength",
"state": "-72",
"attributes": {
"state_class": "measurement",
"event": "115a011a32e20100000172000031bbc85d69",
"unit_of_measurement": "dBm",
"assumed_state": true,
"device_class": "signal_strength",
"friendly_name": "Owl energy Signal strength"
},
"context": {
"id": "01HPC8X76DDZ4D3XK5BMH8KKFW",
"parent_id": null,
"user_id": null
},
"last_changed": "2024-02-11T14:24:59.597Z",
"last_updated": "2024-02-11T14:24:59.597Z",
"display": {
"entity_id": "sensor.owl_energy_signal_strength",
"device_id": "91b4ffe9a73db4d1ee9482d0e7d94a84",
"platform": "rfxtrx",
"entity_category": "diagnostic",
"name": "Signal strength"
},
"device": {
"area_id": "outside",
"configuration_url": null,
"config_entries": [
"2c67d4fe27613df1b3de59a1f042dc5c"
],
"connections": [],
"disabled_by": null,
"entry_type": null,
"hw_version": null,
"id": "91b4ffe9a73db4d1ee9482d0e7d94a84",
"identifiers": [
[
"rfxtrx",
"5a",
"1",
"32:e2"
]
],
"manufacturer": null,
"model": "ELEC2, CM119/160",
"name_by_user": "Owl energy",
"name": "ELEC2, CM119/160 32:e2",
"serial_number": null,
"sw_version": null,
"via_device_id": null
},
"area": {
"aliases": [],
"area_id": "outside",
"name": "Outside",
"picture": null
}
}
```
</details>

When you look at the entity data you can for example figure out what you can display using KString e.g. `Area: {area.name}, Device: {device.name_by_user}`

## Development
<details>
<summary>Click to expand</summary>
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "battery-state-card",
"version": "3.1.2",
"version": "3.2.0",
"description": "Battery State card for Home Assistant",
"main": "dist/battery-state-card.js",
"author": "Max Chodorowski",
Expand All @@ -21,7 +21,7 @@
"release": "rollup --environment RELEASE -c",
"watch": "rollup -c --watch",
"test": "jest",
"test+integration": "jest --testPathPattern=test/entity",
"test+integration": "jest --testPathPattern=\"test/(entity|card)\"",
"test+coverage": "jest --coverage",
"test+coverage+unit": "jest --coverage --testPathPattern=test/other",
"test+debug": "SET DEBUG_MODE=1&&jest"
Expand Down
38 changes: 27 additions & 11 deletions src/battery-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,27 @@ import { log, safeGetConfigArrayOfObjects } from "./utils";
import { HomeAssistant } from "custom-card-helpers";
import { BatteryStateEntity } from "./custom-elements/battery-state-entity";
import { Filter } from "./filter";
import { HomeAssistantExt } from "./type-extensions";
import { EntityRegistryDisplayEntry, HomeAssistantExt } from "./type-extensions";

/**
* Properties which should be copied over to individual entities from the card
*/
const entititesGlobalProps: (keyof IBatteryEntityConfig)[] = [ "tap_action", "state_map", "charging_state", "secondary_info", "colors", "bulk_rename", "icon", "round", "unit", "value_override", "non_battery_entity", "default_state_formatting" ];
const entititesGlobalProps: (keyof IBatteryEntityConfig)[] = [
"bulk_rename",
"charging_state",
"colors",
"debug",
"default_state_formatting",
"extend_entity_data",
"icon",
"non_battery_entity",
"round",
"secondary_info",
"state_map",
"tap_action",
"value_override",
"unit",
];

/**
* Class responsible for intializing Battery view models based on given configuration.
Expand Down Expand Up @@ -63,15 +78,15 @@ export class BatteryProvider {
this.processIncludes(hass);
}

this.processExcludes(hass);

const updateComplete = Object.keys(this.batteries).map(id => {
const battery = this.batteries[id];
battery.hass = hass;
return battery.cardUpdated;
});

await Promise.all(updateComplete);

this.processExcludes();
}

/**
Expand Down Expand Up @@ -199,25 +214,26 @@ export class BatteryProvider {

/**
* Removes or hides batteries based on filter.exclude config.
* @param hass Home Assistant instance
*/
private processExcludes(hass: HomeAssistant) {
private processExcludes() {
if (this.exclude == undefined) {
Object.keys(this.batteries).forEach((entityId) => {
const battery = this.batteries[entityId];
battery.isHidden = (<EntityRegistryDisplayEntry>battery.entityData?.display)?.hidden;
});

return;
}

const filters = this.exclude;
const toBeRemoved: string[] = [];



Object.keys(this.batteries).forEach((entityId) => {
const battery = this.batteries[entityId];
let isHidden = false;
for (let filter of filters) {
const entityState = hass.states[entityId];
// we want to show batteries for which entities are missing in HA
if (entityState !== undefined && filter.isValid(entityState, battery.state)) {
if (filter.isValid(battery.entityData, battery.state)) {
if (filter.is_permanent) {
// permanent filters have conditions based on static values so we can safely
// remove such battery to avoid updating them unnecessarily
Expand All @@ -233,7 +249,7 @@ export class BatteryProvider {

// we keep the view model to keep updating it
// it might be shown/not-hidden next time
battery.isHidden = isHidden;
battery.isHidden = isHidden || (<EntityRegistryDisplayEntry>battery.entityData?.display)?.hidden;
});

toBeRemoved.forEach(entityId => delete this.batteries[entityId]);
Expand Down
35 changes: 9 additions & 26 deletions src/custom-elements/battery-state-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import sharedStyles from "./shared.css"
import cardStyles from "./battery-state-card.css"
import { getIdsOfSortedBatteries } from "../sorting";
import { safeGetConfigArrayOfObjects } from "../utils";
import defaultConfig from "../default-config";


/**
Expand Down Expand Up @@ -51,11 +52,11 @@ export class BatteryStateCard extends LovelaceCard<IBatteryCardConfig> {
}

async internalUpdate(configUpdated: boolean, hassUpdated: boolean) {

if (this.batteryProvider == undefined || configUpdated) {
// checking whether we should apply default config
if (Object.keys(this.config).length == 1) {
this.config = getDefaultConfig();
// cloning default config
this.config = { ... defaultConfig };
}

this.batteryProvider = new BatteryProvider(this.config);
Expand Down Expand Up @@ -86,18 +87,22 @@ export class BatteryStateCard extends LovelaceCard<IBatteryCardConfig> {
}
}

render(): TemplateResult<1> {
internalRender(): TemplateResult<1> {
if (this.list.length == 0 && this.groups.length == 0) {
// if there are no entities to show we don't want to render anything
this.style.display = "none";
return html``;
}

this.style.removeProperty("display");

return cardHtml(this);
}

onError(): void {
this.style.removeProperty("display");
}

/**
* Gets the height of your card.
*
Expand All @@ -124,26 +129,4 @@ export class BatteryStateCard extends LovelaceCard<IBatteryCardConfig> {
// +1 to account header
return size + 1;
}
}

const getDefaultConfig = () => <IBatteryStateCardConfig>{
sort: {
by: "state"
},
collapse: 8,
filter: {
include: [{
name: "attributes.device_class",
value: "battery"
}]
},
secondary_info: "{last_changed}",
bulk_rename: [
{ from: " Battery" },
{ from: " level" },
],
colors: {
steps: [ "#ff0000", "#ffff00", "#00ff00" ],
gradient: true,
}
}
2 changes: 1 addition & 1 deletion src/custom-elements/battery-state-card.views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const collapsableWrapper = (model: IBatteryGroup, batteries: IBatteryColl
</div>
<div class="chevron">&lsaquo;</div>
</div>
<div style="max-height: ${Object.keys(batteries).length * 50}px">
<div style="max-height: ${Object.keys(batteries).length * 50}px" class="groupItems">
${model.batteryIds.map(id => batteryWrapper(batteries[id]))}
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/custom-elements/battery-state-entity.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
display: flex;
align-items: center;
}
:host > ha-alert {
flex: 1 0 auto;
}
Loading

0 comments on commit 0b5e24e

Please sign in to comment.