@@ -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
947986getTimeframeForOverride ( 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