Skip to content

Commit

Permalink
Update to v0.1.0-beta (#6)
Browse files Browse the repository at this point in the history
* Remove pi api key for weather and ipGeolocation

* Add local weather

* Add settings and allow hide pages

* Add piSensor for collecting data on Rasp-pi with DHT11

* Change port for nginx

* Fix missing arguments

* Fix missing argument for sleep

* Fix media type for put request

* Add autostart script

* Update README.md to include piSensor
  • Loading branch information
rssws authored Jun 25, 2022
1 parent 0f32a66 commit 34363bd
Show file tree
Hide file tree
Showing 39 changed files with 814 additions and 133 deletions.
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
VERSION='0.0.9'
VERSION='0.1.0-beta'
OPEN_WEATHER_API='YOUR-KEY-GOES-HERE'
PI_API='324cj2io3WRjrc'
PI_API="a10d052a-4133-4e50-80e8-b8e1adb2f7c6"
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,14 @@ Prerequisites: `docker` (and `docker compose`)
This project can work with their free plan. Use it for non-commercial purposes!

3. Get the docker images:

1. Pull the image directly:

```bash
docker compose pull
```
**Docker Hub:**

**Docker Hub:**
[pi-client](https://hub.docker.com/repository/docker/rssws/pi-client),
[pi-service](https://hub.docker.com/repository/docker/rssws/pi-service)

Expand All @@ -121,8 +122,8 @@ Prerequisites: `docker` (and `docker compose`)
docker compose up -d
```

Then you can access the frontend via `http://localhost:80`
and the backend via `http://localhost:80/api/`.
Then you can access the frontend via `http://localhost:31414`
and the backend via `http://localhost:31414/api/`.

If you want to set up an SSL connection and change the domain name from `localhost` to your own domain,
edit the Nginx configuration file `nginx.conf`.
Expand Down Expand Up @@ -159,6 +160,18 @@ Use `mvn spring-boot:run -Dspring-boot.run.profiles=dev` to launch the server wi
You might need to create this file first and specify the `apiKey`.
Use `application-prod.yml` as a template.

#### piSensor

Starting from `v0.1.0-beta`, we added a new functionality called "local weather".

The idea is to turn your raspberry pi into a temperature and humidity sensor with DHT11.
The script will send the collected data to `piService`, which will be shown in `piClient`.

The monitor page for local weather is hidden in `piClient` by default.
Click on the "setting" to turn it on.

Check more details [here](./piSensor/README.md).

## Gallery

Let's see some pictures taken from the raspberry pi.
Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ services:
nginx:
image: nginx:latest
ports:
- "80:80"
- "31414:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
restart: on-failure
Expand All @@ -14,7 +14,6 @@ services:
build:
context: ./piClient
args:
PI_API: "${PI_API}"
VERSION: "${VERSION}"
image: rssws/pi-client:${VERSION}
restart: on-failure
Expand Down
1 change: 0 additions & 1 deletion piClient/.env.development
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
NG_APP_PI_API=$PI_API
1 change: 0 additions & 1 deletion piClient/.env.production
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
NG_APP_PI_API=$PI_API
2 changes: 0 additions & 2 deletions piClient/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ FROM node:lts-alpine as build
# set working directory
WORKDIR /build

ARG PI_API
ENV PI_API $PI_API
ARG VERSION

ENV PATH /app/node_modules/.bin:$PATH
Expand Down
1 change: 1 addition & 0 deletions piClient/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"chart.js": "^3.8.0",
"material-design-icons": "^3.0.1",
"ng2-charts": "^3.0.11",
"ngx-cookie-service": "^14.0.0",
"rxjs": "~7.5.5",
"zone.js": "~0.11.5"
},
Expand Down
7 changes: 6 additions & 1 deletion piClient/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { WeatherDefaultComponent } from './weather/weather-default/weather-defau
import { NgChartsModule } from 'ng2-charts';
import { WeatherSevenDayChartComponent } from './weather/weather-seven-day-chart/weather-seven-day-chart.component';
import { WeatherHourlyChartComponent } from './weather/weather-hourly-chart/weather-hourly-chart.component';
import { WeatherLocalComponent } from './weather/weather-local/weather-local.component';
import { SettingsComponent } from './settings/settings.component';
import { CookieService } from 'ngx-cookie-service';

@NgModule({
declarations: [
Expand All @@ -19,9 +22,11 @@ import { WeatherHourlyChartComponent } from './weather/weather-hourly-chart/weat
WeatherDefaultComponent,
WeatherSevenDayChartComponent,
WeatherHourlyChartComponent,
WeatherLocalComponent,
SettingsComponent,
],
imports: [BrowserModule, HttpClientModule, AppRoutingModule, NgChartsModule],
providers: [],
providers: [CookieService],
bootstrap: [AppComponent],
})
export class AppModule {}
20 changes: 20 additions & 0 deletions piClient/src/app/model/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export class Settings {
display: {
weatherDefault: {
show: boolean;
index: number;
};
weatherHourly: {
show: boolean;
index: number;
};
weatherDaily: {
show: boolean;
index: number;
};
weatherLocal: {
show: boolean;
index: number;
};
};
}
8 changes: 8 additions & 0 deletions piClient/src/app/navigation/navigation.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,11 @@
font-size: 4vh;
}

.btn {
line-height: 0;
}

#nav-bar {
z-index: 10000;
position: relative;
}
6 changes: 5 additions & 1 deletion piClient/src/app/navigation/navigation.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<div class="container-fluid bg-dark text-light h-100">
<div class="container-fluid bg-dark text-light h-100" id="nav-bar">
<div class="d-flex p-0 justify-content-between align-items-center h-100">
<div class="d-flex p-0 justify-content-center align-items-center">
<h5 class="m-0 navigation-text" style="font-size: 5vh">PiWeather</h5>
<div class="badge bg-primary ml-2 navigation-text">V {{ version }}</div>
<button type="button" class="btn btn-secondary ml-2 p-1" data-toggle="modal" data-target="#staticBackdrop">
<i class="material-icons navigation-text">settings</i>
</button>
<app-settings></app-settings>
</div>
<h5 class="m-0 navigation-text" style="font-size: 5vh">{{ today | date: 'medium' }}</h5>
</div>
Expand Down
Empty file.
71 changes: 71 additions & 0 deletions piClient/src/app/settings/settings.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<div
class="modal fade"
id="staticBackdrop"
data-backdrop="static"
data-keyboard="false"
tabindex="-1"
aria-labelledby="staticBackdropLabel"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Settings</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h5>Display</h5>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value=""
id="weather-default"
[checked]="settings.display.weatherDefault.show"
(change)="settings.display.weatherDefault.show = !settings.display.weatherDefault.show"
/>
<label class="form-check-label" for="weather-default"> Weather Default </label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value=""
id="weather-hourly"
[checked]="settings.display.weatherHourly.show"
(change)="settings.display.weatherHourly.show = !settings.display.weatherHourly.show"
/>
<label class="form-check-label" for="weather-hourly"> Weather Hourly </label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value=""
id="weather-daily"
[checked]="settings.display.weatherDaily.show"
(change)="settings.display.weatherDaily.show = !settings.display.weatherDaily.show"
/>
<label class="form-check-label" for="weather-daily"> Weather Daily </label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value=""
id="weather-local"
[checked]="settings.display.weatherLocal.show"
(change)="settings.display.weatherLocal.show = !settings.display.weatherLocal.show"
/>
<label class="form-check-label" for="weather-local"> Weather Local </label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" (click)="save()">Save</button>
</div>
</div>
</div>
</div>
22 changes: 22 additions & 0 deletions piClient/src/app/settings/settings.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { SettingsComponent } from './settings.component';

