homebridge-viessmann-vicare 2.0.63 β†’ 2.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1033,11 +1033,25 @@ For issues and questions:
1033
1033
 
1034
1034
  ## πŸ“ˆ Changelog
1035
1035
 
1036
+ ### [2.0.65] - 2026-03-19
1037
+ - fix: HTTP 400 (gateway offline / boiler off) no longer triggers aggressive retry and error logs
1038
+ - fix: api-client.ts β€” 400 responses skip retry loop, logged at debug level only
1039
+ - fix: platform.ts β€” 400 during update cycle logged as debug "⏸️ gateway offline", not error
1040
+ - fix: platform.ts β€” 400 during initial setup logged as debug, not error
1041
+
1042
+ ### [2.0.64] - 2026-03-18
1043
+ - fix: CSV cleanup β€” 4 rows with invalid program='heating' (from first run on 10/03) corrected to empty string
1044
+ - fix: version bump (v2.0.63 was already published)
1045
+
1036
1046
  ### [2.0.63] - 2026-03-18
1037
1047
  - fix: ReferenceError T() in browser β€” chart labels now evaluated at build time via \${} wrapper
1038
1048
  - fix: tooltip callbacks use pre-injected _tooltip object with _tt() helper
1039
1049
  - fix: thermal efficiency note still hardcoded in Energy Summary section
1040
1050
 
1051
+ ### [2.0.63] - 2026-03-18
1052
+ - fix: SyntaxError "Unexpected identifier" in browser β€” chart labels T() values were emitted without quotes (label:Temp. ambiente (Β°C) instead of label:"Temp. ambiente (Β°C)")
1053
+ - fix: all 40 chart label and axis T() expressions now correctly wrapped in quotes in generated HTML
1054
+
1041
1055
  ### [2.0.62] - 2026-03-18
1042
1056
  - fix: report server UI β€” Language selector now always visible as dedicated card (was hidden inside Advanced panel)
1043
1057
  - fix: Advanced panel β€” curve slope and shift now have separate labeled fields
package/SETUP-GUIDE.md CHANGED
@@ -1,4 +1,4 @@
1
- # Complete Setup Guide - v2.0.63
1
+ # Complete Setup Guide - v2.0.65
2
2
 
3
3
  ## Overview
4
4
 
@@ -1228,10 +1228,19 @@ sudo systemctl restart homebridge
1228
1228
 
1229
1229
  ## Changelog
1230
1230
 
1231
+ ### v2.0.65 (2026-03-19)
1232
+ - fix: HTTP 400 (boiler off/gateway offline) silenced β€” no more log spam when secondary installation is off
1233
+
1234
+ ### v2.0.64 (2026-03-18)
1235
+ - fix: version bump
1236
+
1231
1237
  ### v2.0.63 (2026-03-18)
1232
1238
  - fix: ReferenceError T() in browser JS β€” grafici non visibili con --lang it
1233
1239
  - fix: thermal efficiency note tradotta
1234
1240
 
1241
+ ### v2.0.63 (2026-03-18)
1242
+ - fix: SyntaxError in browser β€” chart labels missing quotes around translated strings
1243
+
1235
1244
  ### v2.0.62 (2026-03-18)
1236
1245
  - fix: report server β€” Language card always visible, Advanced panel fields cleaned up
