Add dashboard pressure trend arrow

This commit is contained in:
2019-10-06 19:59:13 -04:00
parent d593c0095f
commit 7c062dbc04
13 changed files with 148 additions and 7 deletions

View File

@@ -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",

View File

@@ -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"

View File

@@ -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,

View File

@@ -16,5 +16,8 @@
<gridster-item [item]="dashboard[1]">
<app-laundry></app-laundry>
</gridster-item>
<gridster-item [item]="dashboard[2]">
<app-pressure-trend></app-pressure-trend>
</gridster-item>
</gridster>
</div>

View File

@@ -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) {

View File

@@ -135,7 +135,7 @@ export class WeatherChartsComponent implements OnInit {
this.chart = new Chart({
chart: {
type: 'line',
zoomType: "x"
zoomType: 'x'
},
title: {
text: title

View File

@@ -0,0 +1 @@
<mat-icon id="pressure-arrow" *ngIf="pressureDifference !== null" [ngClass]="rotationClass()">arrow_right_alt</mat-icon>

View File

@@ -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;
}

View File

@@ -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<PressureTrendComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [PressureTrendComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PressureTrendComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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<Array<number>> = [];
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';
}
}
}

View File

@@ -0,0 +1,3 @@
export enum WeatherValueType {
Pressure = 'Pressure'
}

View File

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

View File

@@ -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<WeatherReading> = new BehaviorSubject<WeatherReading>(null);
constructor() {
constructor(private httpClient: HttpClient) {
this.connection = new HubConnectionBuilder()
.withUrl('/api/hub/weather')
.build();
@@ -25,4 +30,13 @@ export class WeatherService {
getLatestReading(): Observable<WeatherReading> {
return this.latestReading.asObservable();
}
async getReadingValueHistory(valueType: WeatherValueType, start: moment.Moment, end: moment.Moment): Promise<WeatherValue[]> {
const startString = start.toISOString();
const endString = end.toISOString();
const data = await this.httpClient.get<WeatherValue[]>(`/api/weather/readings/value-history?weatherValueType=${valueType}&start=${startString}&end=${endString}`).toPromise();
return data;
}
}