graph query
This commit is contained in:
parent
1ec89c72c1
commit
feb6ba49ed
@ -2,6 +2,7 @@ import { Controller, Get, Query, UseInterceptors } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
import { CacheInterceptor, CacheTTL } from '@nestjs/cache-manager';
|
||||
import { HistoryQueryDto } from './dtos/history-query.dto';
|
||||
import { GraphQueryDto } from './dtos/graph-query.dto';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
@ -18,4 +19,9 @@ export class AppController {
|
||||
getWeatherHistory(@Query() query: HistoryQueryDto) {
|
||||
return this.appService.getWeatherHistory(query);
|
||||
}
|
||||
|
||||
@Get('graph')
|
||||
makeGraph(@Query() query: GraphQueryDto) {
|
||||
return this.appService.graphWeatherHistory(query);
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,12 @@ import {
|
||||
OnApplicationShutdown,
|
||||
} from '@nestjs/common';
|
||||
import WS1080 from './module/ws1080';
|
||||
import { MoreThan, Repository } from 'typeorm';
|
||||
import { Between, LessThan, MoreThan, Repository } from 'typeorm';
|
||||
import { WeatherEntity } from './entities/weather.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Cron } from '@nestjs/schedule';
|
||||
import { HistoryQueryDto } from './dtos/history-query.dto';
|
||||
import { GraphQueryDto } from './dtos/graph-query.dto';
|
||||
|
||||
@Injectable()
|
||||
export class AppService implements OnApplicationShutdown {
|
||||
@ -21,10 +22,14 @@ export class AppService implements OnApplicationShutdown {
|
||||
private readonly weatherRepository: Repository<WeatherEntity>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get current weather information.
|
||||
* @returns Weather data
|
||||
*/
|
||||
async getWeather() {
|
||||
try {
|
||||
// Retrieve from USB
|
||||
if (!this.station) this.station = WS1080.fromDevice();
|
||||
await this.createStation();
|
||||
const data = await this.station.read();
|
||||
|
||||
// Save weather data to database
|
||||
@ -50,26 +55,54 @@ export class AppService implements OnApplicationShutdown {
|
||||
this.logger.error('Failed to retrieve weather data:', error.stack);
|
||||
|
||||
// Retrieve previous entry on error
|
||||
const [previous] = await this.weatherRepository.find({
|
||||
order: { date: -1 },
|
||||
take: 1,
|
||||
});
|
||||
|
||||
const previous = await this.getPreviousEntry();
|
||||
if (!previous) throw new InternalServerErrorException();
|
||||
|
||||
previous.rain24h = await this.rainFall24h(previous.date);
|
||||
previous.fresh = false;
|
||||
return previous;
|
||||
}
|
||||
}
|
||||
|
||||
async getWeatherHistory(query: HistoryQueryDto) {
|
||||
/**
|
||||
* Get previous weather entry.
|
||||
* @returns Previous weather data entry
|
||||
*/
|
||||
async getPreviousEntry() {
|
||||
const [previous] = await this.weatherRepository.find({
|
||||
order: { date: -1 },
|
||||
take: 1,
|
||||
});
|
||||
|
||||
if (!previous) return null;
|
||||
|
||||
previous.rain24h = await this.rainFall24h(previous.date);
|
||||
previous.fresh = false;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get weather history.
|
||||
* @param query Weather history search
|
||||
* @returns Paginated history list
|
||||
*/
|
||||
async getWeatherHistory(
|
||||
query: HistoryQueryDto,
|
||||
select?: (keyof WeatherEntity)[],
|
||||
) {
|
||||
const pageSize = Number(query.pageSize) || 100;
|
||||
const page = Number(query.page) || 1;
|
||||
const [list, rowCount] = await this.weatherRepository.findAndCount({
|
||||
where: query.since
|
||||
? { date: MoreThan(new Date(query.since)) }
|
||||
: undefined,
|
||||
select,
|
||||
where:
|
||||
query.since || query.until
|
||||
? {
|
||||
date:
|
||||
query.since && query.until
|
||||
? Between(new Date(query.since), new Date(query.until))
|
||||
: query.since
|
||||
? MoreThan(new Date(query.since))
|
||||
: LessThan(new Date(query.until)),
|
||||
}
|
||||
: undefined,
|
||||
order: { date: -1 },
|
||||
take: pageSize,
|
||||
skip: (page - 1) * pageSize,
|
||||
@ -87,6 +120,42 @@ export class AppService implements OnApplicationShutdown {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get graph datasets for weather.
|
||||
* @param query Weather history search
|
||||
* @returns Paginated graph dataset
|
||||
*/
|
||||
async graphWeatherHistory(query: GraphQueryDto) {
|
||||
const { list, pagination } = await this.getWeatherHistory(query, [
|
||||
...(query.columns as (keyof WeatherEntity)[]),
|
||||
'date',
|
||||
]);
|
||||
|
||||
const datasets = query.columns.reduce(
|
||||
(mass, key: keyof WeatherEntity) => ({
|
||||
...mass,
|
||||
[key]: { label: String(key), data: [] },
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
list.forEach((entry) => {
|
||||
Object.keys(entry)
|
||||
.filter((key) => !['id', 'date'].includes(key))
|
||||
.forEach((key) => {
|
||||
datasets[key].data.push({
|
||||
x: entry.date.getTime(),
|
||||
y: entry[key],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
list: Object.values(datasets),
|
||||
pagination,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rainfall in the last 24h since `since` start point.
|
||||
* @param since Time start point
|
||||
@ -103,6 +172,19 @@ export class AppService implements OnApplicationShutdown {
|
||||
return Number(rainfall) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create station instance.
|
||||
*/
|
||||
async createStation() {
|
||||
if (this.station) return;
|
||||
this.station = WS1080.fromDevice();
|
||||
|
||||
const previous = await this.getPreviousEntry();
|
||||
if (previous) {
|
||||
this.station.previousRain = previous.totalRain;
|
||||
}
|
||||
}
|
||||
|
||||
@Cron('0 * * * *')
|
||||
scheduledPulls() {
|
||||
this.getWeather().catch(() => {
|
||||
|
5
src/dtos/graph-query.dto.ts
Normal file
5
src/dtos/graph-query.dto.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { HistoryQueryDto } from './history-query.dto';
|
||||
|
||||
export interface GraphQueryDto extends HistoryQueryDto {
|
||||
columns: string[];
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
export class HistoryQueryDto {
|
||||
since?: string;
|
||||
until?: string;
|
||||
page?: string;
|
||||
pageSize?: string;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const app = await NestFactory.create(AppModule, { cors: true });
|
||||
await app.listen(3000);
|
||||
}
|
||||
bootstrap();
|
||||
|
@ -44,7 +44,7 @@ const WIND_DIRS = [
|
||||
* Then remove your device from your machine and plug it back in again
|
||||
*/
|
||||
class WS1080 {
|
||||
private previousRain = 0;
|
||||
public previousRain = 0;
|
||||
|
||||
constructor(private device: Device, private dInterface: Interface) {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user