1237
1246
 
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAc,EAAiB,aAAa,EAA0C,MAAM,OAAO,CAAC;AACpG,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAoB,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAY,WAAW,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAoB,UAAU,EAAE,MAAM,sBAAsB,CAAC;AASpE,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,yBAAyB,EAAE,OAAO,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,qBAAa,SAAS;IAQlB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAT9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgD;IACxE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;gBAGd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,WAAW;IA+B3C,OAAO,CAAC,qBAAqB;IAgB7B,OAAO,CAAC,iBAAiB;IAgFzB,OAAO,CAAC,qBAAqB;IAchB,WAAW,CAAC,CAAC,EACxB,SAAS,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAC1C,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,GAAE,MAAU,GACrB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAmF5B,OAAO,CAAC,KAAK;IAKA,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAQ5D,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAQzE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAQxE,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IASrE,kBAAkB;;;;;;;;;IAIlB,aAAa,IAAI,UAAU;IAI3B,iBAAiB,IAAI,MAAM;IAI3B,kBAAkB,IAAI,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU;IAIzE,uBAAuB;;;;;;;IAIvB,qBAAqB;IAIrB,qBAAqB;;;;;;;;IAIrB,eAAe,IAAI,IAAI;IAIvB,aAAa;IAIb,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM;IAK3B,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC;IAK9C,OAAO,IAAI,IAAI;CAIvB"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAc,EAAiB,aAAa,EAA0C,MAAM,OAAO,CAAC;AACpG,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAoB,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAY,WAAW,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAoB,UAAU,EAAE,MAAM,sBAAsB,CAAC;AASpE,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,yBAAyB,EAAE,OAAO,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,qBAAa,SAAS;IAQlB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAT9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgD;IACxE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;gBAGd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,WAAW;IA+B3C,OAAO,CAAC,qBAAqB;IAgB7B,OAAO,CAAC,iBAAiB;IAgFzB,OAAO,CAAC,qBAAqB;IAchB,WAAW,CAAC,CAAC,EACxB,SAAS,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAC1C,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,GAAE,MAAU,GACrB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IA4F5B,OAAO,CAAC,KAAK;IAKA,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAQ5D,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAQzE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAQxE,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IASrE,kBAAkB;;;;;;;;;IAIlB,aAAa,IAAI,UAAU;IAI3B,iBAAiB,IAAI,MAAM;IAI3B,kBAAkB,IAAI,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU;IAIzE,uBAAuB;;;;;;;IAIvB,qBAAqB;IAIrB,qBAAqB;;;;;;;;IAIrB,eAAe,IAAI,IAAI;IAIvB,aAAa;IAIb,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM;IAK3B,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC;IAK9C,OAAO,IAAI,IAAI;CAIvB"}
@@ -203,9 +203,17 @@ class APIClient {
203
203
  }
204
204
  }
