diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 11caee45..00000000 Binary files a/.DS_Store and /dev/null differ diff --git a/angular-client/src/app/app.module.ts b/angular-client/src/app/app.module.ts index 3f989e53..fd70e4d8 100644 --- a/angular-client/src/app/app.module.ts +++ b/angular-client/src/app/app.module.ts @@ -80,7 +80,6 @@ import { SwitchComponent } from 'src/components/switch/switch.component'; import { DoubleLineGraphComponent } from 'src/components/double-line-graph/double-line-graph.component'; import BatteryInfoDesktop from 'src/pages/charging-page/components/battery-info-display/battery-info-desktop/battery-info-desktop.component'; import BatteryInfoMobile from 'src/pages/charging-page/components/battery-info-display/battery-info-mobile/battery-info-mobile.component'; -import BatteryStatusDisplay from 'src/pages/charging-page/components/battery-status-display/battery-status-display.component'; import StateOfChargeDisplay from 'src/pages/charging-page/components/state-of-charge/state-of-charge-display/state-of-charge-display.component'; import PackTemp from 'src/pages/charging-page/components/pack-temp/pack-temp.component'; import CellTempDisplay from 'src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component'; @@ -92,9 +91,19 @@ import HighLowCellDisplay from 'src/pages/charging-page/components/high-low-cell import HighLowCellGraph from 'src/pages/charging-page/components/high-low-cell/high-low-cell-graph/high-low-cell-graph.component'; import PackVoltageGraph from 'src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component'; import PackVoltageDisplay from 'src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component'; -import ChargingStateComponent from 'src/pages/charging-page/components/charging-state/charging-state.component'; +import ChargingStatusComponent from 'src/pages/charging-page/components/charging-state/charging-status.component'; import { BatteryPercentageComponent } from 'src/pages/charging-page/components/battery-percentage/battery-percentage.component'; import { BatteryInfoDisplay } from 'src/pages/charging-page/components/battery-info-display/battery-info-display'; +import StartingSocTimer from 'src/pages/charging-page/components/starting-soc/starting-soc-timer.component'; +import CurrentTotalTimer from 'src/components/current-total-timer/current-total-timer.component'; +import BalancingStatus from 'src/pages/charging-page/components/balancing-status/balancing-status.component'; +import FaultedStatus from 'src/pages/charging-page/components/faulted-status/faulted-status.component'; +import ActiveStatus from 'src/pages/charging-page/components/active-status/active-status.component'; +import CombinedStatusDisplay from 'src/pages/charging-page/components/combined-status-display/combined-status-display.component'; +import CombinedStatusMobile from 'src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component'; +import PackVoltageMobileDisplay from 'src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component'; +import HighLowCellMobile from 'src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component'; +import CellTempMobile from 'src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component'; @NgModule({ declarations: [ @@ -159,7 +168,7 @@ import { BatteryInfoDisplay } from 'src/pages/charging-page/components/battery-i BatteryInfoMobile, NodeFilterPipe, DataTypeFilterPipe, - BatteryStatusDisplay, + CombinedStatusDisplay, StateOfChargeDisplay, PackTemp, CellTempDisplay, @@ -173,7 +182,16 @@ import { BatteryInfoDisplay } from 'src/pages/charging-page/components/battery-i HighLowCellGraph, PackVoltageGraph, PackVoltageDisplay, - ChargingStateComponent + ChargingStatusComponent, + StartingSocTimer, + CurrentTotalTimer, + BalancingStatus, + FaultedStatus, + ActiveStatus, + CombinedStatusMobile, + PackVoltageMobileDisplay, + HighLowCellMobile, + CellTempMobile ], bootstrap: [AppContext], imports: [ @@ -244,6 +262,11 @@ export class AppModule { .addSvgIcon('thermostat', this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/thermostat.svg')) .addSvgIcon('model_training', this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/model_training.svg')) .addSvgIcon('quickreply', this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/quickreply.svg')) - .addSvgIcon('bolt', this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/bolt.svg')); + .addSvgIcon('bolt', this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/bolt.svg')) + .addSvgIcon('timer', this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/timer.svg')) + .addSvgIcon( + 'arrow_drop_down_circle', + this.domSanitizer.bypassSecurityTrustResourceUrl('../assests/icons/arrow_drop_down_circle.svg') + ); } } diff --git a/angular-client/src/assets/icons/timer.svg b/angular-client/src/assets/icons/timer.svg new file mode 100644 index 00000000..6a08fce5 --- /dev/null +++ b/angular-client/src/assets/icons/timer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/angular-client/src/components/current-total-timer/current-total-timer.component.css b/angular-client/src/components/current-total-timer/current-total-timer.component.css new file mode 100644 index 00000000..e69de29b diff --git a/angular-client/src/components/current-total-timer/current-total-timer.component.html b/angular-client/src/components/current-total-timer/current-total-timer.component.html new file mode 100644 index 00000000..ba85c731 --- /dev/null +++ b/angular-client/src/components/current-total-timer/current-total-timer.component.html @@ -0,0 +1,22 @@ + +
+ + + + + + + + + + +
+
diff --git a/angular-client/src/components/current-total-timer/current-total-timer.component.ts b/angular-client/src/components/current-total-timer/current-total-timer.component.ts new file mode 100644 index 00000000..859cae53 --- /dev/null +++ b/angular-client/src/components/current-total-timer/current-total-timer.component.ts @@ -0,0 +1,35 @@ +import { Component, Input } from '@angular/core'; +import Storage from 'src/services/storage.service'; + +@Component({ + selector: 'current-total-timer', + templateUrl: './current-total-timer.component.html', + styleUrls: ['./current-total-timer.component.css'] +}) +export default class CurrentTotalTimer { + @Input() currentTime: number = 0; + @Input() totalTime: number = 0; + + constructor(private storage: Storage) {} + + getCurrentTime() { + return this.formatTime(this.currentTime); + } + + getTotalTime() { + return this.formatTime(this.totalTime); + } + + /** + * Formats the given time. + * + * @param time the time to format. + * @returns the time as a string in the given format: 00:00 (leading zeros included). + */ + formatTime(time: number) { + const minutes = Math.floor(time / 60); + const seconds = time % 60; + + return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; + } +} diff --git a/angular-client/src/components/double-line-graph/double-line-graph.component.ts b/angular-client/src/components/double-line-graph/double-line-graph.component.ts index 63975cda..c5bb3aae 100644 --- a/angular-client/src/components/double-line-graph/double-line-graph.component.ts +++ b/angular-client/src/components/double-line-graph/double-line-graph.component.ts @@ -47,9 +47,13 @@ export class DoubleLineGraphComponent implements OnInit { @Input() title2?: string; @Input() header?: string; @Input() graphContainerId!: string; + @Input({ required: false }) timeRangeSec!: number; options!: ChartOptions; chart!: ApexCharts; series: ApexAxisChartSeries = []; + timeDiffMs: number = 0; + isSliding: boolean = false; + timeRangeMs: number = 120000; // 2 minutes in ms constructor(public dialogService: DialogService) {} @@ -68,20 +72,39 @@ export class DoubleLineGraphComponent implements OnInit { this.series = [ { name: this.title1, - data: this.data1 + data: Array.from(this.data1) }, { name: this.title2, - data: this.data2 + data: Array.from(this.data2) } ]; + // temp fix, for now just basing change on data1 length... + // even though probably should check data1 also + if (!this.isSliding && this.data1.length > 2) { + this.timeDiffMs = this.data1[this.data1.length - 1].x - this.data1[0].x; + } + + if (!this.isSliding && this.timeDiffMs > this.timeRangeMs) { + this.isSliding = true; + this.chart.updateOptions({ + ...this.options, + xaxis: { + ...this.options.xaxis, + range: this.timeRangeMs + } + }); + } + this.chart.updateSeries(this.series); setTimeout(() => { this.updateChart(); - }, 1000); + }, 800); }; ngOnInit(): void { + this.timeRangeMs = (this.timeRangeSec ?? 120) * 1000; + this.series = [ { name: this.title1, diff --git a/angular-client/src/components/graph/graph.component.ts b/angular-client/src/components/graph/graph.component.ts index aa4cac14..58d1d64a 100644 --- a/angular-client/src/components/graph/graph.component.ts +++ b/angular-client/src/components/graph/graph.component.ts @@ -51,7 +51,7 @@ export class GraphComponent implements OnInit { updateChart = () => { this.chart.updateSeries([ { - name: 'Data Series', + name: this.title, data: Array.from(this.data) } ]); diff --git a/angular-client/src/components/info-background/info-background.component.html b/angular-client/src/components/info-background/info-background.component.html index 76814958..2107c29a 100644 --- a/angular-client/src/components/info-background/info-background.component.html +++ b/angular-client/src/components/info-background/info-background.component.html @@ -6,7 +6,13 @@
- +
- - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/angular-client/src/pages/charging-page/charging-page-mobile/charging-page-mobile.component.ts b/angular-client/src/pages/charging-page/charging-page-mobile/charging-page-mobile.component.ts index 56bdcc74..4e96eede 100644 --- a/angular-client/src/pages/charging-page/charging-page-mobile/charging-page-mobile.component.ts +++ b/angular-client/src/pages/charging-page/charging-page-mobile/charging-page-mobile.component.ts @@ -11,7 +11,7 @@ export default class ChargingPageMobile { @Input() time = new Date(); location: string = 'No Location Set'; constructor(private storage: Storage) {} - mobileThreshold = 1000; + mobileThreshold = 1070; isMobile = window.innerWidth < this.mobileThreshold; ngOnInit() { diff --git a/angular-client/src/pages/charging-page/charging-page.component.html b/angular-client/src/pages/charging-page/charging-page.component.html index 19209636..a0f6fcb4 100644 --- a/angular-client/src/pages/charging-page/charging-page.component.html +++ b/angular-client/src/pages/charging-page/charging-page.component.html @@ -17,29 +17,20 @@ /> - - - - - - - - - - - - - -
- - - - - - -
-
-
+ + + + + + + + + + + + + + diff --git a/angular-client/src/pages/charging-page/charging-page.component.ts b/angular-client/src/pages/charging-page/charging-page.component.ts index 56689a3a..405374ea 100644 --- a/angular-client/src/pages/charging-page/charging-page.component.ts +++ b/angular-client/src/pages/charging-page/charging-page.component.ts @@ -14,7 +14,7 @@ export default class ChargingPage implements OnInit { time = new Date(); location: string = 'No Location Set'; constructor(private storage: Storage) {} - mobileThreshold = 1000; + mobileThreshold = 1070; isMobile = window.innerWidth < this.mobileThreshold; ngOnInit() { diff --git a/angular-client/src/pages/charging-page/components/active-status/active-status.component.css b/angular-client/src/pages/charging-page/components/active-status/active-status.component.css new file mode 100644 index 00000000..2783a6a3 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/active-status/active-status.component.css @@ -0,0 +1,7 @@ +.connection-dot { + background-color: #2c2c2c; + border: 3px solid; + width: 40px; + height: 40px; + border-radius: 50%; +} diff --git a/angular-client/src/pages/charging-page/components/active-status/active-status.component.html b/angular-client/src/pages/charging-page/components/active-status/active-status.component.html new file mode 100644 index 00000000..25cad486 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/active-status/active-status.component.html @@ -0,0 +1,16 @@ + + + +
+
+
+
+
diff --git a/angular-client/src/pages/charging-page/components/active-status/active-status.component.ts b/angular-client/src/pages/charging-page/components/active-status/active-status.component.ts new file mode 100644 index 00000000..2bbce720 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/active-status/active-status.component.ts @@ -0,0 +1,53 @@ +import { Component } from '@angular/core'; +import Storage from 'src/services/storage.service'; +import Theme from 'src/services/theme.service'; +import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; +import { floatPipe } from 'src/utils/pipes.utils'; + +@Component({ + selector: 'active-status', + templateUrl: './active-status.component.html', + styleUrls: ['./active-status.component.css'] +}) +export default class ActiveStatus { + isActive: boolean = false; + currentSeconds: number = 0; + totalSeconds: number = Number(sessionStorage.getItem('active-total-seconds')) || 0; + intervalId!: NodeJS.Timeout; + constructor(private storage: Storage) {} + + ngOnInit() { + this.storage.get(IdentifierDataType.BMS_MODE).subscribe((value) => { + const statusStateValue = floatPipe(value.values[0]); + if (this.isActive) { + if (!(statusStateValue === 2)) { + this.isActive = false; + this.stopTimer(); + this.resetCurrentSecs(); + } + } else if (statusStateValue === 2) { + this.isActive = true; + this.startTimer(); + } + }); + } + + startTimer() { + this.intervalId = setInterval(() => { + this.currentSeconds++; + this.totalSeconds++; + sessionStorage.setItem('active-total-seconds', this.totalSeconds.toString()); + }, 1000); + } + + stopTimer() { + clearInterval(this.intervalId); + } + + resetCurrentSecs() { + this.currentSeconds = 0; + } + getStatusColor(isActive: boolean) { + return isActive ? 'green' : Theme.infoBackground; + } +} diff --git a/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.css b/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.css new file mode 100644 index 00000000..2783a6a3 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.css @@ -0,0 +1,7 @@ +.connection-dot { + background-color: #2c2c2c; + border: 3px solid; + width: 40px; + height: 40px; + border-radius: 50%; +} diff --git a/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.html b/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.html new file mode 100644 index 00000000..e00c2500 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.html @@ -0,0 +1,16 @@ + + + +
+
+
+
+
diff --git a/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.ts b/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.ts new file mode 100644 index 00000000..ae0cc038 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/balancing-status/balancing-status.component.ts @@ -0,0 +1,58 @@ +import { Component } from '@angular/core'; +import Storage from 'src/services/storage.service'; +import Theme from 'src/services/theme.service'; +import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; +import { floatPipe } from 'src/utils/pipes.utils'; + +@Component({ + selector: 'balancing-status', + templateUrl: './balancing-status.component.html', + styleUrls: ['./balancing-status.component.css'] +}) +export default class BalancingStatus { + isBalancing: boolean = false; + currentSeconds: number = 0; + totalSeconds: number = Number(sessionStorage.getItem('balancing-total-seconds')) || 0; + intervalId!: NodeJS.Timeout; + constructor(private storage: Storage) {} + + ngOnInit() { + this.storage.get(IdentifierDataType.STATUS_BALANCING).subscribe((value) => { + const statusBalancingValue = floatPipe(value.values[0]); + if (this.isBalancing) { + if (!(statusBalancingValue === 1)) { + this.isBalancing = false; + this.stopTimer(); + this.resetCurrentSecs(); + } + } else if (statusBalancingValue === 1) { + this.isBalancing = true; + this.startTimer(); + } + }); + } + + startTimer() { + this.intervalId = setInterval(() => { + this.currentSeconds++; + this.totalSeconds++; + sessionStorage.setItem('balancing-total-seconds', this.totalSeconds.toString()); + }, 1000); + } + + stopTimer() { + clearInterval(this.intervalId); + } + + resetCurrentSecs() { + this.currentSeconds = 0; + } + + getBatteryStatus(connected: boolean) { + return connected ? 'BALANCING' : 'NOT BALANCING'; + } + + getStatusColor(isBalancing: boolean) { + return isBalancing ? 'blue' : Theme.infoBackground; + } +} diff --git a/angular-client/src/pages/charging-page/components/battery-current/current-display/current-display.component.html b/angular-client/src/pages/charging-page/components/battery-current/current-display/current-display.component.html index ec23472e..5e29a5e1 100644 --- a/angular-client/src/pages/charging-page/components/battery-current/current-display/current-display.component.html +++ b/angular-client/src/pages/charging-page/components/battery-current/current-display/current-display.component.html @@ -1,6 +1,6 @@
- - + +
diff --git a/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.html b/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.html deleted file mode 100644 index 3ff24e66..00000000 --- a/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.html +++ /dev/null @@ -1,8 +0,0 @@ - -
- -
- -
-
-
diff --git a/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.ts b/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.ts deleted file mode 100644 index 696c225a..00000000 --- a/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Component } from '@angular/core'; -import Storage from 'src/services/storage.service'; -import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; -import { floatPipe } from 'src/utils/pipes.utils'; - -@Component({ - selector: 'battery-status-display', - templateUrl: './battery-status-display.component.html', - styleUrls: ['./battery-status-display.component.css'] -}) -export default class BatteryStatusDisplay { - isBalancing: boolean = false; - constructor(private storage: Storage) {} - - ngOnInit() { - this.storage.get(IdentifierDataType.STATUS).subscribe((value) => { - this.isBalancing = floatPipe(value.values[0]) === 1; - }); - } - - getBatteryStatus(connected: boolean) { - return connected ? 'BALANCING' : 'NOT BALANCING'; - } - - getStatusColor(isBalancing: boolean) { - return isBalancing ? 'green' : 'red'; - } -} diff --git a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.html b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.html index eb1110cd..7364d816 100644 --- a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.html +++ b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.html @@ -1,24 +1,26 @@ - + - - - - + + - - - - + + - + or just don't enforce --> + + diff --git a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.ts b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.ts index 98144964..5cc41734 100644 --- a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.ts +++ b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-display.component.ts @@ -1,7 +1,8 @@ -import { Component } from '@angular/core'; +import { Component, HostListener } from '@angular/core'; import Storage from 'src/services/storage.service'; import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; -import { floatPipe } from 'src/utils/pipes.utils'; +import { decimalPipe, floatPipe } from 'src/utils/pipes.utils'; +import { GraphData } from 'src/utils/types.utils'; @Component({ selector: 'cell-temp-display', @@ -11,20 +12,27 @@ import { floatPipe } from 'src/utils/pipes.utils'; export default class CellTempDisplay { avgTemp: number = 0; maxTemp: number = 0; + resetGraphButton = { + onClick: () => { + this.cellTempData = []; + }, + icon: 'restart_alt' + }; + cellTempData: GraphData[] = []; + mobileThreshold = 1070; + isDesktop = window.innerWidth > this.mobileThreshold; - // -------- Commented out for now, until mobile view is implemented -----// - // mobileThreshold = 1000; - // isDesktop = window.innerWidth > this.mobileThreshold; - // @HostListener('window:resize', ['$event']) - // onResize() { - // this.isDesktop = window.innerWidth >= this.mobileThreshold; - // } + @HostListener('window:resize', ['$event']) + onResize() { + this.isDesktop = window.innerWidth >= this.mobileThreshold; + } constructor(private storage: Storage) {} ngOnInit() { this.storage.get(IdentifierDataType.CELL_TEMP_HIGH).subscribe((value) => { this.maxTemp = floatPipe(value.values[0]); + this.cellTempData.push({ x: decimalPipe(value.time), y: this.maxTemp }); }); this.storage.get(IdentifierDataType.CELL_TEMP_AVG).subscribe((value) => { this.avgTemp = floatPipe(value.values[0]); diff --git a/angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.css b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.css similarity index 100% rename from angular-client/src/pages/charging-page/components/battery-status-display/battery-status-display.component.css rename to angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.css diff --git a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.html b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.html new file mode 100644 index 00000000..edb2e720 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.html @@ -0,0 +1,22 @@ + +
+ + + + + + + +
+ + +
+ + + + + +
+ +
+
diff --git a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.ts b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.ts new file mode 100644 index 00000000..dd53c284 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-display/cell-temp-mobile/cell-temp-mobile.component.ts @@ -0,0 +1,24 @@ +import { Component, Input } from '@angular/core'; +import Storage from 'src/services/storage.service'; + +import { GraphData } from 'src/utils/types.utils'; + +@Component({ + selector: 'cell-temp-mobile', + templateUrl: './cell-temp-mobile.component.html', + styleUrls: ['./cell-temp-mobile.component.css'] +}) +export default class CellTempMobile { + @Input() avgTemp: number = 0; + @Input() maxTemp: number = 0; + @Input() resetGraphButton = { + onClick: () => { + this.cellTempData = []; + }, + icon: 'restart_alt' + }; + @Input() cellTempData: GraphData[] = []; + constructor(private storage: Storage) {} + + ngOnInit() {} +} diff --git a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.html b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.html index 5a79bf4b..d3063595 100644 --- a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.html +++ b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.html @@ -1,8 +1,7 @@ - +> diff --git a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.ts b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.ts index 8d0e8725..fe31f261 100644 --- a/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.ts +++ b/angular-client/src/pages/charging-page/components/cell-temp/cell-temp-graph/cell-temp-graph.component.ts @@ -1,6 +1,5 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import Storage from 'src/services/storage.service'; -import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; import { GraphData } from 'src/utils/types.utils'; @Component({ @@ -9,16 +8,7 @@ import { GraphData } from 'src/utils/types.utils'; styleUrls: ['./cell-temp-graph.component.css'] }) export default class CellTempGraph implements OnInit { - cellTempData: GraphData[] = []; - maxDataPoints = 100; - + @Input() maxCellTempData: GraphData[] = []; constructor(private storage: Storage) {} - ngOnInit() { - this.storage.get(IdentifierDataType.CELL_TEMP_HIGH).subscribe((value) => { - this.cellTempData.push({ x: new Date().getTime(), y: parseInt(value.values[0]) }); - if (this.cellTempData.length >= 100) { - this.cellTempData.shift(); - } - }); - } + ngOnInit() {} } diff --git a/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.html b/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.html deleted file mode 100644 index 8a6c24fc..00000000 --- a/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.html +++ /dev/null @@ -1,8 +0,0 @@ - -
- -
- -
-
-
diff --git a/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.ts b/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.ts deleted file mode 100644 index f460728d..00000000 --- a/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Component } from '@angular/core'; -import Storage from 'src/services/storage.service'; -import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; -import { floatPipe } from 'src/utils/pipes.utils'; - -@Component({ - selector: 'charging-state', - templateUrl: './charging-state.component.html', - styleUrls: ['./charging-state.component.css'] -}) -export default class ChargingStateComponent { - isCharging: boolean = false; - timer: number = 0; - timerInterval: any; - - constructor(private storage: Storage) {} - - ngOnInit() { - this.startTimer(); - this.storage.get(IdentifierDataType.CHARGING).subscribe((value) => { - const newChargingState = floatPipe(value.values[0]) === 1; - - if (this.isCharging !== newChargingState) { - this.resetTimer(); - if (newChargingState) { - this.startTimer(); - } - } - - this.isCharging = newChargingState; - }); - } - - getChargingState(connected: boolean) { - return connected ? 'PAUSED' : 'NOT PAUSED'; - } - - getStateColor(isCharging: boolean) { - return isCharging ? 'green' : 'red'; - } - - startTimer() { - this.timerInterval = setInterval(() => { - this.timer++; - }, 1000); - } - - resetTimer() { - clearInterval(this.timerInterval); - this.timer = 0; - } - - getTimerInfo() { - const minutes = Math.floor(this.timer / 60); - const seconds = this.timer % 60; - return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; - } -} diff --git a/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.css b/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.css similarity index 60% rename from angular-client/src/pages/charging-page/components/charging-state/charging-state.component.css rename to angular-client/src/pages/charging-page/components/charging-state/charging-status.component.css index 38059d73..c4a9a4da 100644 --- a/angular-client/src/pages/charging-page/components/charging-state/charging-state.component.css +++ b/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.css @@ -1,8 +1,9 @@ .connection-dot { - width: 50px; - height: 50px; + background-color: #2c2c2c; + border: 3px solid; + width: 40px; + height: 40px; border-radius: 50%; - margin-top: 20px; } .typography-centered { diff --git a/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.html b/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.html new file mode 100644 index 00000000..37974bc4 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.html @@ -0,0 +1,16 @@ + + + +
+
+
+
+
diff --git a/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.ts b/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.ts new file mode 100644 index 00000000..84b4093c --- /dev/null +++ b/angular-client/src/pages/charging-page/components/charging-state/charging-status.component.ts @@ -0,0 +1,59 @@ +import { Component } from '@angular/core'; +import Storage from 'src/services/storage.service'; +import Theme from 'src/services/theme.service'; +import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; +import { floatPipe } from 'src/utils/pipes.utils'; + +@Component({ + selector: 'charging-status', + templateUrl: './charging-status.component.html', + styleUrls: ['./charging-status.component.css'] +}) +export default class ChargingStatusComponent { + isCharging: boolean = false; + currentSeconds: number = 0; + totalSeconds: number = Number(sessionStorage.getItem('charging-total-seconds')) || 0; + intervalId!: NodeJS.Timeout; + + constructor(private storage: Storage) {} + + ngOnInit() { + this.storage.get(IdentifierDataType.CHARGING).subscribe((value) => { + const chargingControlValue = floatPipe(value.values[0]); + if (this.isCharging) { + if (chargingControlValue === 1) { + this.isCharging = false; + this.stopTimer(); + this.resetCurrentSecs(); + } + } else if (chargingControlValue === 0) { + this.isCharging = true; + this.startTimer(); + } + }); + } + + startTimer() { + this.intervalId = setInterval(() => { + this.currentSeconds++; + this.totalSeconds++; + sessionStorage.setItem('charging-total-seconds', this.totalSeconds.toString()); + }, 1000); + } + + stopTimer() { + clearInterval(this.intervalId); + } + + resetCurrentSecs() { + this.currentSeconds = 0; + } + + getChargingState(connected: boolean) { + return connected ? 'PAUSED' : 'NOT PAUSED'; + } + + getStateColor(isCharging: boolean) { + return isCharging ? 'yellow' : Theme.infoBackground; + } +} diff --git a/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.css b/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.css new file mode 100644 index 00000000..2783a6a3 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.css @@ -0,0 +1,7 @@ +.connection-dot { + background-color: #2c2c2c; + border: 3px solid; + width: 40px; + height: 40px; + border-radius: 50%; +} diff --git a/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.html b/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.html new file mode 100644 index 00000000..fa0c10f0 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.html @@ -0,0 +1,13 @@ + +
+ + + + + + + + + +
+
diff --git a/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.ts b/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.ts new file mode 100644 index 00000000..b8146fac --- /dev/null +++ b/angular-client/src/pages/charging-page/components/combined-status-display/combined-status-display.component.ts @@ -0,0 +1,16 @@ +import { Component, HostListener } from '@angular/core'; + +@Component({ + selector: 'combined-status-display', + templateUrl: './combined-status-display.component.html', + styleUrls: ['./combined-status-display.component.css'] +}) +export default class CombinedStatusDisplay { + mobileThreshold = 1070; + isMobile = window.innerWidth < this.mobileThreshold; + + @HostListener('window:resize', ['$event']) + onResize() { + this.isMobile = window.innerWidth <= this.mobileThreshold; + } +} diff --git a/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.css b/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.css new file mode 100644 index 00000000..2783a6a3 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.css @@ -0,0 +1,7 @@ +.connection-dot { + background-color: #2c2c2c; + border: 3px solid; + width: 40px; + height: 40px; + border-radius: 50%; +} diff --git a/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.html b/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.html new file mode 100644 index 00000000..e2e50ee3 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.ts b/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.ts new file mode 100644 index 00000000..562a046e --- /dev/null +++ b/angular-client/src/pages/charging-page/components/combined-status-display/mobile-view/combined-status-mobile.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'combined-status-mobile', + templateUrl: './combined-status-mobile.component.html', + styleUrls: ['./combined-status-mobile.component.css'] +}) +export default class CombinedStatusMobile {} diff --git a/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.css b/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.css index d7e78752..07b6e76e 100644 --- a/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.css +++ b/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.css @@ -3,6 +3,5 @@ display: flex; align-items: left; justify-content: left; - padding-left: 10%; overflow-y: auto; } diff --git a/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.html b/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.html index fafc8612..4f984ebb 100644 --- a/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.html +++ b/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.html @@ -1,17 +1,25 @@ -
+
- - +
+ + + +
diff --git a/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.ts b/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.ts index 45c56fd6..ce9a425a 100644 --- a/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.ts +++ b/angular-client/src/pages/charging-page/components/fault-display/fault-display.component.ts @@ -2,13 +2,40 @@ import { Component } from '@angular/core'; import Storage from 'src/services/storage.service'; import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; +enum BMS_FAULTS_TYPES { + CELLS_NOT_BALANCING = 1, + CELL_VOLTAGE_TOO_LOW = 2, + CELL_VOLTAGE_TOO_HIGH = 4, + PACK_TOO_HOT = 8, + OPEN_WIRING_FAULT = 16, + INTERNAL_SOFTWARE_FAULT = 32, + INTERNAL_THERMAL_ERROR = 64, + INTERNAL_CELL_COMM_FAULT = 128, + CURRENT_SENSOR_FAULT = 256, + CHARGE_READING_MISMATCH = 512, + LOW_CELL_VOLTAGE = 1024, + WEAK_PACK_FAULT = 2048, + EXTERNAL_CAN_FAULT = 4096, + DISCHARGE_LIMIT_ENFORCEMENT_FAULT = 8192, + CHARGER_SAFETY_RELAY = 16384, + BATTERY_THERMISTOR = 32768, + CHARGER_CAN_FAULT = 65536, + CHARGER_LIMIT_ENFORCEMENT_FAULT = 131072 +} + +enum FaultType { + BMS = 'BMS', + Charger = 'Charger' +} + @Component({ selector: 'fault-display', templateUrl: './fault-display.component.html', styleUrls: ['./fault-display.component.css'] }) export default class FaultDisplay { - faults: { faultName: string; time: string }[] = []; + faults: { type: string; name: string; time: string }[] = []; + faultsShifted: boolean = false; resetButton = { onClick: () => { this.faults = []; @@ -19,27 +46,31 @@ export default class FaultDisplay { ngOnInit() { this.storage.get(IdentifierDataType.COMM_TIMEOUT_FAULT).subscribe((value) => { - this.addFault(value.values[0], 'Comm Timeout'); + this.addFault(parseInt(value.values[0]), 'Comm Timeout', FaultType.Charger); }); this.storage.get(IdentifierDataType.HARDWARE_FAILURE_FAULT).subscribe((value) => { - this.addFault(value.values[0], 'Hardware Failure'); + this.addFault(parseInt(value.values[0]), 'Hardware Failure', FaultType.Charger); }); this.storage.get(IdentifierDataType.OVER_TEMP_FAULT).subscribe((value) => { - this.addFault(value.values[0], 'Over Temp'); + this.addFault(parseInt(value.values[0]), 'Over Temp', FaultType.Charger); }); this.storage.get(IdentifierDataType.VOLTAGE_WRONG_FAULT).subscribe((value) => { - this.addFault(value.values[0], 'Voltage Wrong'); + this.addFault(parseInt(value.values[0]), 'Voltage Wrong', FaultType.Charger); }); this.storage.get(IdentifierDataType.WRONG_BAT_CONNECT_FAULT).subscribe((value) => { - this.addFault(value.values[0], 'Wrong Battery Connect'); + this.addFault(parseInt(value.values[0]), 'Wrong Battery Connect', FaultType.Charger); + }); + + this.storage.get(IdentifierDataType.BMS_FAULTS).subscribe((value) => { + const bmsFaultID = parseInt(value.values[0]); + this.addFault(bmsFaultID, this.getBMSFaultName(bmsFaultID), FaultType.BMS); }); } - // /** * Adds the fault name, with the current time to the faults array, if the faultValue is NOT 0. * Shifts through the fault array to keep only the most recent 50 faults. @@ -47,12 +78,81 @@ export default class FaultDisplay { * @param faultValue an string with an integer value. * @param faultName the name of the fault, to be displayed. */ - addFault(faultValue: string, faultName: string) { - if (parseInt(faultValue) !== 0) { + addFault(faultValue: number, faultName: string, faultType: FaultType) { + if (faultValue !== 0) { if (this.faults.length >= 50) { this.faults.pop(); } - this.faults.unshift({ faultName, time: new Date().toLocaleTimeString() }); + this.faultsShifted = !this.faultsShifted; + + this.faults.unshift({ type: faultType, name: faultName, time: new Date().toLocaleTimeString() }); + } + } + + /** + * This is based on the shepard enum for faults: + * https://github.com/Northeastern-Electric-Racing/ShepherdBMS-2/blob/6eb3f863ed131a15bdf98665532cb7807bbd2920/Core/Inc/datastructs.h#L39 + */ + getBMSFaultName(faultValue: number): string { + let faultName = ''; + switch (faultValue) { + case 0: + break; + case BMS_FAULTS_TYPES.CELLS_NOT_BALANCING: + faultName = 'Cells Not Balancing'; + break; + case BMS_FAULTS_TYPES.CELL_VOLTAGE_TOO_LOW: + faultName = 'Cell Voltage too Low'; + break; + case BMS_FAULTS_TYPES.CELL_VOLTAGE_TOO_HIGH: + faultName = 'Cell Voltage too High'; + break; + case BMS_FAULTS_TYPES.PACK_TOO_HOT: + faultName = ' Pack too Hot'; + break; + case BMS_FAULTS_TYPES.OPEN_WIRING_FAULT: + faultName = 'Open Wiring Fault'; + break; + case BMS_FAULTS_TYPES.INTERNAL_SOFTWARE_FAULT: + faultName = 'Internal Software Fault'; + break; + case BMS_FAULTS_TYPES.INTERNAL_THERMAL_ERROR: + faultName = 'Internal Thermal Error'; + break; + case BMS_FAULTS_TYPES.INTERNAL_CELL_COMM_FAULT: + faultName = 'Internal Cell Comm Fault'; + break; + case BMS_FAULTS_TYPES.CURRENT_SENSOR_FAULT: + faultName = 'Current Sensor Fault'; + break; + case BMS_FAULTS_TYPES.CHARGE_READING_MISMATCH: + faultName = 'Charge Reading Mismatch'; + break; + case BMS_FAULTS_TYPES.LOW_CELL_VOLTAGE: + faultName = 'Low Cell Voltage'; + break; + case BMS_FAULTS_TYPES.WEAK_PACK_FAULT: + faultName = 'Weak Pack Fault'; + break; + case BMS_FAULTS_TYPES.EXTERNAL_CAN_FAULT: + faultName = 'External Can Fault'; + break; + case BMS_FAULTS_TYPES.DISCHARGE_LIMIT_ENFORCEMENT_FAULT: + faultName = 'Discharge Limit Enforcement Fault'; + break; + case BMS_FAULTS_TYPES.CHARGER_SAFETY_RELAY: + faultName = 'Charger Safety Relay'; + break; + case BMS_FAULTS_TYPES.BATTERY_THERMISTOR: + faultName = 'Battery Thermistor'; + break; + case BMS_FAULTS_TYPES.CHARGER_CAN_FAULT: + faultName = 'Charger Can Fault'; + break; + case BMS_FAULTS_TYPES.CHARGER_LIMIT_ENFORCEMENT_FAULT: + faultName = 'Charger Limit Enforcement Fault'; + break; } + return faultName; } } diff --git a/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.css b/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.css new file mode 100644 index 00000000..2783a6a3 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.css @@ -0,0 +1,7 @@ +.connection-dot { + background-color: #2c2c2c; + border: 3px solid; + width: 40px; + height: 40px; + border-radius: 50%; +} diff --git a/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.html b/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.html new file mode 100644 index 00000000..a568376c --- /dev/null +++ b/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.html @@ -0,0 +1,16 @@ + + + +
+
+
+
+
diff --git a/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.ts b/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.ts new file mode 100644 index 00000000..9c0820cd --- /dev/null +++ b/angular-client/src/pages/charging-page/components/faulted-status/faulted-status.component.ts @@ -0,0 +1,54 @@ +import { Component } from '@angular/core'; +import Storage from 'src/services/storage.service'; +import Theme from 'src/services/theme.service'; +import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; +import { floatPipe } from 'src/utils/pipes.utils'; + +@Component({ + selector: 'faulted-status', + templateUrl: './faulted-status.component.html', + styleUrls: ['./faulted-status.component.css'] +}) +export default class FaultedStatus { + isFaulted: boolean = false; + currentSeconds: number = 0; + totalSeconds: number = Number(sessionStorage.getItem('faulted-total-seconds')) || 0; + intervalId!: NodeJS.Timeout; + constructor(private storage: Storage) {} + + ngOnInit() { + this.storage.get(IdentifierDataType.BMS_MODE).subscribe((value) => { + const statusStateValue = floatPipe(value.values[0]); + if (this.isFaulted) { + if (!(statusStateValue === 3)) { + this.isFaulted = false; + this.stopTimer(); + this.resetCurrentSecs(); + } + } else if (statusStateValue === 3) { + this.isFaulted = true; + this.startTimer(); + } + }); + } + + startTimer() { + this.intervalId = setInterval(() => { + this.currentSeconds++; + this.totalSeconds++; + sessionStorage.setItem('faulted-total-seconds', this.totalSeconds.toString()); + }, 1000); + } + + stopTimer() { + clearInterval(this.intervalId); + } + + resetCurrentSecs() { + this.currentSeconds = 0; + } + + getStatusColor(isFaulted: boolean) { + return isFaulted ? 'red' : Theme.infoBackground; + } +} diff --git a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.html b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.html index 74aa31c0..9bff7d52 100644 --- a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.html +++ b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.html @@ -1,8 +1,19 @@ - + - + + @@ -11,7 +22,18 @@ - + + @@ -20,13 +42,36 @@ - + + - - - + + + + diff --git a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.ts b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.ts index e1d2786f..6bc3140c 100644 --- a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.ts +++ b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-display.component.ts @@ -2,6 +2,7 @@ import { Component, HostListener } from '@angular/core'; import Storage from 'src/services/storage.service'; import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; import { decimalPipe } from 'src/utils/pipes.utils'; +import { GraphData } from 'src/utils/types.utils'; @Component({ selector: 'high-low-cell-display', @@ -12,8 +13,17 @@ export default class HighLowCellDisplay { delta: number = 0; lowCellVoltage: number = 0; highCellVoltage: number = 0; - mobileThreshold = 1000; + mobileThreshold = 1070; isDesktop = window.innerWidth > this.mobileThreshold; + highVoltsData: GraphData[] = []; + lowVoltsData: GraphData[] = []; + resetGraphButton = { + onClick: () => { + this.highVoltsData = []; + this.lowVoltsData = []; + }, + icon: 'restart_alt' + }; constructor(private storage: Storage) {} @@ -26,10 +36,12 @@ export default class HighLowCellDisplay { this.storage.get(IdentifierDataType.VOLTS_LOW).subscribe((value) => { this.lowCellVoltage = decimalPipe(value.values[0], 3); this.delta = decimalPipe((this.highCellVoltage - this.lowCellVoltage).toFixed(3), 3); + this.lowVoltsData.push({ x: decimalPipe(value.time), y: this.lowCellVoltage }); }); this.storage.get(IdentifierDataType.VOLTS_HIGH).subscribe((value) => { this.highCellVoltage = decimalPipe(value.values[0], 3); this.delta = decimalPipe((this.highCellVoltage - this.lowCellVoltage).toFixed(3), 3); + this.highVoltsData.push({ x: decimalPipe(value.time), y: this.highCellVoltage }); }); } } diff --git a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.css b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.css new file mode 100644 index 00000000..6f62df68 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.css @@ -0,0 +1,6 @@ +.connection-dot { + width: 50px; + height: 50px; + border-radius: 50%; + margin-top: 20px; +} diff --git a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.html b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.html new file mode 100644 index 00000000..3c9809aa --- /dev/null +++ b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.html @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.ts b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.ts new file mode 100644 index 00000000..35d31dd5 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-display/high-low-cell-mobile/high-low-cell-mobile.component.ts @@ -0,0 +1,29 @@ +import { Component, Input } from '@angular/core'; +import Storage from 'src/services/storage.service'; +import { GraphData } from 'src/utils/types.utils'; + +@Component({ + selector: 'high-low-cell-mobile', + templateUrl: './high-low-cell-mobile.component.html', + styleUrls: ['./high-low-cell-mobile.component.css'] +}) +export default class HighLowCellMobile { + @Input() delta: number = 0; + @Input() lowCellVoltage: number = 0; + @Input() highCellVoltage: number = 0; + mobileThreshold = 1070; + isDesktop = window.innerWidth > this.mobileThreshold; + @Input() highVoltsData: GraphData[] = []; + @Input() lowVoltsData: GraphData[] = []; + @Input() resetGraphButton = { + onClick: () => { + this.highVoltsData = []; + this.lowVoltsData = []; + }, + icon: 'restart_alt' + }; + + constructor(private storage: Storage) {} + + ngOnInit() {} +} diff --git a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-graph/high-low-cell-graph.component.ts b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-graph/high-low-cell-graph.component.ts index 44356ed6..e4483ae5 100644 --- a/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-graph/high-low-cell-graph.component.ts +++ b/angular-client/src/pages/charging-page/components/high-low-cell/high-low-cell-graph/high-low-cell-graph.component.ts @@ -1,7 +1,5 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import Storage from 'src/services/storage.service'; -import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; -import { decimalPipe } from 'src/utils/pipes.utils'; import { GraphData } from 'src/utils/types.utils'; @Component({ @@ -10,23 +8,9 @@ import { GraphData } from 'src/utils/types.utils'; styleUrls: ['./high-low-cell-graph.component.css'] }) export default class HighLowCellGraph implements OnInit { - highVoltsData: GraphData[] = []; - lowVoltsData: GraphData[] = []; - maxDataPoints = 100; + @Input() highVoltsData: GraphData[] = []; + @Input() lowVoltsData: GraphData[] = []; constructor(private storage: Storage) {} - ngOnInit() { - this.storage.get(IdentifierDataType.VOLTS_HIGH).subscribe((value) => { - this.highVoltsData.push({ x: new Date().getTime(), y: decimalPipe(value.values[0]) }); - if (this.highVoltsData.length >= 100) { - this.highVoltsData.shift(); - } - }); - this.storage.get(IdentifierDataType.VOLTS_LOW).subscribe((value) => { - this.lowVoltsData.push({ x: new Date().getTime(), y: decimalPipe(value.values[0]) }); - if (this.lowVoltsData.length >= 100) { - this.lowVoltsData.shift(); - } - }); - } + ngOnInit() {} } diff --git a/angular-client/src/pages/charging-page/components/pack-temp/pack-temp.component.html b/angular-client/src/pages/charging-page/components/pack-temp/pack-temp.component.html index bc829247..efee2dff 100644 --- a/angular-client/src/pages/charging-page/components/pack-temp/pack-temp.component.html +++ b/angular-client/src/pages/charging-page/components/pack-temp/pack-temp.component.html @@ -1,8 +1,8 @@ -
+
diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.html b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.html index 29d4324c..e7dfd8b5 100644 --- a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.html +++ b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.html @@ -1,8 +1,9 @@ - + - + - + + diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.ts b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.ts index 617c0233..d3a36636 100644 --- a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.ts +++ b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-display.component.ts @@ -1,7 +1,8 @@ -import { Component } from '@angular/core'; +import { Component, HostListener } from '@angular/core'; import Storage from 'src/services/storage.service'; import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; -import { floatPipe } from 'src/utils/pipes.utils'; +import { decimalPipe, floatPipe } from 'src/utils/pipes.utils'; +import { GraphData } from 'src/utils/types.utils'; @Component({ selector: 'pack-voltage-display', @@ -10,12 +11,27 @@ import { floatPipe } from 'src/utils/pipes.utils'; }) export default class PackVoltageDisplay { voltage: number = 0; + packVoltData: GraphData[] = []; + resetGraphButton = { + onClick: () => { + this.packVoltData = []; + }, + icon: 'restart_alt' + }; + mobileThreshold = 1070; + isDesktop = window.innerWidth > this.mobileThreshold; + + @HostListener('window:resize', ['$event']) + onResize() { + this.isDesktop = window.innerWidth >= this.mobileThreshold; + } constructor(private storage: Storage) {} ngOnInit() { this.storage.get(IdentifierDataType.PACK_VOLTAGE).subscribe((value) => { this.voltage = floatPipe(value.values[0]); + this.packVoltData.push({ x: decimalPipe(value.time), y: this.voltage }); }); } } diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.css b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.css new file mode 100644 index 00000000..e69de29b diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.html b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.html new file mode 100644 index 00000000..f761fded --- /dev/null +++ b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.ts b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.ts new file mode 100644 index 00000000..0857c303 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-display/pack-voltage-mobile/pack-voltage-mobile.component.ts @@ -0,0 +1,22 @@ +import { Component, Input } from '@angular/core'; +import Storage from 'src/services/storage.service'; +import { GraphData } from 'src/utils/types.utils'; + +@Component({ + selector: 'pack-voltage-mobile', + templateUrl: './pack-voltage-mobile.component.html', + styleUrls: ['./pack-voltage-mobile.component.css'] +}) +export default class PackVoltageMobileDisplay { + @Input() voltage: number = 0; + @Input() packVoltData: GraphData[] = []; + resetGraphButton = { + onClick: () => { + this.packVoltData = []; + }, + icon: 'restart_alt' + }; + constructor(private storage: Storage) {} + + ngOnInit() {} +} diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.html b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.html index 6eb1718e..8e3f98a5 100644 --- a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.html +++ b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.html @@ -1,2 +1,2 @@ - + diff --git a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.ts b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.ts index 93503753..0e6d1724 100644 --- a/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.ts +++ b/angular-client/src/pages/charging-page/components/pack-voltage/pack-voltage-graph/pack-voltage-graph.component.ts @@ -1,6 +1,5 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import Storage from 'src/services/storage.service'; -import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; import { GraphData } from 'src/utils/types.utils'; @Component({ @@ -9,16 +8,8 @@ import { GraphData } from 'src/utils/types.utils'; styleUrls: ['./pack-voltage-graph.component.css'] }) export default class PackVoltageGraph implements OnInit { - packVoltData: GraphData[] = []; - maxDataPoints = 100; + @Input() packVoltData: GraphData[] = []; constructor(private storage: Storage) {} - ngOnInit() { - this.storage.get(IdentifierDataType.PACK_VOLTAGE).subscribe((value) => { - this.packVoltData.push({ x: new Date().getTime(), y: parseInt(value.values[0]) }); - if (this.packVoltData.length >= 100) { - this.packVoltData.shift(); - } - }); - } + ngOnInit() {} } diff --git a/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.css b/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.css new file mode 100644 index 00000000..e69de29b diff --git a/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.html b/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.html new file mode 100644 index 00000000..edbb3da1 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.html @@ -0,0 +1,4 @@ + + + + diff --git a/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.ts b/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.ts new file mode 100644 index 00000000..aa0187d5 --- /dev/null +++ b/angular-client/src/pages/charging-page/components/starting-soc/starting-soc-timer.component.ts @@ -0,0 +1,22 @@ +import { Component } from '@angular/core'; +import { take } from 'rxjs'; +import Storage from 'src/services/storage.service'; +import { IdentifierDataType } from 'src/utils/enumerations/identifier-data-type'; +import { floatPipe } from 'src/utils/pipes.utils'; + +@Component({ + selector: 'starting-soc-timer', + templateUrl: './starting-soc-timer.component.html', + styleUrls: ['./starting-soc-timer.component.css'] +}) +export default class StartingSocTimer { + startingSoc: number = 0; + constructor(private storage: Storage) { + this.storage + .get(IdentifierDataType.STATE_OF_CHARGE) + .pipe(take(1)) + .subscribe((value) => { + this.startingSoc = floatPipe(value.values[0]); + }); + } +} diff --git a/angular-client/src/pages/charging-page/components/state-of-charge/state-of-charge-display/state-of-charge-display.component.html b/angular-client/src/pages/charging-page/components/state-of-charge/state-of-charge-display/state-of-charge-display.component.html index e4bc6c3f..158541b5 100644 --- a/angular-client/src/pages/charging-page/components/state-of-charge/state-of-charge-display/state-of-charge-display.component.html +++ b/angular-client/src/pages/charging-page/components/state-of-charge/state-of-charge-display/state-of-charge-display.component.html @@ -1,9 +1,9 @@ - + - +
- - + +
diff --git a/angular-client/src/pages/landing-page/landing-page.component.ts b/angular-client/src/pages/landing-page/landing-page.component.ts index 1efe7598..13f15da1 100644 --- a/angular-client/src/pages/landing-page/landing-page.component.ts +++ b/angular-client/src/pages/landing-page/landing-page.component.ts @@ -17,7 +17,7 @@ export default class LandingPage implements OnInit { time = new Date(); location: string = 'No Location Set'; newRunIsLoading = false; - mobileThreshold = 1000; + mobileThreshold = 1070; isMobile = window.innerWidth < this.mobileThreshold; constructor( diff --git a/angular-client/src/utils/enumerations/identifier-data-type.ts b/angular-client/src/utils/enumerations/identifier-data-type.ts index f2996d9f..ef71be97 100644 --- a/angular-client/src/utils/enumerations/identifier-data-type.ts +++ b/angular-client/src/utils/enumerations/identifier-data-type.ts @@ -17,6 +17,7 @@ export enum IdentifierDataType { OVER_TEMP_FAULT = 'Box-F_OverTemp', VOLTAGE_WRONG_FAULT = 'Box-F_OverVoltage', WRONG_BAT_CONNECT_FAULT = 'Box-F_WrongBatConnect', + BMS_FAULTS = 'Status-Faults', VIEWERS = 'Viewers', SPEED = 'State-Speed', TORQUE = 'Torque', @@ -30,7 +31,7 @@ export enum IdentifierDataType { CHARGE_CURRENT_LIMIT = 'Pack-CCL', DISCHARGE_CURRENT_LIMIT = 'Pack-DCL', XYZAccel = 'XYZAcceleration', - STATUS = 'Status-Balancing', + STATUS_BALANCING = 'Status-Balancing', BMS_MODE = 'Status-State', VOLTS_HIGH = 'Cells-Volts_High_Value', VOLTS_LOW = 'Cells-Volts_Low_Value', diff --git a/scylla-server-typescript/src/socket/mock-proxy-client.ts b/scylla-server-typescript/src/socket/mock-proxy-client.ts index ebdc7e94..6bc4c97b 100644 --- a/scylla-server-typescript/src/socket/mock-proxy-client.ts +++ b/scylla-server-typescript/src/socket/mock-proxy-client.ts @@ -32,7 +32,7 @@ const baseMockData: MockData[] = [ max: 100 }, { - name: DataType.STATUS, + name: DataType.STATUS_BALANCING, unit: Unit.BINARY, vals: [0], min: 0, @@ -227,6 +227,13 @@ const baseMockData: MockData[] = [ vals: [0], min: 0, max: 1 + }, + { + name: DataType.BMS_FAULTS, + unit: Unit.HEX, + vals: [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072], + min: 0, + max: 131072 } ]; @@ -278,7 +285,7 @@ export default class MockProxyClient implements ProxyClient { return new Promise((resolve) => setTimeout(() => { resolve('loop'); - }, 1) + }, 10) ); }; @@ -297,11 +304,16 @@ export default class MockProxyClient implements ProxyClient { index = this.getRandomIndex(this.mockData.length); numericalData = this.mockData[index]; - for (const val in numericalData.vals) { - if (numericalData.vals.hasOwnProperty(val)) { - let newVal = numericalData.vals[val] + Math.random() * 2 - 1; - newVal = Math.max(numericalData.min, Math.min(numericalData.max, newVal)); - numericalData.vals[val] = newVal; + // if more than one value is given in the numerical data, it is assumed that only those values should be choosen from. + if (numericalData.vals.length > 1) { + numericalData.vals[0] = numericalData.vals[this.getRandomIndex(numericalData.vals.length)]; + } else { + for (const val in numericalData.vals) { + if (numericalData.vals.hasOwnProperty(val)) { + let newVal = numericalData.vals[val] + Math.random() * 2 - 1; + newVal = Math.max(numericalData.min, Math.min(numericalData.max, newVal)); + numericalData.vals[val] = newVal; + } } } diff --git a/scylla-server-typescript/src/utils/data.utils.ts b/scylla-server-typescript/src/utils/data.utils.ts index f2ef63a2..82247c8d 100644 --- a/scylla-server-typescript/src/utils/data.utils.ts +++ b/scylla-server-typescript/src/utils/data.utils.ts @@ -17,6 +17,7 @@ export enum DataType { OVER_TEMP_FAULT = 'Box-F_OverTemp', VOLTAGE_WRONG_FAULT = 'Box-F_OverVoltage', WRONG_BAT_CONNECT_FAULT = 'Box-F_WrongBatConnect', + BMS_FAULTS = 'Status-Faults', VIEWERS = 'Viewers', SPEED = 'State-Speed', TORQUE = 'Torque', @@ -30,7 +31,7 @@ export enum DataType { CHARGE_CURRENT_LIMIT = 'Pack-CCL', DISCHARGE_CURRENT_LIMIT = 'Pack-DCL', XYZAccel = 'XYZAcceleration', - STATUS = 'Status-Balancing', + STATUS_BALANCING = 'Status-Balancing', BMS_MODE = 'Status-State', VOLTS_HIGH = 'Cells-Volts_High_Value', VOLTS_LOW = 'Cells-Volts_Low_Value',