From 90c0dce6147c139297c0f3a00953a703c368372b Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Mon, 7 Oct 2019 22:09:09 -0400 Subject: [PATCH] Add basic almanac on dashboard --- Display/package-lock.json | 18 ++++++ Display/package.json | 3 + Display/src/app/app.module.ts | 8 ++- .../dashboard/dashboard.component.html | 10 ++++ .../dashboard/dashboard.component.ts | 5 +- .../weather/almanac/almanac.component.html | 33 +++++++++++ .../weather/almanac/almanac.component.scss | 10 ++++ .../weather/almanac/almanac.component.spec.ts | 25 ++++++++ .../weather/almanac/almanac.component.ts | 59 +++++++++++++++++++ 9 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 Display/src/app/components/weather/almanac/almanac.component.html create mode 100644 Display/src/app/components/weather/almanac/almanac.component.scss create mode 100644 Display/src/app/components/weather/almanac/almanac.component.spec.ts create mode 100644 Display/src/app/components/weather/almanac/almanac.component.ts diff --git a/Display/package-lock.json b/Display/package-lock.json index ee501d3..16d717f 100644 --- a/Display/package-lock.json +++ b/Display/package-lock.json @@ -1972,6 +1972,11 @@ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", "dev": true }, + "@types/suncalc": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/suncalc/-/suncalc-1.8.0.tgz", + "integrity": "sha512-1Bx7KgoCLP8LuKaY9whWiX0Y8JMEB9gmZHNJigainwFuv3gEkZvTx0AGNvnA5nSu1daQcJDKScm9tNpW/ZjpjA==" + }, "@types/webpack-sources": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", @@ -7889,6 +7894,14 @@ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, + "ngx-moment": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ngx-moment/-/ngx-moment-3.4.0.tgz", + "integrity": "sha512-GEqzSsu12VsXXP35aerlQpuZ1ienEYQZxHmp+RH7EuJD7hWamKgLOpmbiDI9Ij3KLW/UApvonYzZvyRSv3ea/w==", + "requires": { + "tslib": "^1.9.0" + } + }, "ngx-socket-io": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ngx-socket-io/-/ngx-socket-io-3.0.1.tgz", @@ -10827,6 +10840,11 @@ "when": "~3.6.x" } }, + "suncalc": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.8.0.tgz", + "integrity": "sha1-HZiYEJVjB4dQ9JlKlZ5lTYdqy/U=" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", diff --git a/Display/package.json b/Display/package.json index a9db38c..1cef08a 100644 --- a/Display/package.json +++ b/Display/package.json @@ -24,14 +24,17 @@ "@angular/router": "~8.2.4", "@aspnet/signalr": "^1.1.4", "@types/regression": "^2.0.0", + "@types/suncalc": "^1.8.0", "angular-gridster2": "^8.2.0", "angular-highcharts": "^8.0.3", "hammerjs": "^2.0.8", "highcharts": "^7.2.0", "moment": "^2.24.0", + "ngx-moment": "^3.4.0", "ngx-socket-io": "^3.0.1", "regression": "^2.0.1", "rxjs": "~6.4.0", + "suncalc": "^1.8.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 9d1af00..0f02331 100644 --- a/Display/src/app/app.module.ts +++ b/Display/src/app/app.module.ts @@ -12,6 +12,7 @@ import { LayoutModule } from '@angular/cdk/layout'; import { MatSidenavModule } from '@angular/material/sidenav'; import { MatListModule } from '@angular/material/list'; import { MatMomentDateModule } from '@angular/material-moment-adapter'; +import { MomentModule } from 'ngx-moment'; import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io'; import { GridsterModule } from 'angular-gridster2'; @@ -21,6 +22,7 @@ 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'; +import { AlmanacComponent } from './components/weather/almanac/almanac.component'; const config: SocketIoConfig = { url: '/api/laundry', options: {} }; @@ -32,7 +34,8 @@ const config: SocketIoConfig = { url: '/api/laundry', options: {} }; DashboardComponent, WeatherChartsComponent, WeatherCurrentComponent, - PressureTrendComponent + PressureTrendComponent, + AlmanacComponent ], imports: [ BrowserModule, @@ -56,7 +59,8 @@ const config: SocketIoConfig = { url: '/api/laundry', options: {} }; ReactiveFormsModule, MatMomentDateModule, MatProgressSpinnerModule, - GridsterModule + GridsterModule, + MomentModule ], providers: [], bootstrap: [AppComponent] diff --git a/Display/src/app/components/dashboard/dashboard.component.html b/Display/src/app/components/dashboard/dashboard.component.html index 0c68db3..2b0c486 100644 --- a/Display/src/app/components/dashboard/dashboard.component.html +++ b/Display/src/app/components/dashboard/dashboard.component.html @@ -40,5 +40,15 @@ + +
+
+ Almanac +
+
+ +
+
+
diff --git a/Display/src/app/components/dashboard/dashboard.component.ts b/Display/src/app/components/dashboard/dashboard.component.ts index a15819f..7587ae7 100644 --- a/Display/src/app/components/dashboard/dashboard.component.ts +++ b/Display/src/app/components/dashboard/dashboard.component.ts @@ -13,11 +13,12 @@ export class DashboardComponent implements OnInit { public locked = true; private defaultLayout: DashboardLayout = { - version: 1, + version: 2, layout: [ { cols: 3, rows: 2, y: 0, x: 0 }, { cols: 2, rows: 2, y: 0, x: 3 }, - { cols: 2, rows: 2, y: 0, x: 5 } + { cols: 2, rows: 2, y: 0, x: 5 }, + { cols: 3, rows: 2, y: 0, x: 7 } ] }; diff --git a/Display/src/app/components/weather/almanac/almanac.component.html b/Display/src/app/components/weather/almanac/almanac.component.html new file mode 100644 index 0000000..89820bf --- /dev/null +++ b/Display/src/app/components/weather/almanac/almanac.component.html @@ -0,0 +1,33 @@ +
+
+ Loading... +
+
+ + + + + + + + + + + + + +
+ Sunrise + + {{ sun.sunrise | amLocal | amDateFormat: 'hh:mm:ss A' }} +
+ Sunset + + {{ sun.sunset | amLocal | amDateFormat: 'hh:mm:ss A' }} +
+ Moon + + {{ moonPhaseName(moon.phase) }} - {{ (moon.fraction * 100).toFixed(0) }}% illuminated +
+
+
diff --git a/Display/src/app/components/weather/almanac/almanac.component.scss b/Display/src/app/components/weather/almanac/almanac.component.scss new file mode 100644 index 0000000..f84143d --- /dev/null +++ b/Display/src/app/components/weather/almanac/almanac.component.scss @@ -0,0 +1,10 @@ +.almanac-content { + font-size: 14px; + padding: 20px; +} + +.almanac-table-header { + font-weight: 500; + text-align: right; + padding-right: 10px; +} diff --git a/Display/src/app/components/weather/almanac/almanac.component.spec.ts b/Display/src/app/components/weather/almanac/almanac.component.spec.ts new file mode 100644 index 0000000..44602eb --- /dev/null +++ b/Display/src/app/components/weather/almanac/almanac.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlmanacComponent } from './almanac.component'; + +describe('AlmanacComponent', () => { + let component: AlmanacComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [AlmanacComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AlmanacComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Display/src/app/components/weather/almanac/almanac.component.ts b/Display/src/app/components/weather/almanac/almanac.component.ts new file mode 100644 index 0000000..b9f6adc --- /dev/null +++ b/Display/src/app/components/weather/almanac/almanac.component.ts @@ -0,0 +1,59 @@ +import { Component, OnInit } from '@angular/core'; +import { WeatherReading } from 'src/app/models/weather/weather-reading'; +import { WeatherService } from 'src/app/services/weather/weather.service'; +import { first } from 'rxjs/operators'; + +import * as SunCalc from 'suncalc'; + +@Component({ + selector: 'app-almanac', + templateUrl: './almanac.component.html', + styleUrls: ['./almanac.component.scss'] +}) +export class AlmanacComponent implements OnInit { + public loaded = false; + public latestReading: WeatherReading; + public sun: SunCalc.GetTimesResult; + public moon: SunCalc.GetMoonIlluminationResult; + + constructor(private weatherService: WeatherService) { } + + ngOnInit() { + this.update(); + + setInterval(() => this.update(), 60000); + } + + async update() { + this.weatherService.getLatestReading().pipe(first(r => r !== null)).subscribe(r => { + this.latestReading = r; + + const date = new Date(); + + this.sun = SunCalc.getTimes(date, this.latestReading.Latitude, this.latestReading.Longitude); + this.moon = SunCalc.getMoonIllumination(date); + + this.loaded = true; + }); + } + + moonPhaseName(phase: number): string { + if (phase === 0) { + return 'New Moon'; + } else if (phase < 0.25) { + return 'Waxing Crescent'; + } else if (phase === 0.25) { + return 'First Quarter'; + } else if (phase < 0.5) { + return 'Waxing Gibbous'; + } else if (phase === 0.5) { + return 'Full Moon'; + } else if (phase < 0.75) { + return 'Waning Gibbous'; + } else if (phase === 0.75) { + return 'Last Quarter'; + } else if (phase < 1.0) { + return 'Waning Crescent'; + } + } +}