describe('SettingsComponent', () => {
let component: SettingsComponent;
let fixture: ComponentFixture<SettingsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [SettingsComponent],
}).compileComponents();

fixture = TestBed.createComponent(SettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
24 changes: 24 additions & 0 deletions piClient/src/app/settings/settings.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Component, OnInit } from '@angular/core';
import { CookieService } from 'ngx-cookie-service';
import { Settings } from '../model/settings';

@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.css'],
})
export class SettingsComponent implements OnInit {
settings: Settings;

constructor(private cookieService: CookieService) {}

ngOnInit(): void {
const settingsString = this.cookieService.get('settings');
this.settings = JSON.parse(settingsString);
}

save(): void {
this.cookieService.set('settings', JSON.stringify(this.settings));
window.location.reload();
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import {WeatherResponse} from '../../model/weather/weather-response';
import {WeatherService} from '../weather.service';
import {Coord} from '../../model/weather/coord';
import {ResponseStatus} from '../../model/response-status.enum';
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
import { WeatherResponse } from '../../model/weather/weather-response';
import { WeatherService } from '../weather.service';
import { Coord } from '../../model/weather/coord';

@Component({
selector: 'app-weather-default',
templateUrl: './weather-default.component.html',
styleUrls: ['./weather-default.component.css']
styleUrls: ['./weather-default.component.css'],
})
export class WeatherDefaultComponent implements OnInit, OnChanges{
export class WeatherDefaultComponent implements OnInit, OnChanges {
@Input() weatherResponse: WeatherResponse;
@Input() city: string;
@Input() cityShort: string;
Expand All @@ -20,9 +19,7 @@ export class WeatherDefaultComponent implements OnInit, OnChanges{
cityNameFontSize: string;
errorMessage: string;

constructor(
private weatherService: WeatherService
) { }
constructor(private weatherService: WeatherService) {}

ngOnInit(): void {}

Expand All @@ -40,8 +37,8 @@ export class WeatherDefaultComponent implements OnInit, OnChanges{

updateWeather(): void {
const weatherResponse$ = this.weatherService.getWeatherResponseByCity(this.city);
weatherResponse$
.subscribe(r => {
weatherResponse$.subscribe(
(r) => {
if (r.responseStatus.toString() !== 'SUCCESS') {
this.weatherResponseLoading = true;
this.errorMessage = r.responseMessage;
Expand All @@ -53,11 +50,13 @@ export class WeatherDefaultComponent implements OnInit, OnChanges{
this.prepareFont();
this.weatherResponseLoading = false;
this.errorMessage = undefined;
}, error => {
},
(error) => {
this.weatherResponseLoading = true;
this.errorMessage = error.message;
setTimeout(this.updateWeather.bind(this), 6000);
});
}
);
}

prepareFont(): void {
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<div class="d-flex align-self-stretch justify-content-center" style="height: calc(100% - 5px)">
<div
class="d-flex flex-column align-self-stretch align-items-middle w-100 p-4"
*ngIf="!weatherResponseLoading; else loading"
>
<div class="row row-cols-2">
<div class="col mb-4" *ngIf="localWeatherResponse.responseStatus === 'SUCCESS'">
<div class="card">
<div class="card-body bg-dark">
<h5 class="card-title display-6 bg">{{ localWeatherResponse.weather.description }}</h5>
<p class="m-0 display-5">
{{ localWeatherResponse.weather.temp.toFixed(0).replace('-0', '0') }}℃ /
{{ localWeatherResponse.weather.humidity.toFixed(0).replace('-0', '0') }}%
</p>
</div>
<div class="card-footer bg-secondary">
<small>{{ localWeatherResponse.responseMessage }}</small>
</div>
</div>
</div>
</div>
</div>
<ng-template #loading>
<div class="d-flex flex-column justify-content-center">
<div class="spinner-grow text-light mx-auto" style="width: 3rem; height: 3rem" role="status">
<span class="sr-only">Loading...</span>
</div>
<div class="mx-auto" *ngIf="errorMessage !== undefined">{{ errorMessage }}</div>
</div>
</ng-template>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { WeatherLocalComponent } from './weather-local.component';

describe('WeatherLocalComponent', () => {
let component: WeatherLocalComponent;
let fixture: ComponentFixture<WeatherLocalComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [WeatherLocalComponent],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(WeatherLocalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 34363bd

Please sign in to comment.