205
205
  else {
206
+ // HTTP 400 = gateway offline / boiler off β€” not a transient error, no aggressive retry
207
+ if (axiosError.response?.status === 400) {
208
+ if (retryCount === 0) {
209
+ // Log once at debug level β€” this is expected when boiler is off
210
+ this.log.debug(`⏸️ '${operationName}' β€” gateway offline or boiler off (HTTP 400), skipping retry`);
211
+ }
212
+ throw error;
213
+ }
206
214
  // For other errors, retry with exponential backoff
207
215
  if (retryCount < this.config.maxRetries) {
208
- const delay = Math.min(this.config.baseDelay * Math.pow(2, retryCount), 30000); // Max 30 seconds for non-rate-limit retries
216
+ const delay = Math.min(this.config.baseDelay * Math.pow(2, retryCount), 30000);
209
217
  this.log.warn(`⚠️ Error in '${operationName}': ${axiosError.message}. Retrying in ${delay / 1000} seconds...`);
210
218
  await this.sleep(delay);
211
219
  return this.makeAPICall(requestFn, operationName, cacheKey, retryCount + 1);
@@ -9,7 +9,7 @@ export declare const PLUGIN_NAME = "homebridge-viessmann-vicare";
9
9
  /**
10
10
  * Plugin version for User-Agent and logging
11
11
  */
12
- export declare const PLUGIN_VERSION = "2.0.63";
12
+ export declare const PLUGIN_VERSION = "2.0.65";
13
13
  /**
14
14
  * Default configuration values
15
15
  */
package/dist/settings.js CHANGED
@@ -12,7 +12,7 @@ exports.PLUGIN_NAME = 'homebridge-viessmann-vicare';
12
12
  /**
13
13
  * Plugin version for User-Agent and logging
14
14
  */
15
- exports.PLUGIN_VERSION = '2.0.63';
15
+ exports.PLUGIN_VERSION = '2.0.65';
16
16
  /**
17
17
  * Default configuration values
18
18
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-viessmann-vicare",
3
- "version": "2.0.63",
3
+ "version": "2.0.65",
4
4
  "description": "Complete Homebridge plugin for Viessmann ViCare heating systems with full control capabilities, advanced rate limiting protection, and intelligent cache management",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -2329,14 +2329,14 @@ function _tt(tpl,x,y){return tpl.replace('__X__',x).replace('__Y__',y);}
2329
2329
  new Chart(c,{type:'line',data:{
2330
2330
  labels:${JSON.stringify(ovLabels)},
2331
2331
  datasets:[
2332
- {label:${T('chartRoomTemp')}, yAxisID:'yTemp', data:${JSON.stringify(ovRoom)}, borderColor:'#4e9af1',backgroundColor:'rgba(78,154,241,.06)',fill:true, tension:0.3,pointRadius:1,borderWidth:2},
2333
- {label:${T('chartHC0Setpoint')}, yAxisID:'yTemp', data:${JSON.stringify(ovSetpoint)},borderColor:'#f1c94e',backgroundColor:'transparent', fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[5,4]},
2334
- ...(${JSON.stringify(ovFlow)}.some(v=>v!==null) ? [{label:${T('chartFlowTemp')}, yAxisID:'yTemp', data:${JSON.stringify(ovFlow)}, borderColor:'#ef5350',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[2,2]}] : []),
2335
- {label:${T('chartDHWTemp')}, yAxisID:'yTemp', data:${JSON.stringify(ovDhw)}, borderColor:'#00897b',backgroundColor:'rgba(0,137,123,.04)',fill:false,tension:0.3,pointRadius:1,borderWidth:1.5},
2336
- {label:${T('chartOutdoorTemp')}, yAxisID:'yTemp', data:${JSON.stringify(ovOutside)}, borderColor:'#90a4ae',backgroundColor:'transparent', fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[3,3]},
2337
- {label:${T('chartModulation')}, yAxisID:'yRight',data:${JSON.stringify(ovMod)}, borderColor:'#e65100',backgroundColor:'rgba(230,81,0,.04)',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5},
2338
- {label:${T('chartBurnerBar')}, yAxisID:'yRight',data:${JSON.stringify(ovBurner)}, borderColor:'#37474f',backgroundColor:'rgba(55,71,79,.07)', fill:true, tension:0, pointRadius:0,borderWidth:1,stepped:true},
2339
- ...(${JSON.stringify(ovOutsideHum)}.some(v=>v!==null) ? [{label:${T('chartOutdoorHum')}, yAxisID:'yRight',data:${JSON.stringify(ovOutsideHum)},borderColor:'#7986cb',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[4,2]}] : [])
2332
+ {label:"${T('chartRoomTemp')}", yAxisID:'yTemp', data:${JSON.stringify(ovRoom)}, borderColor:'#4e9af1',backgroundColor:'rgba(78,154,241,.06)',fill:true, tension:0.3,pointRadius:1,borderWidth:2},
2333
+ {label:"${T('chartHC0Setpoint')}", yAxisID:'yTemp', data:${JSON.stringify(ovSetpoint)},borderColor:'#f1c94e',backgroundColor:'transparent', fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[5,4]},
2334
+ ...(${JSON.stringify(ovFlow)}.some(v=>v!==null) ? [{label:"${T('chartFlowTemp')}", yAxisID:'yTemp', data:${JSON.stringify(ovFlow)}, borderColor:'#ef5350',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[2,2]}] : []),
2335
+ {label:"${T('chartDHWTemp')}", yAxisID:'yTemp', data:${JSON.stringify(ovDhw)}, borderColor:'#00897b',backgroundColor:'rgba(0,137,123,.04)',fill:false,tension:0.3,pointRadius:1,borderWidth:1.5},
2336
+ {label:"${T('chartOutdoorTemp')}", yAxisID:'yTemp', data:${JSON.stringify(ovOutside)}, borderColor:'#90a4ae',backgroundColor:'transparent', fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[3,3]},
2337
+ {label:"${T('chartModulation')}", yAxisID:'yRight',data:${JSON.stringify(ovMod)}, borderColor:'#e65100',backgroundColor:'rgba(230,81,0,.04)',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5},
2338
+ {label:"${T('chartBurnerBar')}", yAxisID:'yRight',data:${JSON.stringify(ovBurner)}, borderColor:'#37474f',backgroundColor:'rgba(55,71,79,.07)', fill:true, tension:0, pointRadius:0,borderWidth:1,stepped:true},
2339
+ ...(${JSON.stringify(ovOutsideHum)}.some(v=>v!==null) ? [{label:"${T('chartOutdoorHum')}", yAxisID:'yRight',data:${JSON.stringify(ovOutsideHum)},borderColor:'#7986cb',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[4,2]}] : [])
2340
2340
  ]
2341
2341
  },options:{
2342
2342
  responsive:true,maintainAspectRatio:false,
@@ -2351,18 +2351,18 @@ function _tt(tpl,x,y){return tpl.replace('__X__',x).replace('__Y__',y);}
2351
2351
 
2352
2352
  })();
2353
2353
  ${boilerRows.length>=2?`
2354
- mk('cMod',${JSON.stringify(modChart.labels)},[{label:${T('chartModulation')},data:${JSON.stringify(modChart.values)},borderColor:'#e65100',backgroundColor:'rgba(230,81,0,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'%');
2355
- mk('cBurner',${JSON.stringify(burnerChart.labels)},[{label:${T('chartBurnerOnOff')},data:${JSON.stringify(burnerChart.values)},borderColor:'#1a1a2e',backgroundColor:'rgba(26,26,46,.06)',fill:true,tension:0,pointRadius:0,borderWidth:1.5,stepped:true}],'');`:''}
2354
+ mk('cMod',${JSON.stringify(modChart.labels)},[{label:"${T('chartModulation')}",data:${JSON.stringify(modChart.values)},borderColor:'#e65100',backgroundColor:'rgba(230,81,0,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'%');
2355
+ mk('cBurner',${JSON.stringify(burnerChart.labels)},[{label:"${T('chartBurnerOnOff')}",data:${JSON.stringify(burnerChart.values)},borderColor:'#1a1a2e',backgroundColor:'rgba(26,26,46,.06)',fill:true,tension:0,pointRadius:0,borderWidth:1.5,stepped:true}],'');`:''}
2356
2356
  ${hcRows.length>=2?`
2357
2357
  mk('cRoom',${JSON.stringify(roomChart.labels)},[
2358
- {label:${T('chartRoomTemp')},data:${JSON.stringify(roomChart.values)},borderColor:'#4e9af1',backgroundColor:'rgba(78,154,241,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2},
2359
- {label:${T('chartSetpoint')},data:${JSON.stringify(targetChart.values)},borderColor:'#f1c94e',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:2,borderDash:[5,4]}
2358
+ {label:"${T('chartRoomTemp')}",data:${JSON.stringify(roomChart.values)},borderColor:'#4e9af1',backgroundColor:'rgba(78,154,241,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2},
2359
+ {label:"${T('chartSetpoint')}",data:${JSON.stringify(targetChart.values)},borderColor:'#f1c94e',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:2,borderDash:[5,4]}
2360
2360
  ],'Β°C');`:''}
2361
2361
  ${flowVals.length>=2?`
2362
- mk('cFlow',${JSON.stringify(flowChart.labels)},[{label:${T('chartFlowTemp')},data:${JSON.stringify(flowChart.values)},borderColor:'#ef5350',backgroundColor:'rgba(239,83,80,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'Β°C');
2362
+ mk('cFlow',${JSON.stringify(flowChart.labels)},[{label:"${T('chartFlowTemp')}",data:${JSON.stringify(flowChart.values)},borderColor:'#ef5350',backgroundColor:'rgba(239,83,80,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'Β°C');
2363
2363
  `:''}
2364
2364
  ${cycleCount>=3?`
2365
- (function(){const c=document.getElementById('cCycleHist');if(!c)return;new Chart(c,{type:'bar',data:{labels:${JSON.stringify(histBuckets.map(b=>b.label))},datasets:[{label:${T('chartCycles')},data:${JSON.stringify(histData)},backgroundColor:${JSON.stringify(histData.map((_,i)=>i===0?'rgba(239,83,80,.7)':'rgba(78,154,241,.6)'))},borderColor:${JSON.stringify(histData.map((_,i)=>i===0?'#ef5350':'#4e9af1'))},borderWidth:1.5,borderRadius:4}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{x:{grid:{color:'#f5f5f5'}},y:{title:{display:true,text:${T('axisCycles')}},ticks:{stepSize:1}}}}});})();
2365
+ (function(){const c=document.getElementById('cCycleHist');if(!c)return;new Chart(c,{type:'bar',data:{labels:${JSON.stringify(histBuckets.map(b=>b.label))},datasets:[{label:"${T('chartCycles')}",data:${JSON.stringify(histData)},backgroundColor:${JSON.stringify(histData.map((_,i)=>i===0?'rgba(239,83,80,.7)':'rgba(78,154,241,.6)'))},borderColor:${JSON.stringify(histData.map((_,i)=>i===0?'#ef5350':'#4e9af1'))},borderWidth:1.5,borderRadius:4}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{x:{grid:{color:'#f5f5f5'}},y:{title:{display:true,text:"${T('axisCycles')}"},ticks:{stepSize:1}}}}});})();
2366
2366
  `:''}
2367
2367
  ${hasGasChart?`
2368
2368
  (function(){
@@ -2372,9 +2372,9 @@ ${hasGasChart?`
2372
2372
  data:{
2373
2373
  labels:${JSON.stringify(gasBarLabels)},
2374
2374
  datasets:[
2375
- {type:'bar', label:${T('chartHeatingM3')}, data:${JSON.stringify(gasBarHeating)}, backgroundColor:'rgba(26,86,180,.75)', borderColor:'#1a56b4', borderWidth:1, borderRadius:3, stack:'gas'},
2376
- {type:'bar', label:${T('chartDHWM3')}, data:${JSON.stringify(gasBarDhw)}, backgroundColor:'rgba(0,137,123,.65)', borderColor:'#00897b', borderWidth:1, borderRadius:3, stack:'gas'},
2377
- {type:'line',label:${T('chartTotalM3')}, data:${JSON.stringify(gasLineTotal)}, borderColor:'#e53935', backgroundColor:'transparent', borderWidth:2, pointRadius:4, pointBackgroundColor:'#e53935', tension:0.3, yAxisID:'y'}
2375
+ {type:'bar', label:"${T('chartHeatingM3')}", data:${JSON.stringify(gasBarHeating)}, backgroundColor:'rgba(26,86,180,.75)', borderColor:'#1a56b4', borderWidth:1, borderRadius:3, stack:'gas'},
2376
+ {type:'bar', label:"${T('chartDHWM3')}", data:${JSON.stringify(gasBarDhw)}, backgroundColor:'rgba(0,137,123,.65)', borderColor:'#00897b', borderWidth:1, borderRadius:3, stack:'gas'},
2377
+ {type:'line',label:"${T('chartTotalM3')}", data:${JSON.stringify(gasLineTotal)}, borderColor:'#e53935', backgroundColor:'transparent', borderWidth:2, pointRadius:4, pointBackgroundColor:'#e53935', tension:0.3, yAxisID:'y'}
2378
2378
  ]
2379
2379
  },
2380
2380
  options:{
@@ -2391,19 +2391,19 @@ ${hasGasChart?`
2391
2391
  `:''}
2392
2392
  ${dhwRows.length>=2?`
2393
2393
  mk('cDhw',${JSON.stringify(dhwChart.labels)},[
2394
- {label:${T('chartDHWTemp')},data:${JSON.stringify(dhwChart.values)},borderColor:'#00897b',backgroundColor:'rgba(0,137,123,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2},
2395
- {label:${T('chartDHWSetpoint')},data:${JSON.stringify(dhwTgtChart.values)},borderColor:'#80cbc4',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:2,borderDash:[5,4]}
2394
+ {label:"${T('chartDHWTemp')}",data:${JSON.stringify(dhwChart.values)},borderColor:'#00897b',backgroundColor:'rgba(0,137,123,.07)',fill:true,tension:0.3,pointRadius:2,borderWidth:2},
2395
+ {label:"${T('chartDHWSetpoint')}",data:${JSON.stringify(dhwTgtChart.values)},borderColor:'#80cbc4',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:2,borderDash:[5,4]}
2396
2396
  ],'Β°C');`:''}
2397
2397
  ${hasPV&&energyRows.length>=2?`
2398
- mk('cPV',${JSON.stringify(pvChart.labels)},[{label:${T('chartPVProd')},data:${JSON.stringify(pvChart.values)},borderColor:'#f9a825',backgroundColor:'rgba(249,168,37,.1)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'W');`:''}\n${hasBattery&&energyRows.length>=2?`
2399
- mk('cBatt',${JSON.stringify(battChart.labels)},[{label:${T('chartBattLevel')},data:${JSON.stringify(battChart.values)},borderColor:'#43a047',backgroundColor:'rgba(67,160,71,.08)',fill:true,tension:0.3,pointRadius:2,borderWidth:2},{label:${T('chartBattChargeW')},data:${JSON.stringify(battChrChart.values)},borderColor:'#1e88e5',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[4,3]},{label:${T('chartBattDischarge')},data:${JSON.stringify(battDisChart.values)},borderColor:'#e53935',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[4,3]}],'');`:''}\n${hasWallbox&&energyRows.length>=2?`
2400
- mk('cWallbox',${JSON.stringify(wallboxChart.labels)},[{label:${T('chartWallboxW')},data:${JSON.stringify(wallboxChart.values)},borderColor:'#7b1fa2',backgroundColor:'rgba(123,31,162,.08)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'W');`:''}\n${scatterData.length>=10?`
2398
+ mk('cPV',${JSON.stringify(pvChart.labels)},[{label:"${T('chartPVProd')}",data:${JSON.stringify(pvChart.values)},borderColor:'#f9a825',backgroundColor:'rgba(249,168,37,.1)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'W');`:''}\n${hasBattery&&energyRows.length>=2?`
2399
+ mk('cBatt',${JSON.stringify(battChart.labels)},[{label:"${T('chartBattLevel')}",data:${JSON.stringify(battChart.values)},borderColor:'#43a047',backgroundColor:'rgba(67,160,71,.08)',fill:true,tension:0.3,pointRadius:2,borderWidth:2},{label:"${T('chartBattChargeW')}",data:${JSON.stringify(battChrChart.values)},borderColor:'#1e88e5',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[4,3]},{label:"${T('chartBattDischarge')}",data:${JSON.stringify(battDisChart.values)},borderColor:'#e53935',backgroundColor:'transparent',fill:false,tension:0.3,pointRadius:0,borderWidth:1.5,borderDash:[4,3]}],'');`:''}\n${hasWallbox&&energyRows.length>=2?`
2400
+ mk('cWallbox',${JSON.stringify(wallboxChart.labels)},[{label:"${T('chartWallboxW')}",data:${JSON.stringify(wallboxChart.values)},borderColor:'#7b1fa2',backgroundColor:'rgba(123,31,162,.08)',fill:true,tension:0.3,pointRadius:2,borderWidth:2}],'W');`:''}\n${scatterData.length>=10?`
2401
2401
  (function(){
2402
2402
  const c=document.getElementById('cScatter'); if(!c)return;
2403
2403
  const pts=${JSON.stringify(scatterData.length > 300 ? scatterData.filter((_,i)=>i%Math.ceil(scatterData.length/300)===0) : scatterData)};
2404
2404
  const reg=${JSON.stringify(scatterRegression)};
2405
2405
  const datasets=[{
2406
- label:${T('chartHeatDemand')},
2406
+ label:"${T('chartHeatDemand')}",
2407
2407
  data:pts,
2408
2408
  backgroundColor:'rgba(78,154,241,0.35)',
2409
2409
  pointRadius:3,
@@ -2412,7 +2412,7 @@ mk('cWallbox',${JSON.stringify(wallboxChart.labels)},[{label:${T('chartWallboxW'
2412
2412
  }];
2413
2413
  if(reg){
2414
2414
  datasets.push({
2415
- label:${T('chartTrend')},
2415
+ label:"${T('chartTrend')}",
2416
2416
  data:reg.line,
2417
2417
  type:'line',
2418
2418
  borderColor:'#ef5350',
@@ -2447,8 +2447,8 @@ mk('cWallbox',${JSON.stringify(wallboxChart.labels)},[{label:${T('chartWallboxW'
2447
2447
  tooltip:{callbacks:{label:p=>_tt(_tooltip.outdoor,p.parsed.x,p.parsed.y)}}
2448
2448
  },
2449
2449
  scales:{
2450
- x:{title:{display:true,text:${T('axisOutdoorTemp')}},grid:{color:'#f5f5f5'}},
2451
- y:{title:{display:true,text:${T('axisHeatDemand')}},beginAtZero:true,grid:{color:'#f5f5f5'}}
2450
+ x:{title:{display:true,text:"${T('axisOutdoorTemp')}"},grid:{color:'#f5f5f5'}},
2451
+ y:{title:{display:true,text:"${T('axisHeatDemand')}"},beginAtZero:true,grid:{color:'#f5f5f5'}}
2452
2452
  },
2453
2453
  plugins:{
2454
2454
  zoom:{
@@ -2481,7 +2481,7 @@ ${hasCurve && corrPairs2.length >= 5 ? `
2481
2481
  type:'scatter',
2482
2482
  data:{datasets:[
2483
2483
  {
2484
- label:${T('chartActualFlow')},
2484
+ label:"${T('chartActualFlow')}",
2485
2485
  data:pts,
2486
2486
  backgroundColor:'rgba(78,154,241,0.4)',
2487
2487
  pointRadius:3,
@@ -2489,7 +2489,7 @@ ${hasCurve && corrPairs2.length >= 5 ? `
2489
2489
  type:'scatter'
2490
2490
  },
2491
2491
  {
2492
- label:${T('chartHeatingCurve',{slope:CURVE_SLOPE,shift:CURVE_SHIFT})},
2492
+ label:"${T('chartHeatingCurve',{slope:CURVE_SLOPE,shift:CURVE_SHIFT})}",
2493
2493
  data:curve,
2494
2494
  type:'line',
2495
2495
  borderColor:'#f57c00',
@@ -2500,7 +2500,7 @@ ${hasCurve && corrPairs2.length >= 5 ? `
2500
2500
  tension:0
2501
2501
  },
2502
2502
  {
2503
- label:${T('chartCondensingLimit')},
2503
+ label:"${T('chartCondensingLimit')}",
2504
2504
  data:[{x:-30,y:55},{x:30,y:55}],
2505
2505
  type:'line',
2506
2506
  borderColor:'rgba(67,160,71,0.7)',
@@ -2523,8 +2523,8 @@ ${hasCurve && corrPairs2.length >= 5 ? `
2523
2523
  : _tt(_tooltip.flowCurve,p.parsed.x,p.parsed.y)}}
2524
2524
  },
2525
2525
  scales:{
2526
- x:{title:{display:true,text:${T('axisOutdoorTemp')}},grid:{color:'#f5f5f5'}},
2527
- y:{title:{display:true,text:${T('axisFlowTemp')}},grid:{color:'#f5f5f5'},suggestedMin:20,suggestedMax:80}
2526
+ x:{title:{display:true,text:"${T('axisOutdoorTemp')}"},grid:{color:'#f5f5f5'}},
2527
+ y:{title:{display:true,text:"${T('axisFlowTemp')}"},grid:{color:'#f5f5f5'},suggestedMin:20,suggestedMax:80}
2528
2528
  },
2529
2529
  plugins:{
2530
2530
  zoom:{
@@ -2571,7 +2571,7 @@ ${dailyEfficiency.hasData?`
2571
2571
  data:{
2572
2572
  labels:${JSON.stringify(dailyEfficiency.labels)},
2573
2573
  datasets:[{
2574
- label:${T('chartThermalEff')},
2574
+ label:"${T('chartThermalEff')}",
2575
2575
  data:vals,
2576
2576
  borderColor:'#43a047',
2577
2577
  backgroundColor:'rgba(67,160,71,.09)',
@@ -2601,11 +2601,11 @@ ${energyFlow&&energyFlow.hasData?`
2601
2601
  const c=document.getElementById('cEnergyFlow');if(!c)return;
2602
2602
  const ef=${JSON.stringify(energyFlow)};
2603
2603
  const ds=[
2604
- {label:${T('chartPV')}, data:ef.pv, backgroundColor:'rgba(249,168,37,.75)',borderColor:'#f9a825',borderWidth:1,borderRadius:2,stack:'s'},
2605
- {label:${T('chartBattCharge')}, data:ef.battChr, backgroundColor:'rgba(67,160,71,.65)', borderColor:'#43a047',borderWidth:1,borderRadius:2,stack:'s'},
2606
- {label:${T('chartGridDraw')}, data:ef.gridDraw,backgroundColor:'rgba(30,136,229,.65)',borderColor:'#1e88e5',borderWidth:1,borderRadius:2,stack:'s'},
2604
+ {label:"${T('chartPV')}", data:ef.pv, backgroundColor:'rgba(249,168,37,.75)',borderColor:'#f9a825',borderWidth:1,borderRadius:2,stack:'s'},
2605
+ {label:"${T('chartBattCharge')}", data:ef.battChr, backgroundColor:'rgba(67,160,71,.65)', borderColor:'#43a047',borderWidth:1,borderRadius:2,stack:'s'},
2606
+ {label:"${T('chartGridDraw')}", data:ef.gridDraw,backgroundColor:'rgba(30,136,229,.65)',borderColor:'#1e88e5',borderWidth:1,borderRadius:2,stack:'s'},
2607
2607
  ];
2608
- if(ef.wallbox.some(v=>v>0))ds.push({label:${T('chartWallbox')},data:ef.wallbox,backgroundColor:'rgba(123,31,162,.55)',borderColor:'#7b1fa2',borderWidth:1,borderRadius:2,stack:'s'});
2608
+ if(ef.wallbox.some(v=>v>0))ds.push({label:"${T('chartWallbox')}",data:ef.wallbox,backgroundColor:'rgba(123,31,162,.55)',borderColor:'#7b1fa2',borderWidth:1,borderRadius:2,stack:'s'});
2609
2609
  new Chart(c,{
2610
2610
  type:'bar',
2611
2611
  data:{labels:ef.labels,datasets:ds},
@@ -2615,7 +2615,7 @@ ${energyFlow&&energyFlow.hasData?`
2615
2615
  plugins:{legend:{position:'top',labels:{boxWidth:11,padding:12}}},
2616
2616
  scales:{
2617
2617
  x:{grid:{color:'#f5f5f5'},stacked:true},
2618
- y:{title:{display:true,text:${T('axisAvgW')}},grid:{color:'#f5f5f5'},stacked:true,beginAtZero:true}
2618
+ y:{title:{display:true,text:"${T('axisAvgW')}"},grid:{color:'#f5f5f5'},stacked:true,beginAtZero:true}
2619
2619
  }
2620
2620
  }
2621
2621
  });