Quick and dirty strict checks

This commit is contained in:
2022-08-18 17:53:22 -04:00
parent 8899687c03
commit f17d18a903
28 changed files with 159 additions and 153 deletions

View File

@@ -10,7 +10,7 @@
</button> </button>
</header> </header>
<gridster class="content" [options]="options"> <gridster class="content" [options]="options">
<gridster-item [item]="dashboardLayout.layout[0]"> <gridster-item [item]="dashboardLayout!.layout![0]">
<div class="dashboard-item"> <div class="dashboard-item">
<div class="dashboard-item-header"> <div class="dashboard-item-header">
Weather Weather
@@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</gridster-item> </gridster-item>
<gridster-item [item]="dashboardLayout.layout[1]"> <gridster-item [item]="dashboardLayout!.layout![1]">
<div class="dashboard-item"> <div class="dashboard-item">
<div class="dashboard-item-header"> <div class="dashboard-item-header">
Laundry Laundry
@@ -30,7 +30,7 @@
</div> </div>
</div> </div>
</gridster-item> </gridster-item>
<gridster-item [item]="dashboardLayout.layout[2]"> <gridster-item [item]="dashboardLayout!.layout![2]">
<div class="dashboard-item"> <div class="dashboard-item">
<div class="dashboard-item-header"> <div class="dashboard-item-header">
Almanac Almanac
@@ -40,7 +40,7 @@
</div> </div>
</div> </div>
</gridster-item> </gridster-item>
<gridster-item [item]="dashboardLayout.layout[3]"> <gridster-item [item]="dashboardLayout!.layout![3]">
<div class="dashboard-item"> <div class="dashboard-item">
<div class="dashboard-item-header"> <div class="dashboard-item-header">
Power Power

View File

