Skip to content

Commit d16645f

Browse files
authored
Added error handling for no predbat entity
1 parent 79f1f78 commit d16645f

File tree

1 file changed

+119
-68
lines changed

1 file changed

+119
-68
lines changed

predbat-table-card.js

Lines changed: 119 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,21 @@ class PredbatTableCard extends HTMLElement {
409409
//this.attachShadow({ mode: 'open' });
410410
this.forecast = [];
411411
this.unsubscribe = null;
412+
this._renderErrorMessage = null;
412413
}
414+
415+
renderError(message) {
416+
const errorCard = document.createElement("hui-error-card");
417+
errorCard.setConfig({
418+
type: "error",
419+
error: message,
420+
origConfig: this.config,
421+
});
422+
this.innerHTML = "";
423+
this.appendChild(errorCard);
424+
this.content = null;
425+
this._renderErrorMessage = message;
426+
}
413427

414428
// Whenever the state changes, a new `hass` object is set. Use this to
415429
// update your content.
@@ -429,9 +443,27 @@ class PredbatTableCard extends HTMLElement {
429443
const oldHass = this._hass;
430444
this._hass = hass;
431445

432-
const entityId = this.config.entity;
446+
const entityId = this.config?.entity;
447+
if (!entityId) {
448+
this.renderError("Predbat HTML entity is not set in the card configuration.");
449+
return;
450+
}
451+
const currentEntityState = hass.states?.[entityId];
452+
if (!currentEntityState) {
453+
this.renderError(`Predbat HTML entity "${entityId}" is not available. Hit REFRESH when it is...`);
454+
return;
455+
}
456+
if (currentEntityState.state === "unavailable") {
457+
this.renderError("Predbat HTML entity is not currently available. Hit REFRESH when it is...");
458+
return;
459+
}
460+
const hadError = this._renderErrorMessage !== null;
461+
this._renderErrorMessage = null;
433462
const switchEntityId = this.config.car_charge_switch; // optional
434-
const prefix = this.config.entity.match(/^[^.]+/)[0];
463+
let prefix = this.config.entity.match(/^[^.]+/)[0];
464+
if(prefix === "sensor")
465+
prefix = "predbat";
466+
435467
const predbatActiveEntityId = `switch.${prefix}_active`;
436468

437469
if(oldHass === undefined){
@@ -454,8 +486,8 @@ class PredbatTableCard extends HTMLElement {
454486
this._lastOnText = null;
455487
this.processAndRender(hass);
456488
} else {
457-
const oldEntityUpdateTime = oldHass.states[entityId].last_updated;
458-
const newEntityUpdateTime = hass.states[entityId].last_updated;
489+
const oldEntityUpdateTime = oldHass.states?.[entityId]?.last_updated;
490+
const newEntityUpdateTime = hass.states?.[entityId]?.last_updated;
459491
let carSwitchChanged = false;
460492
let activeSwitchChanged = false;
461493
let manualForceChanged = false;
@@ -492,7 +524,7 @@ class PredbatTableCard extends HTMLElement {
492524
}
493525
}
494526

495-
if (oldEntityUpdateTime !== newEntityUpdateTime || carSwitchChanged || activeSwitchChanged || manualForceChanged) {
527+
if (hadError || oldEntityUpdateTime !== newEntityUpdateTime || carSwitchChanged || activeSwitchChanged || manualForceChanged) {
496528
this.processAndRender(hass);
497529
}
498530
}
@@ -527,9 +559,11 @@ class PredbatTableCard extends HTMLElement {
527559
}
528560
}
529561

530-
async processAndRender(hass){
562+
async processAndRender(hass){
531563

532-
const prefix = this.config.entity.match(/^[^.]+/)[0];
564+
let prefix = this.config.entity.match(/^[^.]+/)[0];
565+
if(prefix === "sensor")
566+
prefix = "predbat";
533567
const predbatActiveEntityId = `switch.${prefix}_active`;
534568

535569
if(this._lastOnText === null){
@@ -550,11 +584,16 @@ class PredbatTableCard extends HTMLElement {
550584

551585
const entityId = this.config.entity;
552586

553-
const state = hass.states[entityId];
554-
const stateStr = state ? state.state : "unavailable";
587+
const state = hass.states?.[entityId];
588+
if (!state) {
589+
this.renderError(`Predbat HTML entity "${entityId}" is not currently available. REFRESH when it is...`);
590+
return;
591+
}
592+
const stateStr = state.state;
555593

556594
if (stateStr === "unavailable") {
557-
throw new Error("Predbat HTML entity is not currently available. Hit REFRESH when it is...");
595+
this.renderError("Predbat HTML entity is not currently available. Hit REFRESH when it is...");
596+
return;
558597
}
559598

560599
let columnsToReturn = this.config.columns;
@@ -946,7 +985,9 @@ isVersionGreater(a, b) {
946985

947986
getTimeframeForOverride(timeString) {
948987

949-
const prefix = this.config.entity.match(/^[^.]+/)[0];
988+
let prefix = this.config.entity.match(/^[^.]+/)[0];
989+
if(prefix === "sensor")
990+
prefix = "predbat";
950991

951992
const predBatVersion =
952993
this._hass.states[`update.${prefix}_version`].attributes.installed_version;
@@ -981,7 +1022,9 @@ getTimeframeForOverride(timeString) {
9811022

9821023
createButtonForOverrides(entityObject, timeForSelectOverride, iconSize, textColor, hideLabel, isAllowed, fromPopup = false) {
9831024

984-
const prefix = this.config.entity.match(/^[^.]+/)[0];
1025+
let prefix = this.config.entity.match(/^[^.]+/)[0];
1026+
if(prefix === "sensor")
1027+
prefix = "predbat";
9851028
const key = entityObject.entityName.replace(`select.${prefix}_manual_`, '');
9861029

9871030
const iconOpacityOff = 1.00;
@@ -1185,7 +1228,9 @@ getTimeframeForOverride(timeString) {
11851228

11861229
// 100✎ →
11871230

1188-
const prefix = this.config.entity.match(/^[^.]+/)[0];
1231+
let prefix = this.config.entity.match(/^[^.]+/)[0];
1232+
if(prefix === "sensor")
1233+
prefix = "predbat";
11891234
const versionEntity = this._hass.states?.[`update.${prefix}_version`];
11901235
const installedVersionRaw = versionEntity?.attributes?.installed_version || '';
11911236
const installedVersion = installedVersionRaw.startsWith('v')
@@ -1295,7 +1340,9 @@ getTimeframeForOverride(timeString) {
12951340

12961341
createPopUpForSoCOverride(entityObject, timeForSelectOverride){
12971342

1298-
const prefix = this.config.entity.match(/^[^.]+/)[0];
1343+
let prefix = this.config.entity.match(/^[^.]+/)[0];
1344+
if(prefix === "sensor")
1345+
prefix = "predbat";
12991346
const inputEntity = `input_number.${prefix}_manual_soc_value`;
13001347
const entityState = this._hass.states?.[inputEntity];
13011348
const defaultSocValue = entityState?.state ?? '';
@@ -1634,7 +1681,9 @@ getTimeframeForOverride(timeString) {
16341681

16351682
let newCell = document.createElement('td');
16361683
let newContent = (typeof theItem?.value === 'string') ? theItem.value.trim() : theItem?.value ?? '';
1637-
const prefix = this.config.entity.match(/^[^.]+/)[0];
1684+
let prefix = this.config.entity.match(/^[^.]+/)[0];
1685+
if(prefix === "sensor")
1686+
prefix = "predbat";
16381687

16391688
let debugValue, rawValue;
16401689

@@ -2943,64 +2992,66 @@ convertTimeStampToFriendly(timestamp){
29432992
getArrayDataFromHTML(html, hassDarkMode) {
29442993

29452994
// Define column headers and corresponding classes
2946-
const headerClassesArray = [
2947-
'time-column',
2948-
'import-column',
2949-
'export-column',
2950-
'state-column',
2951-
'limit-column',
2952-
'pv-column',
2953-
'load-column',
2954-
'soc-column',
2955-
'cost-column',
2956-
'total-column'
2957-
];
2958-
2995+
const headerClassesArray = [
2996+
'time-column',
2997+
'import-column',
2998+
'export-column',
2999+
'state-column',
3000+
'limit-column',
3001+
'pv-column',
3002+
'load-column',
3003+
'soc-column',
3004+
'cost-column',
3005+
'total-column'
3006+
];
3007+
29593008
let totalCostCalculated = 0;
3009+
3010+
// Create a dummy element to manipulate the HTML
3011+
const dummyElement = document.createElement('div');
3012+
dummyElement.innerHTML = html;
29603013

2961-
// Create a dummy element to manipulate the HTML
2962-
const dummyElement = document.createElement('div');
2963-
dummyElement.innerHTML = html;
2964-
2965-
// Find all <tr> elements in the table body
2966-
const trElements = dummyElement.querySelectorAll('tbody tr');
2967-
2968-
// Loop through each <tr> element
2969-
2970-
let rowCount = 0;
2971-
2972-
const newDataObject = [];
2973-
2974-
let currentExportRate;
2975-
let currentExportColor;
2976-
2977-
let firstRowData = 0;
3014+
// Find all <tr> elements in the table body
3015+
const trElements = dummyElement.querySelectorAll('tbody tr');
29783016

2979-
/*
2980-
const str = "1.79 (0.75)";
3017+
// Loop through each <tr> element
3018+
3019+
let rowCount = 0;
3020+
3021+
const newDataObject = [];
3022+
3023+
let currentExportRate;
3024+
let currentExportColor;
3025+
3026+
let firstRowData = 0;
3027+
3028+
/*
3029+
const str = "1.79 (0.75)";
29813030
2982-
// Step 1: Use a regular expression to find all float numbers
2983-
const floatRegex = /-?\d+(\.\d+)?/g; // This regex matches positive and negative floats
2984-
const matches = str.match(floatRegex); // Get an array of matches
2985-
2986-
// Step 2: Convert the matches to floating-point numbers
2987-
const floats = matches.map(match => parseFloat(match));
2988-
2989-
// Step 3: Loop through each float and do something with it
2990-
floats.forEach(float => {
2991-
console.log(float); // Here you can replace this line with whatever you want to do with each float
2992-
});*/
3031+
// Step 1: Use a regular expression to find all float numbers
3032+
const floatRegex = /-?\d+(\.\d+)?/g; // This regex matches positive and negative floats
3033+
const matches = str.match(floatRegex); // Get an array of matches
3034+
3035+
// Step 2: Convert the matches to floating-point numbers
3036+
const floats = matches.map(match => parseFloat(match));
3037+
3038+
// Step 3: Loop through each float and do something with it
3039+
floats.forEach(float => {
3040+
console.log(float); // Here you can replace this line with whatever you want to do with each float
3041+
});*/
29933042

2994-
trElements.forEach((trElement, index) => {
2995-
if(firstRowData === 0){
2996-
const numberOfChildren = trElement.children.length;
2997-
2998-
//detect if row data is actual table data not metadata. If children <td> is greater than 2
2999-
if(numberOfChildren > 2){
3000-
firstRowData = index;
3001-
}
3043+
trElements.forEach((trElement, index) => {
3044+
if(firstRowData === 0){
3045+
const numberOfChildren = trElement.children.length;
3046+
3047+
//detect if row data is actual table data not metadata. If children <td> is greater than 2
3048+
if(numberOfChildren > 2){
3049+
firstRowData = index;
30023050
}
3003-
});
3051+
}
3052+
});
3053+
3054+
console.log(firstRowData);
30043055

30053056
let isCostReset = false;
30063057
let currentCost = 0;
@@ -3059,7 +3110,7 @@ convertTimeStampToFriendly(timestamp){
30593110

30603111
// Loop through each <td> element inside the current <tr>
30613112
tdElements.forEach((tdElement, tdIndex) => {
3062-
3113+
30633114
const userResetFlag = this.config.reset_day_totals;
30643115
if(tdIndex === 0 && tdElement.innerHTML.includes("00:00") && userResetFlag)
30653116
isCostReset = true;

0 commit comments

Comments
 (0)