diff --git a/Display/package-lock.json b/Display/package-lock.json
index 25a981e..9786584 100644
--- a/Display/package-lock.json
+++ b/Display/package-lock.json
@@ -9507,6 +9507,11 @@
}
}
},
+ "regression": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/regression/-/regression-2.0.1.tgz",
+ "integrity": "sha1-jSnD6CJKEIUMNeM36FqLL6w7DIc="
+ },
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
diff --git a/Display/package.json b/Display/package.json
index 4041164..fe3b2db 100644
--- a/Display/package.json
+++ b/Display/package.json
@@ -29,6 +29,7 @@
"highcharts": "^7.2.0",
"moment": "^2.24.0",
"ngx-socket-io": "^3.0.1",
+ "regression": "^2.0.1",
"rxjs": "~6.4.0",
"tslib": "^1.10.0",
"zone.js": "~0.9.1"
diff --git a/Display/src/app/app.module.ts b/Display/src/app/app.module.ts
index cf97fdb..9d1af00 100644
--- a/Display/src/app/app.module.ts
+++ b/Display/src/app/app.module.ts
@@ -20,6 +20,7 @@ import { LaundryComponent } from './components/laundry/laundry.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { WeatherChartsComponent } from './components/weather/charts/weather-charts.component';
import { WeatherCurrentComponent } from './components/weather/current/weather-current.component';
+import { PressureTrendComponent } from './components/weather/pressure-trend/pressure-trend.component';
const config: SocketIoConfig = { url: '/api/laundry', options: {} };
@@ -30,7 +31,8 @@ const config: SocketIoConfig = { url: '/api/laundry', options: {} };
LaundryComponent,
DashboardComponent,
WeatherChartsComponent,
- WeatherCurrentComponent
+ WeatherCurrentComponent,
+ PressureTrendComponent
],
imports: [
BrowserModule,
diff --git a/Display/src/app/components/dashboard/dashboard.component.html b/Display/src/app/components/dashboard/dashboard.component.html
index 2d4911e..792fac1 100644
--- a/Display/src/app/components/dashboard/dashboard.component.html
+++ b/Display/src/app/components/dashboard/dashboard.component.html
@@ -16,5 +16,8 @@
+
+
+
diff --git a/Display/src/app/components/dashboard/dashboard.component.ts b/Display/src/app/components/dashboard/dashboard.component.ts
index 3c86865..f17c11d 100644
--- a/Display/src/app/components/dashboard/dashboard.component.ts
+++ b/Display/src/app/components/dashboard/dashboard.component.ts
@@ -62,7 +62,8 @@ export class DashboardComponent implements OnInit {
const defaultLayout = [
{ cols: 3, rows: 2, y: 0, x: 0 },
- { cols: 2, rows: 1, y: 0, x: 3 }
+ { cols: 2, rows: 1, y: 0, x: 3 },
+ { cols: 1, rows: 1, y: 0, x: 5 }
];
if (savedLayout == null) {
diff --git a/Display/src/app/components/weather/charts/weather-charts.component.ts b/Display/src/app/components/weather/charts/weather-charts.component.ts
index 6352177..6cb667e 100644
--- a/Display/src/app/components/weather/charts/weather-charts.component.ts
+++ b/Display/src/app/components/weather/charts/weather-charts.component.ts
@@ -135,7 +135,7 @@ export class WeatherChartsComponent implements OnInit {
this.chart = new Chart({
chart: {
type: 'line',
- zoomType: "x"
+ zoomType: 'x'
},
title: {
text: title
diff --git a/Display/src/app/components/weather/pressure-trend/pressure-trend.component.html b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.html
new file mode 100644
index 0000000..500a69d
--- /dev/null
+++ b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.html
@@ -0,0 +1 @@
+arrow_right_alt
diff --git a/Display/src/app/components/weather/pressure-trend/pressure-trend.component.scss b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.scss
new file mode 100644
index 0000000..2866c31
--- /dev/null
+++ b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.scss
@@ -0,0 +1,22 @@
+#pressure-arrow {
+ position: relative;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%) scale(3);
+}
+
+.down-high {
+ transform: translate(-50%, -50%) scale(3) rotate(60deg) !important;
+}
+
+.down-low {
+ transform: translate(-50%, -50%) scale(3) rotate(25deg) !important;
+}
+
+.up-high {
+ transform: translate(-50%, -50%) scale(3) rotate(-60deg) !important;
+}
+
+.up-low {
+ transform: translate(-50%, -50%) scale(3) rotate(-25deg) !important;
+}
diff --git a/Display/src/app/components/weather/pressure-trend/pressure-trend.component.spec.ts b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.spec.ts
new file mode 100644
index 0000000..502e742
--- /dev/null
+++ b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PressureTrendComponent } from './pressure-trend.component';
+
+describe('PressureTrendComponent', () => {
+ let component: PressureTrendComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [PressureTrendComponent]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PressureTrendComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Display/src/app/components/weather/pressure-trend/pressure-trend.component.ts b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.ts
new file mode 100644
index 0000000..e5a4f61
--- /dev/null
+++ b/Display/src/app/components/weather/pressure-trend/pressure-trend.component.ts
@@ -0,0 +1,64 @@
+import { Component, OnInit } from '@angular/core';
+import { WeatherService } from 'src/app/services/weather/weather.service';
+import { WeatherValueType } from 'src/app/models/weather/weather-value-type';
+import { WeatherValue } from 'src/app/models/weather/weather-value';
+
+import * as moment from 'moment';
+import * as regression from 'regression';
+
+@Component({
+ selector: 'app-pressure-trend',
+ templateUrl: './pressure-trend.component.html',
+ styleUrls: ['./pressure-trend.component.scss']
+})
+export class PressureTrendComponent implements OnInit {
+ public pressureDifference: number = null;
+
+ constructor(private weatherService: WeatherService) { }
+
+ ngOnInit() {
+ this.update();
+
+ setInterval(this.update, 60000);
+ }
+
+ async update() {
+ const end: moment.Moment = moment();
+ const start: moment.Moment = moment(end).subtract(3, 'hours');
+
+ const weatherData = await this.weatherService.getReadingValueHistory(WeatherValueType.Pressure, start, end);
+
+ if (!weatherData) {
+ return;
+ }
+
+ const points: Array> = [];
+
+ weatherData.forEach((weatherValue: WeatherValue) => {
+ const point = [moment(weatherValue.timestamp).unix(), weatherValue.value / 100];
+ points.push(point);
+ });
+
+ const result = regression.linear(points, { precision: 10 });
+
+ const regressionPoints = result.points;
+
+ this.pressureDifference = regressionPoints[regressionPoints.length - 1][1] - regressionPoints[0][1];
+ }
+
+ rotationClass(): string {
+ if (!this.pressureDifference) {
+ return '';
+ } else if (Math.abs(this.pressureDifference) <= 1.0) {
+ return '';
+ } else if (this.pressureDifference > 1.0 && this.pressureDifference <= 2.0) {
+ return 'up-low';
+ } else if (this.pressureDifference > 2.0) {
+ return 'up-high';
+ } else if (this.pressureDifference < -1.0 && this.pressureDifference >= -2.0) {
+ return 'down-low';
+ } else if (this.pressureDifference < -2.0) {
+ return 'down-high';
+ }
+ }
+}
diff --git a/Display/src/app/models/weather/weather-value-type.ts b/Display/src/app/models/weather/weather-value-type.ts
new file mode 100644
index 0000000..ab7baf3
--- /dev/null
+++ b/Display/src/app/models/weather/weather-value-type.ts
@@ -0,0 +1,3 @@
+export enum WeatherValueType {
+ Pressure = 'Pressure'
+}
diff --git a/Display/src/app/models/weather/weather-value.ts b/Display/src/app/models/weather/weather-value.ts
index 7c2094d..b71ea18 100644
--- a/Display/src/app/models/weather/weather-value.ts
+++ b/Display/src/app/models/weather/weather-value.ts
@@ -1,4 +1,4 @@
export class WeatherValue {
- bucket: string;
- averageValue: number;
+ timestamp: string;
+ value: number;
}
diff --git a/Display/src/app/services/weather/weather.service.ts b/Display/src/app/services/weather/weather.service.ts
index 942796a..c7229c9 100644
--- a/Display/src/app/services/weather/weather.service.ts
+++ b/Display/src/app/services/weather/weather.service.ts
@@ -1,7 +1,12 @@
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
import { HubConnectionBuilder, HubConnection } from '@aspnet/signalr';
-import { WeatherReading } from '../../models/weather/weather-reading';
+import { WeatherReading } from 'src/app/models/weather/weather-reading';
+import { WeatherValue } from 'src/app/models/weather/weather-value';
+import { HttpClient } from '@angular/common/http';
+
+import * as moment from 'moment';
+import { WeatherValueType } from 'src/app/models/weather/weather-value-type';
@Injectable({
providedIn: 'root'
@@ -10,7 +15,7 @@ export class WeatherService {
private connection: HubConnection;
private latestReading: BehaviorSubject = new BehaviorSubject(null);
- constructor() {
+ constructor(private httpClient: HttpClient) {
this.connection = new HubConnectionBuilder()
.withUrl('/api/hub/weather')
.build();
@@ -25,4 +30,13 @@ export class WeatherService {
getLatestReading(): Observable {
return this.latestReading.asObservable();
}
+
+ async getReadingValueHistory(valueType: WeatherValueType, start: moment.Moment, end: moment.Moment): Promise {
+ const startString = start.toISOString();
+ const endString = end.toISOString();
+
+ const data = await this.httpClient.get(`/api/weather/readings/value-history?weatherValueType=${valueType}&start=${startString}&end=${endString}`).toPromise();
+
+ return data;
+ }
}