@@ -84,7 +84,27 @@ class CompactPowerCard extends CompactPowerCardBase {
8484 {
8585 name : "enable_device_power_lines" ,
8686 selector : { boolean : { } } ,
87- } ,
87+ } ,
88+ {
89+ name : "show_remaining_device" ,
90+ selector : { boolean : { } } ,
91+ } ,
92+ {
93+ name : "remaining_device_name" ,
94+ selector : { text : { } } ,
95+ } ,
96+ {
97+ name : "remaining_device_icon" ,
98+ selector : { icon : { } } ,
99+ } ,
100+ {
101+ name : "remaining_device_color" ,
102+ selector : { text : { } } ,
103+ } ,
104+ {
105+ name : "remaining_device_threshold" ,
106+ selector : { number : { step : 1 } } ,
107+ } ,
88108 {
89109 name : "disable_home_gradient" ,
90110 selector : { boolean : { } } ,
@@ -3127,7 +3147,7 @@ class CompactPowerCard extends CompactPowerCardBase {
31273147 ? this . _config ?. entities ?. battery_labels || this . _config ?. entities ?. battery ?. labels
31283148 : batteryCfg ?. labels ;
31293149 const batteryLabels = this . _normalizeLabels ( batteryLabelsSource , null ) ;
3130- const { sources : normalizedSources } = this . _getSourcesConfig ( ) ;
3150+ let { sources : normalizedSources } = this . _getSourcesConfig ( ) ;
31313151 const enableDevicePowerLines = this . _useDevicePowerLines ( ) ;
31323152 const allowGlow = this . _allowGlowEffects ( ) ;
31333153 const homeGlowOpacity = allowGlow ? 0.3 : 0 ;
@@ -3369,6 +3389,38 @@ class CompactPowerCard extends CompactPowerCardBase {
33693389 pvUnitRaw || gridUnitRaw || batteryUnitRaw || homeUnitOverride || "W" ;
33703390 const homeUnit = "W" ;
33713391 const homeNumericW = this . _toWatts ( homeNumeric , inferredHomeUnit ) ;
3392+
3393+ // Optional virtual device: all household usage not covered by configured devices.
3394+ if ( this . _coerceBoolean ( this . _config ?. show_remaining_device , false ) ) {
3395+ const knownDeviceWatts = normalizedSources . reduce ( ( sum , src ) => {
3396+ const entity = src ?. entity || null ;
3397+ if ( ! this . _isPowerDevice ( entity ) ) return sum ;
3398+ const attribute = src ?. attribute || null ;
3399+ const unit = this . hass ?. states ?. [ entity ] ?. attributes ?. unit_of_measurement || "" ;
3400+ const meta = this . _getPowerMeta ( entity , unit , attribute ) ;
3401+ const watts = Number . isFinite ( meta ?. watts ) ? Math . max ( meta . watts , 0 ) : 0 ;
3402+ return sum + watts ;
3403+ } , 0 ) ;
3404+
3405+ const remainingWatts = Math . max (
3406+ ( Number . isFinite ( homeNumericW ) ? homeNumericW : 0 ) - knownDeviceWatts ,
3407+ 0
3408+ ) ;
3409+
3410+ normalizedSources = [
3411+ ...normalizedSources ,
3412+ {
3413+ entity : "__cpc_remaining_devices__" ,
3414+ virtual : true ,
3415+ virtual_watts : remainingWatts ,
3416+ name : this . _config ?. remaining_device_name || "Overige" ,
3417+ icon : this . _config ?. remaining_device_icon || "mdi:devices" ,
3418+ color : this . _config ?. remaining_device_color || "#9e9e9e" ,
3419+ threshold : this . _config ?. remaining_device_threshold ?? 5 ,
3420+ subtract_from_home : false ,
3421+ } ,
3422+ ] ;
3423+ }
33723424 const homeEffectiveW = this . _homeEffective || 0 ;
33733425 const homeEffectiveRender = homeEffectiveW ;
33743426 const homeThresholdDisplay = this . _toWatts ( this . _parseThreshold ( homeCfg . threshold ) , "W" , true ) ;
@@ -3534,13 +3586,22 @@ class CompactPowerCard extends CompactPowerCardBase {
35343586 const name = src . name || null ;
35353587 const nameEntity = name && this . hass ?. states ?. [ name ] ? name : null ;
35363588 const displayName = nameEntity ? this . _formatEntityStateWithUnit ( nameEntity ) : name ;
3537- const icon = src . icon || this . _getEntityIcon ( entity , "mdi:power-plug" ) ;
3538- const isPowerDevice = this . _isPowerDevice ( entity ) ;
3539- const st = entity ? this . hass ?. states ?. [ entity ] : null ;
3540- const raw = attribute ? st ?. attributes ?. [ attribute ] : st ?. state ;
3541- const isUnavailable = this . _isUnavailableState ( raw ) ;
3542- const numeric = isUnavailable ? 0 : this . _getNumericMaybe ( entity , attribute ) ;
3543- const unit = st ?. attributes ?. unit_of_measurement || "" ;
3589+ const isVirtual = this . _coerceBoolean ( src . virtual , false ) ;
3590+ const icon = src . icon || ( isVirtual ? "mdi:devices" : this . _getEntityIcon ( entity , "mdi:power-plug" ) ) ;
3591+ const isPowerDevice = isVirtual || this . _isPowerDevice ( entity ) ;
3592+ const st = ! isVirtual && entity ? this . hass ?. states ?. [ entity ] : null ;
3593+ const raw = isVirtual
3594+ ? src . virtual_watts
3595+ : attribute
3596+ ? st ?. attributes ?. [ attribute ]
3597+ : st ?. state ;
3598+ const isUnavailable = isVirtual ? false : this . _isUnavailableState ( raw ) ;
3599+ const numeric = isVirtual
3600+ ? Number ( src . virtual_watts ) || 0
3601+ : isUnavailable
3602+ ? 0
3603+ : this . _getNumericMaybe ( entity , attribute ) ;
3604+ const unit = isVirtual ? "W" : st ?. attributes ?. unit_of_measurement || "" ;
35443605 const decimals = this . _getDecimalPlaces ( src ) ;
35453606 const numericW = isPowerDevice
35463607 ? isUnavailable
@@ -3581,6 +3642,7 @@ class CompactPowerCard extends CompactPowerCardBase {
35813642 hidden,
35823643 numeric : hasPowerNumeric ? numericW : numeric ?? 0 ,
35833644 isPowerDevice,
3645+ isVirtual,
35843646 threshold,
35853647 forceHideUnderThreshold,
35863648 } ;
@@ -3589,7 +3651,12 @@ class CompactPowerCard extends CompactPowerCardBase {
35893651 const visibleSources = deviceSources . filter (
35903652 ( src ) => ! ( src . forceHideUnderThreshold && src . hidden )
35913653 ) ;
3592- const maxDevices = Math . min ( visibleSources . length , maxItemsByColumns ) ;
3654+ // Show all configured devices, including the virtual remaining-usage device.
3655+ // The previous column-based cap could silently remove the last item (usually "Overige").
3656+ const configuredMaxDevices = this . _parseNumberStrict ( this . _config ?. max_device_items ) ;
3657+ const maxDevices = Number . isFinite ( configuredMaxDevices )
3658+ ? Math . max ( 1 , Math . min ( visibleSources . length , Math . floor ( configuredMaxDevices ) ) )
3659+ : visibleSources . length ;
35933660 const deviceVisible = visibleSources . slice ( 0 , maxDevices ) ;
35943661
35953662 if ( maxDevices > 0 ) {
@@ -3628,7 +3695,7 @@ class CompactPowerCard extends CompactPowerCardBase {
36283695
36293696 const sources = deviceVisible . map ( ( src , idx ) => {
36303697 const pos = sourcePositions [ idx ] || { x : homeX , y : homeRowYBase } ;
3631- const key = src . entity || `idx-${ src . sourceIndex } ` ;
3698+ const key = src . isVirtual ? "__cpc_remaining_devices__" : src . entity || `idx-${ src . sourceIndex } ` ;
36323699 let active = false ;
36333700 let flicker = false ;
36343701 let flickerUntil = 0 ;
@@ -4270,6 +4337,8 @@ class CompactPowerCard extends CompactPowerCardBase {
42704337 @click =${ ( ) => {
42714338 if ( src . switchEntity ) {
42724339 this . _toggleDeviceSwitch ( src ) ;
4340+ } else if ( src . isVirtual ) {
4341+ this . _openMoreInfo ( homeCfg . entity || null ) ;
42734342 } else {
42744343 this . _openMoreInfo ( src . entity || null ) ;
42754344 }
@@ -4286,6 +4355,8 @@ class CompactPowerCard extends CompactPowerCardBase {
42864355 @click =${ ( ) => {
42874356 if ( src . switchEntity ) {
42884357 this . _toggleDeviceSwitch ( src ) ;
4358+ } else if ( src . isVirtual ) {
4359+ this . _openMoreInfo ( homeCfg . entity || null ) ;
42894360 } else {
42904361 this . _openMoreInfo ( src . entity || null ) ;
42914362 }
0 commit comments