From bc7163a87c9782443f1e3d90a84d82b37a5268f1 Mon Sep 17 00:00:00 2001 From: y509144 <120079825+y509144@users.noreply.github.com> Date: Tue, 17 Jan 2023 18:50:46 +0530 Subject: [PATCH] Add files via upload --- weather-forecast-widget/public_api.ts | 18 +++ .../weather-forecast-widget.component.css | 24 +++ .../weather-forecast-widget.component.html | 42 ++++++ .../weather-forecast-widget.component.ts | 142 ++++++++++++++++++ ...ther-forecast-widget.config.component.html | 35 +++++ ...eather-forecast-widget.config.component.ts | 59 ++++++++ .../weather-forecast-widget.module.ts | 44 ++++++ 7 files changed, 364 insertions(+) create mode 100644 weather-forecast-widget/public_api.ts create mode 100644 weather-forecast-widget/weather-forecast-widget.component.css create mode 100644 weather-forecast-widget/weather-forecast-widget.component.html create mode 100644 weather-forecast-widget/weather-forecast-widget.component.ts create mode 100644 weather-forecast-widget/weather-forecast-widget.config.component.html create mode 100644 weather-forecast-widget/weather-forecast-widget.config.component.ts create mode 100644 weather-forecast-widget/weather-forecast-widget.module.ts diff --git a/weather-forecast-widget/public_api.ts b/weather-forecast-widget/public_api.ts new file mode 100644 index 0000000..8769073 --- /dev/null +++ b/weather-forecast-widget/public_api.ts @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2019 Software AG, Darmstadt, Germany and/or its licensors +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ +export { WeatherForecastWidgetModule } from "./weather-forecast-widget.module"; diff --git a/weather-forecast-widget/weather-forecast-widget.component.css b/weather-forecast-widget/weather-forecast-widget.component.css new file mode 100644 index 0000000..100534e --- /dev/null +++ b/weather-forecast-widget/weather-forecast-widget.component.css @@ -0,0 +1,24 @@ +.weather-forecast-container { + display: flex; + justify-content: center; +} + +.weather-group { + float: left; + margin-left: 10px; + margin-right: 10px; +} + +.weather-image-container, .weather-date-container { + padding-right: 3px; + text-align: center; +} + +.weather-attribute-title { + padding-right: 3px; + text-align: right; +} + +.weather-image-container img { + height: 65px; +} \ No newline at end of file diff --git a/weather-forecast-widget/weather-forecast-widget.component.html b/weather-forecast-widget/weather-forecast-widget.component.html new file mode 100644 index 0000000..2a9edd8 --- /dev/null +++ b/weather-forecast-widget/weather-forecast-widget.component.html @@ -0,0 +1,42 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ {{weather.date| date:'EEE dd-MMM'}} +
+ Outlook: + {{weather.desc}}
+ Temperature: + {{weather.temp | number:"1.0-0"}}C
+ Humidity: + {{weather.humidity}}%
+ Wind: + {{weather.wind.speed | number:"1.0-0"}}mph
+
+
+
diff --git a/weather-forecast-widget/weather-forecast-widget.component.ts b/weather-forecast-widget/weather-forecast-widget.component.ts new file mode 100644 index 0000000..6d75ca4 --- /dev/null +++ b/weather-forecast-widget/weather-forecast-widget.component.ts @@ -0,0 +1,142 @@ +/* +* Copyright (c) 2019 Software AG, Darmstadt, Germany and/or its licensors +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ +import { Component, Inject, Injectable, Input, OnDestroy } from '@angular/core'; +import { Realtime, InventoryService } from '@c8y/client'; +import * as _ from 'lodash'; +// import { HttpClient } from "@angular/common/http"; + +@Component({ + templateUrl: './weather-forecast-widget.component.html', + styleUrls: ['./weather-forecast-widget.component.css'], +}) + +// @Injectable({providedIn:"root"}) +export class WeatherForecastWidget implements OnDestroy { + + widgetConfiguration: any; + weather_forecast: any = []; + forecastRefreshTimer: any; + + @Input() set config(newConfig: any) { + this.widgetConfiguration = newConfig; + if( !_.has(this.widgetConfiguration, `weatherAPIConfig.period`) + || this.widgetConfiguration.weatherAPIConfig.period <= 0 ) { + this.widgetConfiguration.weatherAPIConfig.period = 12; + } + this.updateForDeviceChange( this.widgetConfiguration ); + } + + constructor( + // private http: HttpClient, + // private realtime: Realtime, + private invSvc: InventoryService) { } + + ngOnDestroy(): void { + clearInterval(this.forecastRefreshTimer); + } + + private updateForDeviceChange(config) { + // Get the weather forecast data, and filter/transform it + (async () => { + await this.getDeviceLocation( _.get(this.widgetConfiguration, 'device.id') ); + await this.updateForecast(); + this.forecastRefreshTimer = setInterval( async () => { + await this.updateForecast(); + }, this.widgetConfiguration.weatherAPIConfig.period*60*60*1000); + })(); + } + + private async updateForecast() { + const parent = this; + + try { + let getForecastResponse: any; + await this.getForecast(this.widgetConfiguration).then((response)=> response.json()).then((data) => { + getForecastResponse = data; + }); + if (getForecastResponse == undefined || !_.has(getForecastResponse, `list`)) { + return; + } + + parent.weather_forecast = []; + let allWeather = _.get(getForecastResponse, `list`) + allWeather.forEach(function (item) { + if ((item.dt_txt !== undefined) + && (item.dt_txt.includes('12:00:00'))) { + + let currVal = {}; + currVal.date = item.dt_txt.substring(0, 10) + currVal.temp = item.main.temp; + currVal.min_temp = item.main.temp_min; + currVal.max_temp = item.main.temp_max; + currVal.pressure = item.main.pressure; + currVal.humidity = item.main.humidity; + currVal.wind = item.wind; + currVal.overview = item.weather[0].main; + currVal.desc = item.weather[0].description; + currVal.icon = item.weather[0].icon; + + parent.weather_forecast.push(currVal); + } + }); + } catch(error) { + console.error(error); + } + } + + private getForecast(loc: string) { + if ( this.widgetConfiguration.weatherAPIConfig.city ) { + // return this.http.get(`https://api.openweathermap.org/data/2.5/forecast?q=${this.widgetConfiguration.weatherAPIConfig.city}&units=metric&appid=${this.widgetConfiguration.weatherAPIConfig.apikey}`) + return fetch(`https://api.openweathermap.org/data/2.5/forecast?q=${this.widgetConfiguration.weatherAPIConfig.city}&units=metric&appid=${this.widgetConfiguration.weatherAPIConfig.apikey}`); + } else if( this.widgetConfiguration.weatherAPIConfig.latitude && this.widgetConfiguration.weatherAPIConfig.longitude ) { + // return this.http.get(`https://api.openweathermap.org/data/2.5/forecast?lat=${this.widgetConfiguration.weatherAPIConfig.latitude}&lon=${this.widgetConfiguration.weatherAPIConfig.longitude}&units=metric&appid=${this.widgetConfiguration.weatherAPIConfig.apikey}`) + return fetch(`https://api.openweathermap.org/data/2.5/forecast?lat=${this.widgetConfiguration.weatherAPIConfig.latitude}&lon=${this.widgetConfiguration.weatherAPIConfig.longitude}&units=metric&appid=${this.widgetConfiguration.weatherAPIConfig.apikey}`); + } else { + console.log("Weather Widget configuration was not set correctly.") + } + } + + private async getDeviceLocation(deviceId: String) { + if( deviceId ) { + const mo = await this.getTargetObject(deviceId); + if (mo && mo.c8y_Position) { + // console.log("Position:" + mo.c8y_Position); + this.widgetConfiguration.weatherAPIConfig.latitude = mo.c8y_Position.lat; + this.widgetConfiguration.weatherAPIConfig.longitude = mo.c8y_Position.lng; + } else if (this.widgetConfiguration.weatherAPIConfig.city === undefined || + this.widgetConfiguration.weatherAPIConfig.city === '') { + // if the device doesn't have a location, default to London + console.log(`The device selected for the Weather widget does not have a location, defaulting weather widget to 'London'`); + this.widgetConfiguration.weatherAPIConfig.city = 'London'; + } + } + } + + private getTargetObject(deviceId: String): Promise { + return new Promise( (resolve, reject) => { + this.invSvc.detail(deviceId) + .then( (resp) => { + if (resp.res.status == 200) { + resolve(resp.data); + } else { + reject(resp); + } + }); + }); + } +} diff --git a/weather-forecast-widget/weather-forecast-widget.config.component.html b/weather-forecast-widget/weather-forecast-widget.config.component.html new file mode 100644 index 0000000..3016faa --- /dev/null +++ b/weather-forecast-widget/weather-forecast-widget.config.component.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/weather-forecast-widget/weather-forecast-widget.config.component.ts b/weather-forecast-widget/weather-forecast-widget.config.component.ts new file mode 100644 index 0000000..18fa38a --- /dev/null +++ b/weather-forecast-widget/weather-forecast-widget.config.component.ts @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2019 Software AG, Darmstadt, Germany and/or its licensors +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ +import { Component, Input, OnInit } from "@angular/core"; +import { ControlContainer, NgForm } from "@angular/forms"; +import * as _ from 'lodash'; + +@Component({ + selector: 'weather-forecast-widget-config-component', + templateUrl: './weather-forecast-widget.config.component.html', + viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] +}) + +export class WeatherForecastWidgetConfig implements OnInit { + + @Input() config: any = {}; + + weatherAPIConfig = { + apikey: '', + latitude: '', + longitude: '', + city: '', + period: '' + }; + + ngOnInit(): void { + this.initConfig(); + } + + private initConfig(): void { + if (!this.config) { + return; + } + + if (_.has(this.config, 'weatherAPIConfig')) { + this.weatherAPIConfig = _.get(this.config, 'weatherAPIConfig'); + }} + + onConfigChanged($event: Event): void { + if (!this.weatherAPIConfig.apikey ) { + return; + } + _.set(this.config, 'weatherAPIConfig', { ...this.weatherAPIConfig }); + } +} \ No newline at end of file diff --git a/weather-forecast-widget/weather-forecast-widget.module.ts b/weather-forecast-widget/weather-forecast-widget.module.ts new file mode 100644 index 0000000..6678e41 --- /dev/null +++ b/weather-forecast-widget/weather-forecast-widget.module.ts @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2019 Software AG, Darmstadt, Germany and/or its licensors +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ +import { CoreModule, HOOK_COMPONENTS } from "@c8y/ngx-components"; +import { WeatherForecastWidgetConfig } from "./weather-forecast-widget.config.component"; +import { WeatherForecastWidget } from "./weather-forecast-widget.component"; +import { NgModule } from "@angular/core"; +import { HttpClientModule } from "@angular/common/http"; + +@NgModule({ + imports: [ + CoreModule, + HttpClientModule + ], + declarations: [WeatherForecastWidget, WeatherForecastWidgetConfig], + entryComponents: [WeatherForecastWidget, WeatherForecastWidgetConfig], + providers: [{ + provide: HOOK_COMPONENTS, + multi: true, + useValue: { + id: 'global.presales.weather.forecast.widget', + label: 'Weather Forecast', + description: 'Provides a 5-day weather forecast using OpenWeatherAPI', + component: WeatherForecastWidget, + configComponent: WeatherForecastWidgetConfig, + previewImage: require("../styles/previewImage.png") + } + }], +}) +export class WeatherForecastWidgetModule {}