Skip to content

Commit

Permalink
corrected missing icon when no extra battery entity, corrected spacin…
Browse files Browse the repository at this point in the history
…g when appliances but no battery or generation
  • Loading branch information
reptilex committed Mar 11, 2021
1 parent db017ea commit 5b8ae98
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 51 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@
/build
storybook-static

*.d.ts
*.d.ts
LICENSE
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"printWidth": 140
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,11 @@ Then there are four 5 icon configuration variables:
grid_icon: 'mdi:transmission-tower';
generation_icon: 'mdi:solar-panel-large';
house_icon: 'mdi:home';
battery_icon: 'mdi:battery';
appliance1_icon: 'mdi:car-sports';
appliance2_icon: 'mdi:car-sports';
```
The battery does not have one because the icon changes with the charge and overwriting it has not been implemented.
If you define an extra entity for the battery bubble with the state of charge then the icon will be dynamically replaced with the value of that entity and will override the icon definition above.
### templates for missing sensors or for negative sensors
Expand Down
21 changes: 17 additions & 4 deletions src/TeslaStyleSolarPowerCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export class TeslaStyleSolarPowerCard extends LitElement {
if (this.config.generation_icon == null)
this.config.generation_icon = 'mdi:solar-panel-large';
if (this.config.house_icon == null) this.config.house_icon = 'mdi:home';
if (this.config.battery_icon == null)
this.config.battery_icon = 'mdi:battery-medium';
if (this.config.appliance1_icon == null)
this.config.appliance1_icon = 'mdi:car-sports';
if (this.config.appliance2_icon == null)
Expand Down Expand Up @@ -165,10 +167,10 @@ export class TeslaStyleSolarPowerCard extends LitElement {
this.solarCardElements.forEach(solarSensor => {
solarSensor.setValueAndUnitOfMeasurement(
this.hass.states[solarSensor.entity].state,
this.config.w_not_kw,
this.config.show_w_not_kw,
this.hass.states[solarSensor.entity].attributes.unit_of_measurement
);
solarSensor.setSpeed(this.config.w_not_kw);
solarSensor.setSpeed(this.config.show_w_not_kw);
});

super.performUpdate();
Expand All @@ -178,12 +180,11 @@ export class TeslaStyleSolarPowerCard extends LitElement {
protected render(): TemplateResult | void {
// TODO Check for stateObj or other necessary things and render a warning if missing
// if (this.config.show_warning) return this._showWarning(localize('common.show_warning'));
// if (this.config.show_error) return this._showError(localize('common.show_error'));
if (this.config.show_error) return this._showError('common.show_error');

this.pxRate = this.clientWidth / 100;
const half = 22 * this.pxRate;
// .label=${`TeslaStyleSolarPowerCard: ${this.config.entity || 'No Entity Defined'}`}

return html`
<ha-card .header=${this.config.name} tabindex="0">
<div id="tesla-style-solar-power-card">
Expand Down Expand Up @@ -401,6 +402,18 @@ export class TeslaStyleSolarPowerCard extends LitElement {
);
}

private getHassState(entityName: string) {
const stateValue = this.hass.states[entityName];
if (stateValue === undefined) {
this._showError(
"Configuration Error: Entity '" +
entityName +
"' not found in HomeAssistant sensors."
);
}
return stateValue;
}

