Mercurial > ~darius > hgwebdir.cgi > OverviewJD
comparison OverviewJD.qml @ 0:57ffb39f29d4
First commit of new carousel page to allow battery charging current to
be adjusted.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 13 Dec 2021 23:05:38 +1030 |
parents | |
children | 594ba407689b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:57ffb39f29d4 |
---|---|
1 // Modified version of OverviewMobile.qml | |
2 import QtQuick 1.1 | |
3 import com.victron.velib 1.0 | |
4 import "utils.js" as Utils | |
5 | |
6 OverviewPage { | |
7 id: root | |
8 | |
9 property variant sys: theSystem | |
10 property string settingsBindPreffix: "com.victronenergy.settings" | |
11 property string pumpBindPreffix: "com.victronenergy.pump.startstop0" | |
12 property variant activeNotifications: NotificationCenter.notifications.filter( | |
13 function isActive(obj) { return obj.active} ) | |
14 property string noAdjustableByDmc: qsTr("This setting is disabled when a Digital Multi Control " + | |
15 "is connected. If it was recently disconnected execute " + | |
16 "\"Redetect system\" that is avalible on the inverter menu page.") | |
17 property string noAdjustableByBms: qsTr("This setting is disabled when a VE.Bus BMS " + | |
18 "is connected. If it was recently disconnected execute " + | |
19 "\"Redetect system\" that is avalible on the inverter menu page.") | |
20 property string noAdjustableTextByConfig: qsTr("This setting is disabled. " + | |
21 "Possible reasons are \"Overruled by remote\" is not enabled or " + | |
22 "an assistant is preventing the adjustment. Please, check " + | |
23 "the inverter configuration with VEConfigure.") | |
24 property int numberOfMultis: 0 | |
25 property string vebusPrefix: "" | |
26 | |
27 // Keeps track of which button on the bottom row is active | |
28 property int buttonIndex: 0 | |
29 | |
30 title: qsTr("Java Drive") | |
31 | |
32 Component.onCompleted: discoverMulti() | |
33 | |
34 ListView { | |
35 id: pwColumn | |
36 | |
37 property int tilesCount: solarTile.visible || dcSystem.visible ? 3 : 2 | |
38 property int tileHeight: Math.ceil(height / tilesCount) | |
39 interactive: false // static tiles | |
40 | |
41 width: 136 | |
42 anchors { | |
43 left: parent.left | |
44 top: parent.top; | |
45 bottom: acModeButton.top; | |
46 } | |
47 | |
48 model: VisualItemModel { | |
49 Tile { | |
50 width: pwColumn.width | |
51 height: visible ? pwColumn.tileHeight : 0 | |
52 title: qsTr("AC INPUT") | |
53 color: "#82acde" | |
54 visible: !dcSystem.visible || !solarTile.visible | |
55 values: [ | |
56 TileText { | |
57 text: sys.acInput.power.uiText | |
58 font.pixelSize: 25 | |
59 }, | |
60 TileText { | |
61 property VBusItem inV1: VBusItem { bind: Utils.path(sys.vebusPrefix, "/Ac/ActiveIn/L1/V"); unit: "V" } | |
62 text: inV1.format(1) | |
63 font.pixelSize: 15 | |
64 }, | |
65 TileText { | |
66 property VBusItem inI1: VBusItem { bind: Utils.path(sys.vebusPrefix, "/Ac/ActiveIn/L1/I"); unit: "A" } | |
67 text: inI1.format(1) | |
68 font.pixelSize: 15 | |
69 }, | |
70 TileText { | |
71 property VBusItem inF1: VBusItem { bind: Utils.path(sys.vebusPrefix, "/Ac/ActiveIn/L1/F"); unit: "Hz" } | |
72 text: inF1.format(0) | |
73 font.pixelSize: 15 | |
74 } | |
75 ] | |
76 } | |
77 | |
78 TileAcPower { | |
79 width: pwColumn.width | |
80 height: visible ? pwColumn.tileHeight : 0 | |
81 title: qsTr("AC LOADS") | |
82 color: "#e68e8a" | |
83 values: [ | |
84 TileText { | |
85 text: sys.acLoad.power.uiText | |
86 font.pixelSize: 25 | |
87 }, | |
88 TileText { | |
89 property VBusItem outV1: VBusItem { bind: Utils.path(sys.vebusPrefix, "/Ac/Out/L1/V"); unit: "V" } | |
90 text: outV1.format(1) | |
91 font.pixelSize: 15 | |
92 }, | |
93 TileText { | |
94 property VBusItem outI1: VBusItem { bind: Utils.path(sys.vebusPrefix, "/Ac/Out/L1/I"); unit: "A" } | |
95 text: outI1.format(1) | |
96 font.pixelSize: 15 | |
97 }, | |
98 TileText { | |
99 property VBusItem outF1: VBusItem { bind: Utils.path(sys.vebusPrefix, "/Ac/Out/L1/F"); unit: "Hz" } | |
100 text: outF1.format(0) | |
101 font.pixelSize: 15 | |
102 } | |
103 ] | |
104 } | |
105 | |
106 Tile { | |
107 id: solarTile | |
108 width: pwColumn.width | |
109 height: visible ? pwColumn.tileHeight : 0 | |
110 title: qsTr("PV CHARGER") | |
111 color: "#2cc36b" | |
112 visible : sys.pvCharger.power.valid | |
113 | |
114 values: [ | |
115 TileText { | |
116 font.pixelSize: 30 | |
117 text: sys.pvCharger.power.uiText | |
118 } | |
119 ] | |
120 } | |
121 Tile { | |
122 id: dcSystem | |
123 width: pwColumn.width | |
124 height: visible ? pwColumn.tileHeight : 0 | |
125 title: qsTr("DC SYSTEM") | |
126 color: "#16a085" | |
127 visible : hasDcSys.value === 1 | |
128 | |
129 VBusItem { | |
130 id: hasDcSys | |
131 bind: Utils.path(settingsBindPreffix, "/Settings/SystemSetup/HasDcSystem") | |
132 } | |
133 | |
134 values: [ | |
135 TileText { | |
136 font.pixelSize: 30 | |
137 text: sys.dcSystem.power.format(0) | |
138 }, | |
139 TileText { | |
140 text: !sys.dcSystem.power.valid ? "---" : | |
141 sys.dcSystem.power.value < 0 ? qsTr("to battery") : qsTr("from battery") | |
142 } | |
143 ] | |
144 } | |
145 } | |
146 } | |
147 | |
148 Tile { | |
149 id: logoTile | |
150 | |
151 color: "#575748" | |
152 height: 120 | |
153 anchors { | |
154 left: pwColumn.right | |
155 right: tanksColum.left | |
156 top: parent.top | |
157 } | |
158 | |
159 MbIcon { | |
160 x: 1 | |
161 y: 1 | |
162 // see below, so the svg instead of a png if there is a 1x1 image | |
163 visible: customImage.sourceSize.width === 1 && customImage.sourceSize.height === 1 | |
164 iconId: "mobile-builder-logo-svg" | |
165 } | |
166 | |
167 // The uploaded png, the default is a 1x1 transparent pixel now. | |
168 Image { | |
169 id: customImage | |
170 source: "image://theme/mobile-builder-logo" | |
171 anchors.centerIn: parent | |
172 } | |
173 } | |
174 | |
175 Tile { | |
176 id: batteryTile | |
177 height: 112 | |
178 title: qsTr("BATTERY") | |
179 anchors { | |
180 left: pwColumn.right | |
181 right: stateTile.left | |
182 top: logoTile.bottom | |
183 bottom: acModeButton.top | |
184 } | |
185 | |
186 values: [ | |
187 TileText { | |
188 text: sys.battery.soc.absFormat(0) | |
189 font.pixelSize: 30 | |
190 height: 32 | |
191 }, | |
192 TileText { | |
193 text: { | |
194 if (!sys.battery.state.valid) | |
195 return "---" | |
196 switch(sys.battery.state.value) { | |
197 case sys.batteryStateIdle: return qsTr("idle") | |
198 case sys.batteryStateCharging : return qsTr("charging") | |
199 case sys.batteryStateDischarging : return qsTr("discharging") | |
200 } | |
201 } | |
202 }, | |
203 TileText { | |
204 text: sys.battery.power.absFormat(0) | |
205 }, | |
206 TileText { | |
207 text: sys.battery.voltage.format(1) + " " + sys.battery.current.format(1) | |
208 } | |
209 ] | |
210 } | |
211 | |
212 Tile { | |
213 id: stateTile | |
214 | |
215 width: 104 | |
216 title: qsTr("STATUS") | |
217 color: "#4789d0" | |
218 | |
219 anchors { | |
220 right: tanksColum.left | |
221 top: logoTile.bottom | |
222 bottom: acModeButton.top | |
223 } | |
224 | |
225 Timer { | |
226 id: wallClock | |
227 | |
228 running: true | |
229 repeat: true | |
230 interval: 1000 | |
231 triggeredOnStart: true | |
232 onTriggered: time = Qt.formatDateTime(new Date(), "hh:mm") | |
233 | |
234 property string time | |
235 } | |
236 | |
237 values: [ | |
238 TileText { | |
239 id: systemTile | |
240 text: wallClock.time | |
241 font.pixelSize: 30 | |
242 }, | |
243 TileText { | |
244 property VeQuickItem gpsService: VeQuickItem { uid: "dbus/com.victronenergy.system/GpsService" } | |
245 property VeQuickItem speed: VeQuickItem { uid: Utils.path("dbus/", gpsService.value, "/Speed") } | |
246 property VeQuickItem speedUnit: VeQuickItem { uid: "dbus/com.victronenergy.settings/Settings/Gps/SpeedUnit" } | |
247 | |
248 text: speed.value === undefined ? "" : getValue() | |
249 visible: speed.value !== undefined && speedUnit.value !== undefined | |
250 | |
251 function getValue() | |
252 { | |
253 if (speedUnit.value === "km/h") | |
254 return (speed.value * 3.6).toFixed(1) + speedUnit.value | |
255 if (speedUnit.value === "mph") | |
256 return (speed.value * 2.236936).toFixed(1) + speedUnit.value | |
257 if (speedUnit.value === "kt") | |
258 return (speed.value * (3600/1852)).toFixed(1) + speedUnit.value | |
259 return speed.value.toFixed(2) + "m/s" | |
260 } | |
261 }, | |
262 Marquee { | |
263 text: notificationText() | |
264 width: stateTile.width | |
265 interval: 100 | |
266 fontSize: 13 | |
267 } | |
268 ] | |
269 } | |
270 | |
271 ListView { | |
272 id: tanksColum | |
273 | |
274 property int tileHeight: Math.ceil(height / Math.max(count, 2)) | |
275 width: 134 | |
276 interactive: false // static tiles | |
277 model: TankModel { id: tankModel } | |
278 delegate: TileTank { | |
279 // Without an intermediate assignment this will trigger a binding loop warning. | |
280 property variant theService: DBusServices.get(buddy.id) | |
281 service: theService | |
282 width: tanksColum.width | |
283 height: tanksColum.tileHeight | |
284 pumpBindPrefix: root.pumpBindPreffix | |
285 compact: tankModel.rowCount > (pumpButton.pumpEnabled ? 4 : 5) | |
286 Connections { | |
287 target: scrollTimer | |
288 onTriggered: doScroll() | |
289 } | |
290 } | |
291 | |
292 anchors { | |
293 top: root.top | |
294 bottom: pumpButton.pumpEnabled ? acModeButton.top : acModeButton.bottom | |
295 right: root.right | |
296 } | |
297 | |
298 // Synchronise tank name text scroll start | |
299 Timer { | |
300 id: scrollTimer | |
301 interval: 15000 | |
302 repeat: true | |
303 running: root.active && tankModel.rowCount > 4 | |
304 } | |
305 | |
306 Tile { | |
307 title: qsTr("TANKS") | |
308 anchors.fill: parent | |
309 values: TileText { | |
310 text: qsTr("No tanks found") | |
311 width: parent.width | |
312 wrapMode: Text.WordWrap | |
313 } | |
314 z: -1 | |
315 } | |
316 } | |
317 | |
318 Keys.forwardTo: [keyHandler] | |
319 | |
320 Item { | |
321 id: keyHandler | |
322 Keys.onLeftPressed: { | |
323 if (buttonIndex > 0) | |
324 buttonIndex-- | |
325 | |
326 event.accepted = true | |
327 } | |
328 | |
329 Keys.onRightPressed: { | |
330 if (buttonIndex < (pumpButton.pumpEnabled ? 3 : 2)) | |
331 buttonIndex++ | |
332 | |
333 event.accepted = true | |
334 } | |
335 } | |
336 | |
337 MouseArea { | |
338 anchors.fill: parent | |
339 enabled: parent.active | |
340 onPressed: mouse.accepted = acCurrentButton.expanded | |
341 onClicked: acCurrentButton.cancel() | |
342 } | |
343 | |
344 TileSpinBox { | |
345 id: acCurrentButton | |
346 | |
347 anchors.bottom: parent.bottom | |
348 anchors.left: parent.left | |
349 isCurrentItem: (buttonIndex == 0) | |
350 focus: root.active && isCurrentItem | |
351 | |
352 bind: Utils.path(vebusPrefix, "/Ac/ActiveIn/CurrentLimit") | |
353 title: qsTr("AC CURRENT LIMIT") | |
354 color: containsMouse && !editMode ? "#d3d3d3" : "#A8A8A8" | |
355 width: pumpButton.pumpEnabled ? 160 : 173 | |
356 fontPixelSize: 14 | |
357 unit: "A" | |
358 readOnly: currentLimitIsAdjustable.value !== 1 || numberOfMultis > 1 | |
359 buttonColor: "#979797" | |
360 | |
361 VBusItem { id: currentLimitIsAdjustable; bind: Utils.path(vebusPrefix, "/Ac/ActiveIn/CurrentLimitIsAdjustable") } | |
362 | |
363 Keys.onSpacePressed: showErrorToast(event) | |
364 | |
365 function editIsAllowed() { | |
366 if (numberOfMultis > 1) { | |
367 toast.createToast(qsTr("It is not possible to change this setting when there are more than one inverter connected."), 5000) | |
368 return false | |
369 } | |
370 | |
371 if (currentLimitIsAdjustable.value === 0) { | |
372 if (dmc.valid) { | |
373 toast.createToast(noAdjustableByDmc, 5000) | |
374 return false | |
375 } | |
376 if (bms.valid) { | |
377 toast.createToast(noAdjustableByBms, 5000) | |
378 return false | |
379 } | |
380 if (!dmc.valid && !bms.valid) { | |
381 toast.createToast(noAdjustableTextByConfig, 5000) | |
382 return false | |
383 } | |
384 } | |
385 | |
386 return true | |
387 } | |
388 | |
389 function showErrorToast(event) { | |
390 editIsAllowed() | |
391 event.accepted = true | |
392 } | |
393 } | |
394 | |
395 Tile { | |
396 id: acModeButton | |
397 anchors.left: acCurrentButton.right | |
398 anchors.bottom: parent.bottom | |
399 property variant texts: { 4: qsTr("OFF"), 3: qsTr("ON"), 1: qsTr("CHARGER ONLY") } | |
400 property int value: mode.valid ? mode.value : 3 | |
401 property int shownValue: applyAnimation2.running ? applyAnimation2.pendingValue : value | |
402 | |
403 isCurrentItem: (buttonIndex == 1) | |
404 focus: root.active && isCurrentItem | |
405 | |
406 editable: true | |
407 readOnly: !modeIsAdjustable.valid || modeIsAdjustable.value !== 1 || numberOfMultis > 1 | |
408 width: pumpButton.pumpEnabled ? 160 : 173 | |
409 height: 45 | |
410 color: acModeButtonMouseArea.containsPressed ? "#d3d3d3" : "#A8A8A8" | |
411 title: qsTr("AC MODE") | |
412 | |
413 values: [ | |
414 TileText { | |
415 text: modeIsAdjustable.valid && numberOfMultis === 1 ? qsTr("%1").arg(acModeButton.texts[acModeButton.shownValue]) : qsTr("NOT AVAILABLE") | |
416 } | |
417 ] | |
418 | |
419 VBusItem { id: mode; bind: Utils.path(vebusPrefix, "/Mode") } | |
420 VBusItem { id: modeIsAdjustable; bind: Utils.path(vebusPrefix,"/ModeIsAdjustable") } | |
421 | |
422 Keys.onSpacePressed: edit() | |
423 | |
424 function edit() { | |
425 if (!mode.valid) | |
426 return | |
427 | |
428 if (numberOfMultis > 1) { | |
429 toast.createToast(qsTr("It is not possible to change this setting when there are more than one inverter connected."), 5000) | |
430 return | |
431 } | |
432 | |
433 if (modeIsAdjustable.value === 0) { | |
434 if (dmc.valid) | |
435 toast.createToast(noAdjustableByDmc, 5000) | |
436 if (bms.valid) | |
437 toast.createToast(noAdjustableByBms, 5000) | |
438 if (!dmc.valid && !bms.valid) | |
439 toast.createToast(noAdjustableTextByConfig, 5000) | |
440 return | |
441 } | |
442 | |
443 switch (shownValue) { | |
444 case 4: | |
445 applyAnimation2.pendingValue = 3 | |
446 break; | |
447 case 3: | |
448 applyAnimation2.pendingValue = 1 | |
449 break; | |
450 case 1: | |
451 applyAnimation2.pendingValue = 4 | |
452 break; | |
453 } | |
454 | |
455 applyAnimation2.restart() | |
456 } | |
457 | |
458 MouseArea { | |
459 id: acModeButtonMouseArea | |
460 anchors.fill: parent | |
461 property bool containsPressed: containsMouse && pressed | |
462 onClicked: { | |
463 buttonIndex = 1 | |
464 parent.edit() | |
465 } | |
466 } | |
467 | |
468 Rectangle { | |
469 id: timerRect2 | |
470 height: 2 | |
471 width: acModeButton.width * 0.8 | |
472 visible: applyAnimation2.running | |
473 anchors { | |
474 bottom: parent.bottom; bottomMargin: 5 | |
475 horizontalCenter: parent.horizontalCenter | |
476 } | |
477 } | |
478 | |
479 SequentialAnimation { | |
480 id: applyAnimation2 | |
481 | |
482 property int pendingValue | |
483 | |
484 NumberAnimation { | |
485 target: timerRect2 | |
486 property: "width" | |
487 from: 0 | |
488 to: acModeButton.width * 0.8 | |
489 duration: 3000 | |
490 } | |
491 | |
492 ColorAnimation { | |
493 target: acModeButton | |
494 property: "color" | |
495 from: "#A8A8A8" | |
496 to: "#4789d0" | |
497 duration: 200 | |
498 } | |
499 | |
500 ColorAnimation { | |
501 target: acModeButton | |
502 property: "color" | |
503 from: "#4789d0" | |
504 to: "#A8A8A8" | |
505 duration: 200 | |
506 } | |
507 PropertyAction { | |
508 target: timerRect2 | |
509 property: "width" | |
510 value: 0 | |
511 } | |
512 | |
513 ScriptAction { script: mode.setValue(applyAnimation2.pendingValue) } | |
514 | |
515 PauseAnimation { duration: 1000 } | |
516 } | |
517 } | |
518 | |
519 TileSpinBox { | |
520 id: battCurrentButton | |
521 | |
522 anchors.bottom: parent.bottom | |
523 anchors.left: acModeButton.right | |
524 isCurrentItem: (buttonIndex == 2) | |
525 focus: root.active && isCurrentItem | |
526 | |
527 bind: Utils.path(vebusPrefix, "/Dc/0/MaxChargeCurrent") | |
528 title: qsTr("BAT CURR LIMIT") | |
529 color: containsMouse && !editMode ? "#d3d3d3" : "#A8A8A8" | |
530 width: 134 | |
531 fontPixelSize: 14 | |
532 unit: "A" | |
533 readOnly: false | |
534 editable: true | |
535 buttonColor: "#979797" | |
536 | |
537 Keys.onSpacePressed: showErrorToast(event) | |
538 | |
539 function showErrorToast(event) { | |
540 editIsAllowed() | |
541 event.accepted = true | |
542 } | |
543 } | |
544 | |
545 Tile { | |
546 id: pumpButton | |
547 | |
548 anchors.left: battCurrentButton.right | |
549 anchors.bottom: parent.bottom | |
550 | |
551 property variant texts: [ qsTr("AUTO"), qsTr("ON"), qsTr("OFF")] | |
552 property int value: 0 | |
553 property bool reset: false | |
554 property bool pumpEnabled: pumpRelay.value === 3 | |
555 | |
556 show: pumpEnabled | |
557 isCurrentItem: (buttonIndex == 3) | |
558 focus: root.active && isCurrentItem | |
559 | |
560 title: qsTr("PUMP") | |
561 width: show ? 160 : 0 | |
562 height: 45 | |
563 editable: true | |
564 readOnly: false | |
565 color: pumpButtonMouseArea.containsPressed ? "#d3d3d3" : "#A8A8A8" | |
566 | |
567 VBusItem { id: pump; bind: Utils.path(settingsBindPreffix, "/Settings/Pump0/Mode") } | |
568 VBusItem { id: pumpRelay; bind: Utils.path(settingsBindPreffix, "/Settings/Relay/Function") } | |
569 | |
570 values: [ | |
571 TileText { | |
572 text: pumpButton.pumpEnabled ? qsTr("%1").arg(pumpButton.texts[pumpButton.value]) : qsTr("DISABLED") | |
573 } | |
574 ] | |
575 | |
576 Keys.onSpacePressed: edit() | |
577 | |
578 function edit() { | |
579 if (!pumpEnabled) { | |
580 toast.createToast(qsTr("Pump functionality is not enabled. To enable it go to the relay settings page and set function to \"Tank pump\""), 5000) | |
581 return | |
582 } | |
583 | |
584 reset = true | |
585 applyAnimation.restart() | |
586 reset = false | |
587 | |
588 if (value < 2) | |
589 value++ | |
590 else | |
591 value = 0 | |
592 } | |
593 | |
594 MouseArea { | |
595 id: pumpButtonMouseArea | |
596 property bool containsPressed: containsMouse && pressed | |
597 anchors.fill: parent | |
598 onClicked: { | |
599 buttonIndex = 2 | |
600 parent.edit() | |
601 } | |
602 } | |
603 | |
604 Rectangle { | |
605 id: timerRect | |
606 height: 2 | |
607 width: pumpButton.width * 0.8 | |
608 visible: applyAnimation.running | |
609 anchors { | |
610 bottom: parent.bottom; bottomMargin: 5 | |
611 horizontalCenter: parent.horizontalCenter | |
612 } | |
613 } | |
614 | |
615 SequentialAnimation { | |
616 id: applyAnimation | |
617 alwaysRunToEnd: false | |
618 NumberAnimation { | |
619 target: timerRect | |
620 property: "width" | |
621 from: 0 | |
622 to: pumpButton.width * 0.8 | |
623 duration: 3000 | |
624 } | |
625 | |
626 ColorAnimation { | |
627 target: pumpButton | |
628 property: "color" | |
629 from: "#A8A8A8" | |
630 to: "#4789d0" | |
631 duration: 200 | |
632 } | |
633 | |
634 ColorAnimation { | |
635 target: pumpButton | |
636 property: "color" | |
637 from: "#4789d0" | |
638 to: "#A8A8A8" | |
639 duration: 200 | |
640 } | |
641 PropertyAction { | |
642 target: timerRect | |
643 property: "width" | |
644 value: 0 | |
645 } | |
646 // Do not set value if the animation is restarted by user pressing the button | |
647 // to move between options | |
648 onCompleted: if (!pumpButton.reset) pump.setValue(pumpButton.value) | |
649 } | |
650 } | |
651 | |
652 // When new service is found check if is a tank sensor | |
653 Connections { | |
654 target: DBusServices | |
655 onDbusServiceFound: addService(service) | |
656 } | |
657 | |
658 function addService(service) | |
659 { | |
660 if (service.type === DBusService.DBUS_SERVICE_MULTI) { | |
661 numberOfMultis++ | |
662 if (vebusPrefix === "") | |
663 vebusPrefix = service.name; | |
664 } | |
665 } | |
666 | |
667 // Check available services to find tank sesnsors | |
668 function discoverMulti() | |
669 { | |
670 for (var i = 0; i < DBusServices.count; i++) { | |
671 if (DBusServices.at(i).type === DBusService.DBUS_SERVICE_MULTI) { | |
672 addService(DBusServices.at(i)) | |
673 } | |
674 } | |
675 } | |
676 | |
677 function notificationText() | |
678 { | |
679 if (activeNotifications.length === 0) | |
680 return qsTr("no alarms") | |
681 | |
682 var descr = [] | |
683 for (var n = 0; n < activeNotifications.length; n++) { | |
684 var notification = activeNotifications[n]; | |
685 | |
686 var text = notification.serviceName + " - " + notification.description; | |
687 if (notification.value !== "" ) | |
688 text += ": " + notification.value | |
689 | |
690 descr.push(text) | |
691 } | |
692 | |
693 return descr.join(" | ") | |
694 } | |
695 | |
696 VBusItem { id: dmc; bind: Utils.path(vebusPrefix, "/Devices/Dmc/Version") } | |
697 VBusItem { id: bms; bind: Utils.path(vebusPrefix, "/Devices/Bms/Version") } | |
698 } |