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

feat: add secondary info to individual devices #30

Merged
merged 1 commit into from
Mar 27, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

Display current power, gas, and water usage in a display that matches the the official Energy Distribution card included with [Home Assistant](https://home-assistant.io/) as much as possible.




## Install

### HACS (recommended)
Expand Down Expand Up @@ -69,6 +72,7 @@ Else, if you prefer the graphical editor, use the menu to add the resource:

> ⚠️ This card offers a **LOT** of configuration options. Don't worry, if you want your card's appearance to match the oficial Energy Flow Card, you will only need to setup the entities. The rest of the options only enable further customization. If this is your goal, please go to [Minimal Configuration](#minimal-configuration)


### Options

#### Card options
Expand All @@ -79,7 +83,7 @@ Else, if you prefer the graphical editor, use the menu to add the resource:
| entities | `object` | **required** | One or more sensor entities, see [entities object](#entities-object) for additional entity options. |
| title | `string` | | Shows a title at the top of the card. |
| dashboard_link | `string` | | Shows a link to an Energy Dashboard. Should be a url path to location of your choice. If you wanted to link to the built-in dashboard you would enter `/energy` for example. |
| inverted_entities | `string` | | Comma seperated list of entities that should be inverted (negative for consumption and positive for production). |
| inverted_entities | `string` | | Comma seperated list of entities that should be inverted (negative for consumption and positive for production). See [example usage](#inverted-entities-example). |
| kw_decimals | `number` | 1 | Number of decimals rounded to when kilowatts are displayed. |
| w_decimals | `number` | 1 | Number of decimals rounded to when watts are displayed. |
| min_flow_rate | `number` | .75 | Represents the fastest amount of time in seconds for a flow dot to travel from one end to the other, see [flow formula](#flow-formula). |
Expand Down Expand Up @@ -146,6 +150,7 @@ At least one of _grid_, _battery_, or _solar_ is required. All entites (except _
| display_zero | `boolean` | `true` | If set to `true`, the device will be displayed even if the entity state is `0` or not a number (eg: `unavailable`). Otherwise, the non-fossil section will be hidden. |
| unit_of_measurement | `string` | `W`or `kW` (dynamic) | Sets the unit of measurement to show in the corresponding circle |
| inverted_animation |`boolean` | `false` | If set to true, the small dots will flow in the opposite direction. |
| secondary_info | `object` | `undefined` | Check [Secondary Info Object](#secondary-info-configuration)

#### Home Configuration

Expand Down Expand Up @@ -184,6 +189,17 @@ Can be use with either Grid or Battery configuration. The same `unit_of_measurem
| consumption | `string` | Entity ID providing a state value for consumption, this is required if using a split grid object. |
| production | `string` | Entity ID providing a state value for production |

#### Secondary Info Configuration

This Feature allows you to configure an additional small text for each Individual Device. Here you can put , for example, the state of charge of an electric car.

| Name | Type | Description |
| ----------- | -------- | ------------------------------------------------------------------------------------------------- |
| entity| `string` required | Entity ID providing a state value that is going to be displayed. |
| unit_of_measurement | `string` | A string to be used as the unit of measurement. (Important: don't forget surrounding string with quotes) |
| icon | `string` | An icon path to be displayed next to the state of the individual device. This is optional, meaning if you don't use this, no icon will be displayed. |
| display_zero | `boolean` | Default is `false`. If set to `true` info will still be displayed if state of the entity is `0` or `unavailable`.

### Minimal Configuration

> Don't forget to change the entity ids
Expand Down
123 changes: 116 additions & 7 deletions src/power-flow-card-plus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,21 @@ export class PowerFlowCard extends LitElement {
entities.individual2?.display_zero === true) ||
(this.getEntityStateWatts(entities.individual2?.entity) > 0 &&
this.entityAvailable(entities.individual2?.entity!));
const hasIndividual2Secondary =
entities.individual2?.secondary_info?.entity !== undefined &&
(this.getEntityState(entities.individual2?.secondary_info?.entity) > 0 ||
entities.individual2.secondary_info.display_zero === true);

const hasIndividual1 =
(entities.individual1 !== undefined &&
entities.individual1?.display_zero === true) ||
(this.getEntityStateWatts(entities.individual1?.entity) > 0 &&
this.entityAvailable(entities.individual1?.entity!));
const hasIndividual1Secondary =
entities.individual1?.secondary_info?.entity !== undefined &&
(this.getEntityState(entities.individual1?.secondary_info?.entity) > 0 ||
entities.individual1.secondary_info.display_zero === true);

const hasSolarProduction = entities.solar !== undefined;
const hasReturnToGrid =
hasGrid &&
Expand Down Expand Up @@ -254,6 +263,7 @@ export class PowerFlowCard extends LitElement {
);

let individual1Usage: number | null = null;
let individual1SecondaryUsage: number | null = null;
const individual1Name: string =
this._config.entities.individual1?.name || "Car";
const individual1Icon: undefined | string =
Expand All @@ -278,8 +288,25 @@ export class PowerFlowCard extends LitElement {
individual1Usage = Math.abs(Math.min(individual1State, 0));
else individual1Usage = Math.max(individual1State, 0);
}
if (hasIndividual1Secondary) {
const individual1SecondaryEntity =
this.hass.states[
this._config.entities.individual1?.secondary_info?.entity!
];
const individual1SecondaryState = Number(
individual1SecondaryEntity.state
);
if (this.entityInverted("individual1Secondary")) {
individual1SecondaryUsage = Math.abs(
Math.min(individual1SecondaryState, 0)
);
} else {
individual1SecondaryUsage = Math.max(individual1SecondaryState, 0);
}
}

let individual2Usage: number | null = null;
let individual2SecondaryUsage: number | null = null;
const individual2Name: string =
this._config.entities.individual2?.name || "Motorcycle";
const individual2Icon: undefined | string =
Expand All @@ -304,6 +331,22 @@ export class PowerFlowCard extends LitElement {
individual2Usage = Math.abs(Math.min(individual2State, 0));
else individual2Usage = Math.max(individual2State, 0);
}
if (hasIndividual2Secondary) {
const individual2SecondaryEntity =
this.hass.states[
this._config.entities.individual2?.secondary_info?.entity!
];
const individual2SecondaryState = Number(
individual2SecondaryEntity.state
);
if (this.entityInverted("individual2Secondary")) {
individual2SecondaryUsage = Math.abs(
Math.min(individual2SecondaryState, 0)
);
} else {
individual2SecondaryUsage = Math.max(individual2SecondaryState, 0);
}
}

let totalSolarProduction: number = 0;
if (this._config.entities.solar?.color !== undefined)
Expand Down Expand Up @@ -686,17 +729,35 @@ export class PowerFlowCard extends LitElement {
}
}}
>
${hasIndividual2Secondary
? html`
<span class="secondary-info individual2">
${entities.individual2?.secondary_info?.icon
? html`<ha-icon
class="secondary-info small"
.icon=${entities.individual2
?.secondary_info?.icon}
></ha-icon>`
: ""}
${this.displayValue(
individual2SecondaryUsage,
entities.individual2?.secondary_info
?.unit_of_measurement
)}
</span>
`
: ""}
<ha-icon
id="individual2-icon"
.icon=${individual2Icon}
style=${hasIndividual2Secondary
? "padding-top: 2px;"
: "padding-top: 0px;"}
></ha-icon>
${this._config.entities.individual2?.unit_of_measurement
? this.displayValue(
individual2Usage,
this._config.entities.individual2
?.unit_of_measurement
)
: this.displayValue(individual2Usage)}
${this.displayValue(
individual2Usage,
this._config.entities.individual2?.unit_of_measurement
)}
</div>
<svg width="80" height="30">
<path d="M40 -10 v50" id="individual2" />
Expand Down Expand Up @@ -742,9 +803,30 @@ export class PowerFlowCard extends LitElement {
}
}}
>
${hasIndividual1Secondary
? html`
<span class="secondary-info individual1">
${entities.individual1?.secondary_info?.icon
? html`<ha-icon
class="secondary-info small"
.icon=${entities.individual1
?.secondary_info?.icon}
></ha-icon>`
: ""}
${this.displayValue(
individual1SecondaryUsage,
entities.individual1?.secondary_info
?.unit_of_measurement
)}
</span>
`
: ""}
<ha-icon
id="individual1-icon"
.icon=${individual1Icon}
style=${hasIndividual1Secondary
? "padding-top: 2px;"
: "padding-top: 0px;"}
></ha-icon>
${this._config.entities.individual1?.unit_of_measurement
? this.displayValue(
Expand Down Expand Up @@ -1173,9 +1255,30 @@ export class PowerFlowCard extends LitElement {
}
}}
>
${hasIndividual1Secondary
? html`
<span class="secondary-info individual1">
${entities.individual1?.secondary_info?.icon
? html`<ha-icon
class="secondary-info small"
.icon=${entities.individual1
?.secondary_info?.icon}
></ha-icon>`
: ""}
${this.displayValue(
individual1SecondaryUsage,
entities.individual1?.secondary_info
?.unit_of_measurement
)}
</span>
`
: ""}
<ha-icon
id="individual1-icon"
.icon=${individual1Icon}
style=${hasIndividual1Secondary
? "padding-top: 2px;"
: "padding-top: 0px;"}
></ha-icon>
${this._config.entities.individual1?.unit_of_measurement
? this.displayValue(
Expand Down Expand Up @@ -1592,6 +1695,12 @@ export class PowerFlowCard extends LitElement {
top: 0;
left: 0;
}

span.secondary-info {
color: var(--secondary-text-color);
font-size: 10px;
}

.individual2 path,
.individual2 circle {
stroke: var(--individualtwo-color);
Expand Down
10 changes: 9 additions & 1 deletion src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ export type IndividualDeviceType = {
display_zero?: boolean;
inverted_animation?: boolean;
unit_of_measurement?: string;
secondary_info?: {
entity: string;
unit_of_measurement?: string;
icon?: string;
display_zero?: boolean;
};
};

export type EntityType =
| "battery"
| "grid"
| "solar"
| "individual1"
| "individual2";
| "individual1Secondary"
| "individual2"
| "individual2Secondary";