mirror of
https://github.com/ckaczor/HomeMonitor.git
synced 2026-02-16 10:58:32 -05:00
Add basic almanac on dashboard
This commit is contained in:
18
Display/package-lock.json
generated
18
Display/package-lock.json
generated
@@ -1972,6 +1972,11 @@
|
|||||||
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
|
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
|
||||||
"dev": true
|
"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": {
|
"@types/webpack-sources": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz",
|
||||||
@@ -7889,6 +7894,14 @@
|
|||||||
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
|
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
|
||||||
"dev": true
|
"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": {
|
"ngx-socket-io": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ngx-socket-io/-/ngx-socket-io-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ngx-socket-io/-/ngx-socket-io-3.0.1.tgz",
|
||||||
@@ -10827,6 +10840,11 @@
|
|||||||
"when": "~3.6.x"
|
"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": {
|
"supports-color": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
|||||||
@@ -24,14 +24,17 @@
|
|||||||
"@angular/router": "~8.2.4",
|
"@angular/router": "~8.2.4",
|
||||||
"@aspnet/signalr": "^1.1.4",
|
"@aspnet/signalr": "^1.1.4",
|
||||||
"@types/regression": "^2.0.0",
|
"@types/regression": "^2.0.0",
|
||||||
|
"@types/suncalc": "^1.8.0",
|
||||||
"angular-gridster2": "^8.2.0",
|
"angular-gridster2": "^8.2.0",
|
||||||
"angular-highcharts": "^8.0.3",
|
"angular-highcharts": "^8.0.3",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"highcharts": "^7.2.0",
|
"highcharts": "^7.2.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
|
"ngx-moment": "^3.4.0",
|
||||||
"ngx-socket-io": "^3.0.1",
|
"ngx-socket-io": "^3.0.1",
|
||||||
"regression": "^2.0.1",
|
"regression": "^2.0.1",
|
||||||
"rxjs": "~6.4.0",
|
"rxjs": "~6.4.0",
|
||||||
|
"suncalc": "^1.8.0",
|
||||||
"tslib": "^1.10.0",
|
"tslib": "^1.10.0",
|
||||||
"zone.js": "~0.9.1"
|
"zone.js": "~0.9.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { LayoutModule } from '@angular/cdk/layout';
|
|||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list';
|
||||||
import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
||||||
|
import { MomentModule } from 'ngx-moment';
|
||||||
|
|
||||||
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
|
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
|
||||||
import { GridsterModule } from 'angular-gridster2';
|
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 { WeatherChartsComponent } from './components/weather/charts/weather-charts.component';
|
||||||
import { WeatherCurrentComponent } from './components/weather/current/weather-current.component';
|
import { WeatherCurrentComponent } from './components/weather/current/weather-current.component';
|
||||||
import { PressureTrendComponent } from './components/weather/pressure-trend/pressure-trend.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: {} };
|
const config: SocketIoConfig = { url: '/api/laundry', options: {} };
|
||||||
|
|
||||||
@@ -32,7 +34,8 @@ const config: SocketIoConfig = { url: '/api/laundry', options: {} };
|
|||||||
DashboardComponent,
|
DashboardComponent,
|
||||||
WeatherChartsComponent,
|
WeatherChartsComponent,
|
||||||
WeatherCurrentComponent,
|
WeatherCurrentComponent,
|
||||||
PressureTrendComponent
|
PressureTrendComponent,
|
||||||
|
AlmanacComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@@ -56,7 +59,8 @@ const config: SocketIoConfig = { url: '/api/laundry', options: {} };
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatMomentDateModule,
|
MatMomentDateModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
GridsterModule
|
GridsterModule,
|
||||||
|
MomentModule
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|||||||
@@ -40,5 +40,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</gridster-item>
|
</gridster-item>
|
||||||
|
<gridster-item [item]="dashboardLayout.layout[3]">
|
||||||
|
<div class="dashboard-item">
|
||||||
|
<div class="dashboard-item-header">
|
||||||
|
Almanac
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-item-content">
|
||||||
|
<app-almanac></app-almanac>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</gridster-item>
|
||||||
</gridster>
|
</gridster>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ export class DashboardComponent implements OnInit {
|
|||||||
public locked = true;
|
public locked = true;
|
||||||
|
|
||||||
private defaultLayout: DashboardLayout = {
|
private defaultLayout: DashboardLayout = {
|
||||||
version: 1,
|
version: 2,
|
||||||
layout: [
|
layout: [
|
||||||
{ cols: 3, rows: 2, y: 0, x: 0 },
|
{ cols: 3, rows: 2, y: 0, x: 0 },
|
||||||
{ cols: 2, rows: 2, y: 0, x: 3 },
|
{ 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 }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<div class="almanac-content">
|
||||||
|
<div *ngIf="!loaded">
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
<div *ngIf="loaded">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="almanac-table-header">
|
||||||
|
Sunrise
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ sun.sunrise | amLocal | amDateFormat: 'hh:mm:ss A' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="almanac-table-header">
|
||||||
|
Sunset
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ sun.sunset | amLocal | amDateFormat: 'hh:mm:ss A' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="almanac-table-header">
|
||||||
|
Moon
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ moonPhaseName(moon.phase) }} - {{ (moon.fraction * 100).toFixed(0) }}% illuminated
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.almanac-content {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.almanac-table-header {
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
@@ -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<AlmanacComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [AlmanacComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AlmanacComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user