private animateCircles(obj: any) {
requestAnimationFrame(timestamp => {
obj.updateAllCircles(timestamp);
Expand Down
2 changes: 1 addition & 1 deletion src/models/TeslaStyleSolarPowerCardConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface TeslaStyleSolarPowerCardConfig extends LovelaceCardConfig {
show_warning?: boolean;
show_error?: boolean;
test_gui?: boolean;
w_not_kw: boolean;
show_w_not_kw: boolean;
hide_inactive_lines?: boolean;

grid_icon?: string;
Expand Down
20 changes: 12 additions & 8 deletions src/services/HtmlResizeForPowerCard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable prefer-template, import/extensions, no-param-reassign, class-methods-use-this, lit-a11y/click-events-have-key-events */
/* eslint-disable func-names, prefer-template, import/extensions, no-param-reassign, class-methods-use-this, lit-a11y/click-events-have-key-events */
import { SensorElement } from '../models/SensorElement';
import { TeslaStyleSolarPowerCard } from '../TeslaStyleSolarPowerCard';

Expand Down Expand Up @@ -68,7 +68,7 @@ export class HtmlResizeForPowerCard {
.querySelectorAll<HTMLElement>('.acc_text')
.forEach(icontext => {
icontext.style['font-size'] = 3 * pxRate + 'px';
icontext.style['margin-top'] = -1 * pxRate + 'px';
icontext.style['margin-top'] = -0.5 * pxRate + 'px';
});
teslaCardElement
.querySelectorAll<HTMLElement>('.acc_text_extra')
Expand Down Expand Up @@ -248,19 +248,23 @@ export class HtmlResizeForPowerCard {
);

const topElement = <HTMLElement>(
teslaCardElement.querySelector('.acc_top')
teslaCardElement.querySelector('.generation_yield_entity')
);
if (topElement === null && value === 1 && selectorElement !== null) {
changeSelectorStyle('.acc_center', 'padding-top', 21 * pxRate + 'px');
changeSelectorStyle(
'.acc_center_container',
'margin-top',
19 * pxRate + 'px'
);
}
const bottomElement = <HTMLElement>(
teslaCardElement.querySelector('.acc_bottom')
teslaCardElement.querySelector('.battery_consumption_entity')
);
if (bottomElement === null && value === 2 && selectorElement !== null) {
changeSelectorStyle(
'.acc_center',
'padding-bottom',
21 * pxRate + 'px'
'.acc_center_container',
'margin-bottom',
19 * pxRate + 'px'
);
}
});
Expand Down
3 changes: 1 addition & 2 deletions src/services/htmlWriterForPowerCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class HtmlWriterForPowerCard {
<ha-icon class="acc_icon" icon="${icon}"></ha-icon>
<div
class="acc_text"
style="font-size:${3 * this.pxRate + 'px'}; margin-top:${-0.8 *
style="font-size:${3 * this.pxRate + 'px'}; margin-top:${-0.5 *
this.pxRate +
'px'}"
>
Expand Down Expand Up @@ -95,7 +95,6 @@ export class HtmlWriterForPowerCard {
batteryValue: number,
batteryChargeDischargeValue: number
) {
// called as dynamic function in this.writeCardDiv()
let TempSocValue = batteryValue;
if (batteryValue <= 5) TempSocValue = 0;

Expand Down
73 changes: 39 additions & 34 deletions tesla-style-solar-power-card.js

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions test/batteryWithoutExtra.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { expect, assert } from '@open-wc/testing';
import { LovelaceCardConfig } from 'custom-card-helpers';
import { setViewport } from '@web/test-runner-commands';

import { TeslaStyleSolarPowerCard } from '../src/TeslaStyleSolarPowerCard.js';
import '../tesla-style-solar-power-card.js';
import { setCard } from './setters.js';

describe('TeslaStyleSolarPowerCard battery tests', () => {
let card: TeslaStyleSolarPowerCard;
let haCard: HTMLElement | null;
let teslaCard: HTMLElement | null | undefined;
let hass: any;
let config: LovelaceCardConfig;

/** Tests are extended in energy_capable. * */

beforeEach(async () => {
config = {
type: 'custom:tesla-style-solar-power-card',
name: 'Powerhouse',
house_consumption_entity: 'sensor.house_consumption',
battery_consumption_entity: 'sensor.battery_consumption',
battery_to_house_entity: 'sensor.battery_consumption',
};
hass = {
states: {
'sensor.house_consumption': {
attributes: {
unit_of_measurement: 'W',
friendly_name: 'House consumption',
},
entity_id: 'sensor.house_consumption',
state: '1300',
},
'sensor.battery_consumption': {
attributes: {
unit_of_measurement: 'W',
},
entity_id: 'battery_consumption',
state: '1300',
},
'sensor.battery_to_house': {
attributes: {
unit_of_measurement: 'W',
},
entity_id: 'sensor.battery_to_house',
state: '1300',
},
},
};
await setViewport({ width: 1200, height: 1000 });
card = <TeslaStyleSolarPowerCard>await setCard(hass, config);
// let iframe = document.createElement('iframe');
// document.body.appendChild(iframe);
// let div = document.createElement('div');
// document.body.
// console.log("document width " + document.body.clientWidth);
// document.body.appendChild(card);
if (card.shadowRoot === null) assert.fail('No Card Shadowroot');
haCard = card.shadowRoot.querySelector('ha-card');
if (haCard === null || haCard === undefined) assert.fail('No ha-card');
teslaCard = <HTMLElement>(
haCard.querySelector('#tesla-style-solar-power-card')
);
if (teslaCard === null || teslaCard === undefined)
assert.fail('No tesla-style-card');
});

it('has house_consumption_entity, text and icon', async () => {
const houseEntity = teslaCard?.querySelector('.house_consumption_entity');
if (houseEntity === null || houseEntity === undefined)
assert.fail('No house_consumption_entity element found');
expect(houseEntity?.querySelector('.acc_text')?.innerHTML).contains(
'1.3 kW'
);
expect(
houseEntity?.querySelector('.acc_icon')?.getAttribute('icon')?.toString()
).to.equal('mdi:home');
});

it('has battery_consumption_entity, text and icon', async () => {
const batteryEntity = teslaCard?.querySelector(
'.battery_consumption_entity'
);
if (batteryEntity === null || batteryEntity === undefined)
assert.fail('No battery_consumption_entity element found');
expect(batteryEntity?.querySelector('.acc_text')?.innerHTML).contains(
'1.3 kW'
);
expect(
batteryEntity
?.querySelector('.acc_icon')
?.getAttribute('icon')
?.toString()
).to.equal('mdi:battery-medium');
});

it('has battery to house consumption line and circle', async () => {
// await setCardConsumingFromGrid();
const batteryToHouseLine = teslaCard?.querySelector(
'#battery_to_house_entity_line'
);
if (batteryToHouseLine === null || batteryToHouseLine === undefined) {
assert.fail('No battery_to_house_line element found');
}
const batteryToHouseCircle = teslaCard?.querySelector(
'#battery_to_house_entity_circle'
);
if (batteryToHouseCircle === null || batteryToHouseCircle === undefined) {
assert.fail('No batter_to_house_entity_circle element found');
}

if (haCard === null || haCard === undefined) assert.fail('No ha-card');
expect(batteryToHouseLine?.getAttribute('hidden')).to.equal(null);
});

it('has no pv, grid or appliance icons', async () => {
const pvEntity = teslaCard?.querySelector('.pv_consumption_entity');
if (pvEntity !== null)
assert.fail('No pv_consumption_entity element found');

const gridEntity = teslaCard?.querySelector('.grid_consumption_entity');
if (gridEntity !== null)
assert.fail('No battery_consumption_entity element found');

const appliance1Entity = teslaCard?.querySelector(
'.appliance1_consumption_entity'
);
if (appliance1Entity !== null)
assert.fail('No appliance1_consumption_entity element found');

const appliance2Entity = teslaCard?.querySelector(
'.appliance2_consumption_entity'
);
if (appliance2Entity !== null)
assert.fail('No appliance2_consumption_entity element found');
});

it('has battery icon', async () => {
card.requestUpdate();
const batteryEntity = teslaCard?.querySelector(
'.battery_consumption_entity'
);
if (batteryEntity === null || batteryEntity === undefined)
assert.fail('No battery_consumption_entity element found');
expect(
batteryEntity
?.querySelector('.acc_icon')
?.getAttribute('icon')
?.toString()
).to.equal('mdi:battery');
});
});

0 comments on commit 5b8ae98

Please sign in to comment.