@@ -8,8 +8,8 @@ import { DashboardLayout } from 'src/app/models/dashboard/dashboard-layout';
styleUrls: ['./dashboard.component.scss'] styleUrls: ['./dashboard.component.scss']
}) })
export class DashboardComponent implements OnInit { export class DashboardComponent implements OnInit {
public options: GridsterConfig; public options: GridsterConfig | undefined;
public dashboardLayout: DashboardLayout; public dashboardLayout: DashboardLayout | undefined;
public locked = true; public locked = true;
private defaultLayout: DashboardLayout = { private defaultLayout: DashboardLayout = {
@@ -46,14 +46,14 @@ export class DashboardComponent implements OnInit {
} }
changedOptions() { changedOptions() {
this.options.api.optionsChanged(); this.options!.api!.optionsChanged!();
} }
toggleLocked() { toggleLocked() {
this.locked = !this.locked; this.locked = !this.locked;
this.options.resizable.enabled = !this.locked; this.options!.resizable!.enabled = !this.locked;
this.options.draggable.enabled = !this.locked; this.options!.draggable!.enabled = !this.locked;
this.changedOptions(); this.changedOptions();
} }

View File

@@ -8,16 +8,16 @@
<td class="laundry-current-header"> <td class="laundry-current-header">
Washer Washer
</td> </td>
<td [ngClass]="latestStatus.washer.toString()"> <td [ngClass]="latestStatus!.washer!.toString()">
{{ latestStatus.washer ? 'On' : 'Off' }} {{ latestStatus!.washer ? 'On' : 'Off' }}
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="laundry-current-header"> <td class="laundry-current-header">
Dryer Dryer
</td> </td>
<td [ngClass]="latestStatus.dryer.toString()"> <td [ngClass]="latestStatus!.dryer!.toString()">
{{ latestStatus.dryer ? 'On' : 'Off' }} {{ latestStatus!.dryer ? 'On' : 'Off' }}
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -8,7 +8,7 @@ import { LaundryStatus } from '../../models/laundry/laundry-status';
styleUrls: ['./laundry.component.scss'] styleUrls: ['./laundry.component.scss']
}) })
export class LaundryComponent implements OnInit { export class LaundryComponent implements OnInit {
public latestStatus: LaundryStatus; public latestStatus: LaundryStatus | undefined;
constructor(private laundryService: LaundryService) { } constructor(private laundryService: LaundryService) { }
ngOnInit() { ngOnInit() {

View File

@@ -10,7 +10,7 @@ import { MatSidenav } from '@angular/material/sidenav';
styleUrls: ['./nav.component.scss'] styleUrls: ['./nav.component.scss']
}) })
export class NavComponent { export class NavComponent {
@ViewChild('sidenav', {}) sidenav: MatSidenav; @ViewChild('sidenav', {}) sidenav: MatSidenav | undefined;
isHandset$: Observable<boolean> = this.breakpointObserver.observe([ isHandset$: Observable<boolean> = this.breakpointObserver.observe([
Breakpoints.HandsetLandscape, Breakpoints.HandsetLandscape,
@@ -30,7 +30,7 @@ export class NavComponent {
public toggleSidenav() { public toggleSidenav() {
this.isHandset$.subscribe(isHandset => { this.isHandset$.subscribe(isHandset => {
if (isHandset) { if (isHandset) {
this.sidenav.toggle(); this.sidenav!.toggle();
} }
}); });
} }

View File

@@ -21,7 +21,7 @@ HC_exporting(Highcharts);
}) })
export class PowerChartsComponent implements OnInit { export class PowerChartsComponent implements OnInit {
public chart: Chart; public chart: Chart | undefined;
public loading = true; public loading = true;
private timeSpanValue: TimeSpan = TimeSpan.Last24Hours; private timeSpanValue: TimeSpan = TimeSpan.Last24Hours;
@@ -71,19 +71,19 @@ export class PowerChartsComponent implements OnInit {
]).subscribe(data => { ]).subscribe(data => {
const seriesData: Array<SeriesLineOptions> = []; const seriesData: Array<SeriesLineOptions> = [];
seriesData.push({ name: 'Generation', data: [], yAxis: 0, marker: { enabled: false }, tooltip: { valueSuffix: ' W' } } as SeriesLineOptions); seriesData.push({ type: 'line', name: 'Generation', data: [], yAxis: 0, marker: { enabled: false }, tooltip: { valueSuffix: ' W' } } as SeriesLineOptions);
seriesData.push({ name: 'Consumption', data: [], yAxis: 0, marker: { enabled: false }, tooltip: { valueSuffix: ' W' } } as SeriesLineOptions); seriesData.push({ type: 'line', name: 'Consumption', data: [], yAxis: 0, marker: { enabled: false }, tooltip: { valueSuffix: ' W' } } as SeriesLineOptions);
seriesData.push({ name: 'Light', data: [], yAxis: 1, marker: { enabled: false }, tooltip: { valueSuffix: ' lx' } } as SeriesLineOptions); seriesData.push({ type: 'line', name: 'Light', data: [], yAxis: 1, marker: { enabled: false }, tooltip: { valueSuffix: ' lx' } } as SeriesLineOptions);
data[0].forEach(dataElement => { data[0].forEach(dataElement => {
const date = Date.parse(dataElement.bucket); const date = Date.parse(dataElement.bucket!);
seriesData[0].data.push([date, dataElement.averageGeneration < 0 ? 0 : dataElement.averageGeneration]); seriesData[0].data!.push([date, dataElement.averageGeneration! < 0 ? 0 : dataElement.averageGeneration]);
seriesData[1].data.push([date, dataElement.averageConsumption < 0 ? 0 : dataElement.averageConsumption]); seriesData[1].data!.push([date, dataElement.averageConsumption! < 0 ? 0 : dataElement.averageConsumption]);
}); });
data[1].forEach(dataElement => { data[1].forEach(dataElement => {
const date = Date.parse(dataElement.bucket); const date = Date.parse(dataElement.bucket!);
seriesData[2].data.push([date, dataElement.averageValue]); seriesData[2].data!.push([date, dataElement.averageValue]);
}); });
this.chart = new Chart({ this.chart = new Chart({

View File

@@ -9,7 +9,7 @@
Generation Generation
</td> </td>
<td> <td>
{{ latestStatus.Generation < 0 ? 0 : latestStatus.Generation }} W {{ latestStatus!.Generation < 0 ? 0 : latestStatus!.Generation }} W
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -17,7 +17,7 @@
Consumption Consumption
</td> </td>
<td> <td>
{{ latestStatus.Consumption < 0 ? 0 : latestStatus.Consumption }} W {{ latestStatus!.Consumption < 0 ? 0 : latestStatus!.Consumption }} W
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -8,7 +8,7 @@ import { PowerStatus } from 'src/app/models/power/power-status';
styleUrls: ['./power.component.scss'] styleUrls: ['./power.component.scss']
}) })
export class PowerComponent implements OnInit { export class PowerComponent implements OnInit {
public latestStatus: PowerStatus; public latestStatus: PowerStatus | undefined | null;
constructor(private powerService: PowerService) { } constructor(private powerService: PowerService) { }
ngOnInit() { ngOnInit() {

View File

@@ -1,7 +1,7 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { TimeSpan } from 'src/app/models/time-span'; import { TimeSpan } from 'src/app/models/time-span';
import * as moment from 'moment'; import moment from 'moment';
@Component({ @Component({
selector: 'app-time-range', selector: 'app-time-range',
@@ -11,12 +11,12 @@ import * as moment from 'moment';
export class TimeRangeComponent implements OnInit { export class TimeRangeComponent implements OnInit {
@Input() @Input()
public loading: boolean; public loading: boolean | undefined;
private timeSpanValue: TimeSpan; private timeSpanValue: TimeSpan | undefined;
@Input() @Input()
public set timeSpan(val: TimeSpan) { public set timeSpan(val: TimeSpan | undefined) {
this.timeSpanChange.emit(val); this.timeSpanChange.emit(val);
this.timeSpanValue = val; this.timeSpanValue = val;
} }
@@ -28,10 +28,10 @@ export class TimeRangeComponent implements OnInit {
@Output() @Output()
public timeSpanChange: EventEmitter<TimeSpan> = new EventEmitter<TimeSpan>(); public timeSpanChange: EventEmitter<TimeSpan> = new EventEmitter<TimeSpan>();
private dateValue: moment.Moment; private dateValue: moment.Moment | undefined;
@Input() @Input()
public set date(val: moment.Moment) { public set date(val: moment.Moment | undefined) {
this.dateChange.emit(val); this.dateChange.emit(val);
this.dateValue = val; this.dateValue = val;
} }

View File

@@ -9,7 +9,7 @@
Sunrise Sunrise
</td> </td>
<td colspan="2"> <td colspan="2">
{{ sunTimes.sunrise | amLocal | amDateFormat: 'hh:mm:ss A' }} {{ sunTimes!.sunrise | amLocal | amDateFormat: 'hh:mm:ss A' }}
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -17,7 +17,7 @@
Sunset Sunset
</td> </td>
<td colspan="2"> <td colspan="2">
{{ sunTimes.sunset | amLocal | amDateFormat: 'hh:mm:ss A' }} {{ sunTimes!.sunset | amLocal | amDateFormat: 'hh:mm:ss A' }}
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -33,7 +33,7 @@
Moonrise Moonrise
</td> </td>
<td colspan="2"> <td colspan="2">
{{ moonTimes.rise | amLocal | amDateFormat: 'hh:mm:ss A' }} {{ moonTimes!.rise | amLocal | amDateFormat: 'hh:mm:ss A' }}
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -41,7 +41,7 @@
Moonset Moonset
</td> </td>
<td colspan="2"> <td colspan="2">
{{ moonTimes.set | amLocal | amDateFormat: 'hh:mm:ss A' }} {{ moonTimes!.set | amLocal | amDateFormat: 'hh:mm:ss A' }}
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -49,13 +49,13 @@
Moon Moon
</td> </td>
<td> <td>
{{ moonPhaseName(moon.phase) }} {{ moonPhaseName(moon!.phase) }}
<br> <br>
{{ (moon.fraction * 100).toFixed(1) }}% illuminated {{ (moon!.fraction * 100).toFixed(1) }}% illuminated
</td> </td>
<td> <td>
<div class="moon-phase"> <div class="moon-phase">
{{ moonPhaseLetter(moon.phase) }} {{ moonPhaseLetter(moon!.phase) }}
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -14,10 +14,10 @@ import 'moment-duration-format';
}) })
export class AlmanacComponent implements OnInit { export class AlmanacComponent implements OnInit {
public loaded = false; public loaded = false;
public latestReading: WeatherUpdate; public latestReading: WeatherUpdate | undefined | null;
public sunTimes: SunCalc.GetTimesResult; public sunTimes: SunCalc.GetTimesResult | undefined | null;
public moonTimes: SunCalc.GetMoonTimes; public moonTimes: SunCalc.GetMoonTimes | undefined | null;
public moon: SunCalc.GetMoonIlluminationResult; public moon: SunCalc.GetMoonIlluminationResult | undefined | null;
constructor(private weatherService: WeatherService) { } constructor(private weatherService: WeatherService) { }
@@ -33,8 +33,8 @@ export class AlmanacComponent implements OnInit {
const date = new Date(); const date = new Date();
this.sunTimes = SunCalc.getTimes(date, this.latestReading.Latitude, this.latestReading.Longitude); this.sunTimes = SunCalc.getTimes(date, this.latestReading?.Latitude!, this.latestReading?.Longitude!);
this.moonTimes = SunCalc.getMoonTimes(date, this.latestReading.Latitude, this.latestReading.Longitude); this.moonTimes = SunCalc.getMoonTimes(date, this.latestReading?.Latitude!, this.latestReading?.Longitude!);
this.moon = SunCalc.getMoonIllumination(date); this.moon = SunCalc.getMoonIllumination(date);
this.loaded = true; this.loaded = true;
@@ -59,6 +59,8 @@ export class AlmanacComponent implements OnInit {
} else if (phase < 1.0) { } else if (phase < 1.0) {
return 'Waning Crescent'; return 'Waning Crescent';
} }
return '';
} }
moonPhaseLetter(phase: number): string { moonPhaseLetter(phase: number): string {
@@ -79,10 +81,12 @@ export class AlmanacComponent implements OnInit {
} else if (phase < 1.0) { } else if (phase < 1.0) {
return 'W'; return 'W';
} }
return '';
} }
dayLength(): string { dayLength(): string {
const duration = moment.duration((this.sunTimes.sunset.valueOf() - this.sunTimes.sunrise.valueOf())); const duration = moment.duration((this.sunTimes!.sunset.valueOf() - this.sunTimes!.sunrise.valueOf()));
return duration.format('hh [hours] mm [minutes]'); return duration.format('hh [hours] mm [minutes]');
} }
} }

View File

@@ -26,7 +26,7 @@ enum ChartType {
}) })
export class WeatherChartsComponent implements OnInit { export class WeatherChartsComponent implements OnInit {
public chart: Chart; public chart: Chart | undefined;
public loading = true; public loading = true;
public selectedChartType: ChartType = ChartType.Weather; public selectedChartType: ChartType = ChartType.Weather;
@@ -91,12 +91,12 @@ export class WeatherChartsComponent implements OnInit {
seriesData.push({ type: 'column', name: 'Rain', data: [], yAxis: 3, marker: { enabled: false }, tooltip: { valueSuffix: '"' } } as SeriesColumnOptions); seriesData.push({ type: 'column', name: 'Rain', data: [], yAxis: 3, marker: { enabled: false }, tooltip: { valueSuffix: '"' } } as SeriesColumnOptions);
data.forEach(dataElement => { data.forEach(dataElement => {
const date = Date.parse(dataElement.bucket); const date = Date.parse(dataElement.bucket!);
seriesData[0].data.push([date, dataElement.averageTemperature]); seriesData[0].data!.push([date, dataElement.averageTemperature]);
seriesData[1].data.push([date, dataElement.averagePressure / 33.864 / 100]); seriesData[1].data!.push([date, dataElement.averagePressure! / 33.864 / 100]);
seriesData[2].data.push([date, dataElement.averageHumidity]); seriesData[2].data!.push([date, dataElement.averageHumidity]);
seriesData[3].data.push([date, dataElement.averageLightLevel]); seriesData[3].data!.push([date, dataElement.averageLightLevel]);
seriesData[4].data.push([date, dataElement.rainTotal]); seriesData[4].data!.push([date, dataElement.rainTotal]);
}); });
this.chart = new Chart({ this.chart = new Chart({
@@ -219,11 +219,11 @@ export class WeatherChartsComponent implements OnInit {
seriesData.push({ type: 'windbarb', name: 'Direction', data: [], marker: { enabled: false }, tooltip: { valueSuffix: ' MPH' } } as SeriesWindbarbOptions); seriesData.push({ type: 'windbarb', name: 'Direction', data: [], marker: { enabled: false }, tooltip: { valueSuffix: ' MPH' } } as SeriesWindbarbOptions);
data.forEach(dataElement => { data.forEach(dataElement => {
const date = Date.parse(dataElement.bucket); const date = Date.parse(dataElement.bucket!);
seriesData[0].data.push([date, dataElement.minimumSpeed]); seriesData[0].data!.push([date, dataElement.minimumSpeed]);
seriesData[1].data.push([date, dataElement.averageSpeed]); seriesData[1].data!.push([date, dataElement.averageSpeed]);
seriesData[2].data.push([date, dataElement.maximumSpeed]); seriesData[2].data!.push([date, dataElement.maximumSpeed]);
seriesData[3].data.push([date, dataElement.averageSpeed, dataElement.averageDirection]); seriesData[3].data!.push([date, dataElement.averageSpeed, dataElement.averageDirection]);
}); });
this.chart = new Chart({ this.chart = new Chart({

View File

@@ -10,23 +10,23 @@
Temperature Temperature
</td> </td>
<td> <td>
{{ latestReading.Temperature.toFixed(2) }}°F {{ latestReading!.Temperature?.toFixed(2) }}°F
</td> </td>
</tr> </tr>
<tr *ngIf="latestReading.HeatIndex"> <tr *ngIf="latestReading!.HeatIndex">
<td class="weather-current-header"> <td class="weather-current-header">
Heat index Heat index
</td> </td>
<td> <td>
{{ latestReading.HeatIndex.toFixed(2) }}°F {{ latestReading!.HeatIndex?.toFixed(2) }}°F
</td> </td>
</tr> </tr>
<tr *ngIf="latestReading.WindChill"> <tr *ngIf="latestReading!.WindChill">
<td class="weather-current-header"> <td class="weather-current-header">
Wind chill Wind chill
</td> </td>
<td> <td>
{{ latestReading.WindChill.toFixed(2) }}°F {{ latestReading!.WindChill?.toFixed(2) }}°F
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -34,7 +34,7 @@
Humidity Humidity
</td> </td>
<td> <td>
{{ latestReading.Humidity.toFixed(2) }}% {{ latestReading!.Humidity?.toFixed(2) }}%
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -42,7 +42,7 @@
Dew point Dew point
</td> </td>
<td> <td>
{{ latestReading.DewPoint.toFixed(2) }}°F {{ latestReading!.DewPoint?.toFixed(2) }}°F
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -50,9 +50,9 @@
Pressure Pressure
</td> </td>
<td> <td>
{{ (latestReading.Pressure / 33.864 / 100).toFixed(2) }}" {{ latestReading!.Pressure && (latestReading!.Pressure / 33.864 / 100)?.toFixed(2) }}"
<span class="pressure-trend-arrow" [ngClass]="rotationClass()" title="3 Hour Change: {{ latestReading.PressureDifferenceThreeHour.toFixed(1) }}"></span> <span class="pressure-trend-arrow" [ngClass]="rotationClass()" title="3 Hour Change: {{ latestReading!.PressureDifferenceThreeHour?.toFixed(1) }}"></span>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -60,7 +60,7 @@
Wind Wind
</td> </td>
<td> <td>
{{ latestReading.WindSpeed.toFixed(2) }} mph {{ latestReading.WindDirection }} {{ latestReading!.WindSpeed?.toFixed(2) }} mph {{ latestReading!.WindDirection }}
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -68,7 +68,7 @@
Rain Rain
</td> </td>
<td> <td>
{{ latestReading.RainLastHour.toFixed(2) }}" (last hour) {{ latestReading!.RainLastHour?.toFixed(2) }}" (last hour)
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -76,7 +76,7 @@
Light Light
</td> </td>
<td> <td>
{{ latestReading.LightLevel.toFixed(2) }} lx {{ latestReading!.LightLevel?.toFixed(2) }} lx
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -8,7 +8,7 @@ import { WeatherService } from 'src/app/services/weather/weather.service';
styleUrls: ['./weather-current.component.scss'] styleUrls: ['./weather-current.component.scss']
}) })
export class WeatherCurrentComponent implements OnInit { export class WeatherCurrentComponent implements OnInit {
public latestReading: WeatherUpdate; public latestReading: WeatherUpdate | null | undefined;
constructor(private weatherService: WeatherService) { } constructor(private weatherService: WeatherService) { }
@@ -17,7 +17,7 @@ export class WeatherCurrentComponent implements OnInit {
} }
rotationClass(): string { rotationClass(): string {
const pressureDifference = this.latestReading.PressureDifferenceThreeHour; const pressureDifference = this.latestReading?.PressureDifferenceThreeHour;
if (!pressureDifference) { if (!pressureDifference) {
return ''; return '';
@@ -32,5 +32,7 @@ export class WeatherCurrentComponent implements OnInit {
} else if (pressureDifference < -2.0) { } else if (pressureDifference < -2.0) {
return 'down-high'; return 'down-high';
} }
return '';
} }
} }

View File

@@ -39,13 +39,13 @@
Temperature Temperature
</td> </td>
<td> <td>
{{ weatherAggregates.temperature.min.toFixed(2) }}°F {{ weatherAggregates!.temperature.min.toFixed(2) }}°F
</td> </td>
<td> <td>
{{ weatherAggregates.temperature.average.toFixed(2) }}°F {{ weatherAggregates!.temperature.average.toFixed(2) }}°F
</td> </td>
<td> <td>
{{ weatherAggregates.temperature.max.toFixed(2) }}°F {{ weatherAggregates!.temperature.max.toFixed(2) }}°F
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -53,13 +53,13 @@
Humidity Humidity
</td> </td>
<td> <td>
{{ weatherAggregates.humidity.min.toFixed(2) }}% {{ weatherAggregates!.humidity.min.toFixed(2) }}%
</td> </td>
<td> <td>
{{ weatherAggregates.humidity.average.toFixed(2) }}% {{ weatherAggregates!.humidity.average.toFixed(2) }}%
</td> </td>
<td> <td>
{{ weatherAggregates.humidity.max.toFixed(2) }}% {{ weatherAggregates!.humidity.max.toFixed(2) }}%
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -67,13 +67,13 @@
Pressure Pressure
</td> </td>
<td> <td>
{{ (weatherAggregates.pressure.min / 33.864 / 100).toFixed(2) }}" {{ (weatherAggregates!.pressure.min / 33.864 / 100).toFixed(2) }}"
</td> </td>
<td> <td>
{{ (weatherAggregates.pressure.average / 33.864 / 100).toFixed(2) }}" {{ (weatherAggregates!.pressure.average / 33.864 / 100).toFixed(2) }}"
</td> </td>
<td> <td>
{{ (weatherAggregates.pressure.max / 33.864 / 100).toFixed(2) }}" {{ (weatherAggregates!.pressure.max / 33.864 / 100).toFixed(2) }}"
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -81,13 +81,13 @@
Light Light
</td> </td>
<td> <td>
{{ weatherAggregates.light.min.toFixed(2) }} lx {{ weatherAggregates!.light.min.toFixed(2) }} lx
</td> </td>
<td> <td>
{{ weatherAggregates.light.average.toFixed(2) }} lx {{ weatherAggregates!.light.average.toFixed(2) }} lx
</td> </td>
<td> <td>
{{ weatherAggregates.light.max.toFixed(2) }} lx {{ weatherAggregates!.light.max.toFixed(2) }} lx
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -95,13 +95,13 @@
Wind Speed Wind Speed
</td> </td>
<td> <td>
{{ weatherAggregates.windSpeed.min.toFixed(2) }} mph {{ weatherAggregates!.windSpeed.min.toFixed(2) }} mph
</td> </td>
<td> <td>
{{ weatherAggregates.windSpeed.average.toFixed(2) }} mph {{ weatherAggregates!.windSpeed.average.toFixed(2) }} mph
</td> </td>
<td> <td>
{{ weatherAggregates.windSpeed.max.toFixed(2) }} mph {{ weatherAggregates!.windSpeed.max.toFixed(2) }} mph
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -111,7 +111,7 @@
<td> <td>
</td> </td>
<td> <td>
{{ weatherAggregates.windDirectionAverage }} {{ weatherAggregates!.windDirectionAverage }}
</td> </td>
<td> <td>
</td> </td>
@@ -125,7 +125,7 @@
<td> <td>
</td> </td>
<td> <td>
{{ weatherAggregates.rainTotal.toFixed(2) }}" {{ weatherAggregates!.rainTotal.toFixed(2) }}"
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -3,7 +3,7 @@ import { TimeSpan } from 'src/app/models/time-span';
import { WeatherService } from 'src/app/services/weather/weather.service'; import { WeatherService } from 'src/app/services/weather/weather.service';
import { WeatherAggregates } from 'src/app/models/weather/weather-aggregates'; import { WeatherAggregates } from 'src/app/models/weather/weather-aggregates';
import * as moment from 'moment'; import moment from 'moment';
@Component({ @Component({
selector: 'app-weather-summary', selector: 'app-weather-summary',
@@ -13,7 +13,7 @@ import * as moment from 'moment';
export class WeatherSummaryComponent implements OnInit { export class WeatherSummaryComponent implements OnInit {
public loading = true; public loading = true;
public weatherAggregates: WeatherAggregates = null; public weatherAggregates: WeatherAggregates | undefined | null = null;
private timeSpanValue: TimeSpan = TimeSpan.Last24Hours; private timeSpanValue: TimeSpan = TimeSpan.Last24Hours;
private dateValue: moment.Moment = moment().startOf('day'); private dateValue: moment.Moment = moment().startOf('day');

View File

@@ -1,6 +1,6 @@
import { GridsterItem } from 'angular-gridster2'; import { GridsterItem } from 'angular-gridster2';
export class DashboardLayout { export class DashboardLayout {
version: number; version: number | undefined;
layout: Array<GridsterItem>; layout: Array<GridsterItem> | undefined;
} }

View File

@@ -1,4 +1,4 @@
export class LaundryStatus { export class LaundryStatus {
washer = false; washer: boolean | undefined = false;
dryer = false; dryer: boolean | undefined = false;
} }

View File

@@ -1,5 +1,5 @@
export class PowerStatusGrouped { export class PowerStatusGrouped {
bucket: string; bucket: string | undefined;
averageGeneration: number; averageGeneration: number | undefined;
averageConsumption: number; averageConsumption: number | undefined;
} }

View File

@@ -1,8 +1,8 @@
export class WeatherReadingGrouped { export class WeatherReadingGrouped {
bucket: string; bucket: string | undefined;
averageTemperature: number; averageTemperature: number | undefined;
averagePressure: number; averagePressure: number | undefined;
averageLightLevel: number; averageLightLevel: number | undefined;
averageHumidity: number; averageHumidity: number | undefined;
rainTotal: number; rainTotal: number | undefined;
} }

View File

@@ -1,25 +1,25 @@
export class WeatherUpdate { export class WeatherUpdate {
Type: string; Type: string | undefined;
Message: null; Message: null | undefined;
Timestamp: Date; Timestamp: Date | undefined;
WindDirection: string; WindDirection: string | undefined;
WindSpeed: number; WindSpeed: number | undefined;
Humidity: number; Humidity: number | undefined;
Rain: number; Rain: number | undefined;
Pressure: number; Pressure: number | undefined;
Temperature: number; Temperature: number | undefined;
BatteryLevel: number; BatteryLevel: number | undefined;
LightLevel: number; LightLevel: number | undefined;
Latitude: number; Latitude: number | undefined;
Longitude: number; Longitude: number | undefined;
Altitude: number; Altitude: number | undefined;
SatelliteCount: number; SatelliteCount: number | undefined;
GpsTimestamp: Date; GpsTimestamp: Date | undefined;
WindChill: number; WindChill: number | undefined;
HeatIndex: number; HeatIndex: number | undefined;
DewPoint: number; DewPoint: number | undefined;
PressureDifferenceThreeHour: number; PressureDifferenceThreeHour: number | undefined;
PressureSlope: number; PressureSlope: number | undefined;
PressureAngle: number; PressureAngle: number | undefined;
RainLastHour: number; RainLastHour: number | undefined;
} }

View File

@@ -1,4 +1,4 @@
export class WeatherValueGrouped { export class WeatherValueGrouped {
bucket: string; bucket: string | undefined;
averageValue: number; averageValue: number | undefined;
} }

View File

@@ -1,4 +1,4 @@
export class WeatherValue { export class WeatherValue {
timestamp: string; timestamp: string | undefined;
value: number; value: number | undefined;
} }

View File

@@ -1,8 +1,8 @@
export class WindHistoryGrouped { export class WindHistoryGrouped {
bucket: string; bucket: string | undefined;
minimumSpeed: number; minimumSpeed: number | undefined;
averageSpeed: number; averageSpeed: number | undefined;
maximumSpeed: number; maximumSpeed: number | undefined;
averageDirection: number; averageDirection: number | undefined;
} }

View File

@@ -1,12 +1,12 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs'; import { Observable, BehaviorSubject, firstValueFrom } from 'rxjs';
import { HubConnectionBuilder, HubConnection } from '@aspnet/signalr'; import { HubConnectionBuilder, HubConnection } from '@aspnet/signalr';
import { LaundryStatus } from '../../models/laundry/laundry-status'; import { LaundryStatus } from '../../models/laundry/laundry-status';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
class DeviceMessage { class DeviceMessage {
name: string; name: string | undefined;
status: boolean; status: boolean | undefined;
} }
@Injectable({ @Injectable({
@@ -48,7 +48,7 @@ export class LaundryService {
} }
private async loadLatestStatus() { private async loadLatestStatus() {
const data = await this.httpClient.get<DeviceMessage[]>(`/api/device-status/status/recent`).toPromise(); const data = await firstValueFrom(this.httpClient.get<DeviceMessage[]>(`/api/device-status/status/recent`));
const newStatus = new LaundryStatus(); const newStatus = new LaundryStatus();

View File

@@ -8,7 +8,7 @@ import { PowerStatus } from 'src/app/models/power/power-status';
}) })
export class PowerService { export class PowerService {
private connection: HubConnection; private connection: HubConnection;
private latestStatus: BehaviorSubject<PowerStatus> = new BehaviorSubject<PowerStatus>(null); private latestStatus: BehaviorSubject<PowerStatus | null> = new BehaviorSubject<PowerStatus | null>(null);
constructor() { constructor() {
this.connection = new HubConnectionBuilder() this.connection = new HubConnectionBuilder()
@@ -22,7 +22,7 @@ export class PowerService {
this.connection.start(); this.connection.start();
} }
getLatestStatus(): Observable<PowerStatus> { getLatestStatus(): Observable<PowerStatus | null> {
return this.latestStatus.asObservable(); return this.latestStatus.asObservable();
} }
} }

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs'; import { Observable, BehaviorSubject, firstValueFrom } from 'rxjs';
import { HubConnectionBuilder, HubConnection } from '@aspnet/signalr'; import { HubConnectionBuilder, HubConnection } from '@aspnet/signalr';
import { WeatherUpdate } from 'src/app/models/weather/weather-update'; import { WeatherUpdate } from 'src/app/models/weather/weather-update';
import { WeatherValue } from 'src/app/models/weather/weather-value'; import { WeatherValue } from 'src/app/models/weather/weather-value';
@@ -7,14 +7,14 @@ import { HttpClient } from '@angular/common/http';
import { WeatherValueType } from 'src/app/models/weather/weather-value-type'; import { WeatherValueType } from 'src/app/models/weather/weather-value-type';
import { WeatherAggregates } from 'src/app/models/weather/weather-aggregates'; import { WeatherAggregates } from 'src/app/models/weather/weather-aggregates';
import * as moment from 'moment'; import moment from 'moment';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class WeatherService { export class WeatherService {
private connection: HubConnection; private connection: HubConnection;
private latestReading: BehaviorSubject<WeatherUpdate> = new BehaviorSubject<WeatherUpdate>(null); private latestReading: BehaviorSubject<WeatherUpdate | null> = new BehaviorSubject<WeatherUpdate | null>(null);
constructor(private httpClient: HttpClient) { constructor(private httpClient: HttpClient) {
this.connection = new HubConnectionBuilder() this.connection = new HubConnectionBuilder()
@@ -28,24 +28,24 @@ export class WeatherService {
this.connection.start(); this.connection.start();
} }
getLatestReading(): Observable<WeatherUpdate> { getLatestReading(): Observable<WeatherUpdate | null> {
return this.latestReading.asObservable(); return this.latestReading.asObservable();
} }
async getReadingValueHistory(valueType: WeatherValueType, start: moment.Moment, end: moment.Moment): Promise<WeatherValue[]> { async getReadingValueHistory(valueType: WeatherValueType, start: moment.Moment, end: moment.Moment): Promise<WeatherValue[] | undefined> {
const startString = start.toISOString(); const startString = start.toISOString();
const endString = end.toISOString(); const endString = end.toISOString();
const data = await this.httpClient.get<WeatherValue[]>(`/api/weather/readings/value-history?weatherValueType=${valueType}&start=${startString}&end=${endString}`).toPromise(); const data = await firstValueFrom(this.httpClient.get<WeatherValue[]>(`/api/weather/readings/value-history?weatherValueType=${valueType}&start=${startString}&end=${endString}`));
return data; return data;
} }
async getReadingAggregate(start: moment.Moment, end: moment.Moment): Promise<WeatherAggregates> { async getReadingAggregate(start: moment.Moment, end: moment.Moment): Promise<WeatherAggregates | undefined> {
const startString = start.toISOString(); const startString = start.toISOString();
const endString = end.toISOString(); const endString = end.toISOString();
const data = await this.httpClient.get<WeatherAggregates>(`/api/weather/readings/aggregate?start=${startString}&end=${endString}`).toPromise(); const data = await firstValueFrom(this.httpClient.get<WeatherAggregates>(`/api/weather/readings/aggregate?start=${startString}&end=${endString}`));
return data; return data;
} }

View File

@@ -8,7 +8,7 @@
"downlevelIteration": true, "downlevelIteration": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"strict": false, "strict": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",