save data to sqlite

This commit is contained in:
Evert Prants 2023-09-17 09:54:01 +03:00
parent 11e1d1b468
commit 53d7efc20a
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
6 changed files with 942 additions and 64 deletions

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
# compiled output # compiled output
/dist /dist
/node_modules /node_modules
*.sqlite
# Logs # Logs
logs logs
@ -32,4 +33,4 @@ lerna-debug.log*
!.vscode/settings.json !.vscode/settings.json
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json

View File

@ -25,9 +25,12 @@
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/schedule": "^3.0.3", "@nestjs/schedule": "^3.0.3",
"@nestjs/typeorm": "^10.0.0",
"cache-manager": "^5.2.3", "cache-manager": "^5.2.3",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"sqlite3": "^5.1.6",
"typeorm": "^0.3.17",
"usb": "^2.10.0" "usb": "^2.10.0"
}, },
"devDependencies": { "devDependencies": {

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,24 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller'; import { AppController } from './app.controller';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { CacheModule } from '@nestjs/cache-manager'; import { CacheModule } from '@nestjs/cache-manager';
import { TypeOrmModule } from '@nestjs/typeorm';
import { join } from 'path';
import { WeatherEntity } from './entities/weather.entity';
@Module({ @Module({
imports: [CacheModule.register()], imports: [
CacheModule.register(),
TypeOrmModule.forRoot({
type: 'sqlite',
database: join(process.cwd(), 'data.sqlite'),
entities: [WeatherEntity],
synchronize: true,
}),
TypeOrmModule.forFeature([WeatherEntity]),
ScheduleModule.forRoot(),
],
controllers: [AppController], controllers: [AppController],
providers: [AppService], providers: [AppService],
}) })

View File

@ -1,13 +1,70 @@
import { Injectable, OnApplicationShutdown } from '@nestjs/common'; import {
Injectable,
InternalServerErrorException,
Logger,
OnApplicationShutdown,
} from '@nestjs/common';
import WS1080 from './module/ws1080'; import WS1080 from './module/ws1080';
import { Repository } from 'typeorm';
import { WeatherEntity } from './entities/weather.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Cron } from '@nestjs/schedule';
@Injectable() @Injectable()
export class AppService implements OnApplicationShutdown { export class AppService implements OnApplicationShutdown {
private logger = new Logger(AppService.name);
public station?: WS1080; public station?: WS1080;
constructor(
@InjectRepository(WeatherEntity)
private readonly weatherRepository: Repository<WeatherEntity>,
) {}
async getWeather() { async getWeather() {
if (!this.station) this.station = WS1080.fromDevice(); try {
return this.station.read(); // Retrieve from USB
if (!this.station) this.station = WS1080.fromDevice();
const data = await this.station.read();
// Save weather data to database
const entity = this.weatherRepository.create({
date: new Date(),
...data,
});
await this.weatherRepository.save(entity);
entity.fresh = true;
return entity;
} catch (error) {
// USB errors likely mean we are not connected anymore
if (error.message?.includes('USB')) {
try {
this.station?.close();
} catch {}
this.station = null;
}
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,
});
if (!previous) throw new InternalServerErrorException();
previous.fresh = false;
return previous;
}
}
@Cron('0 * * * *')
scheduledPulls() {
this.getWeather().catch(() => {
// do nothing
});
} }
onApplicationShutdown() { onApplicationShutdown() {

View File

@ -0,0 +1,48 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class WeatherEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: Date })
date: Date;
@Column({ nullable: true })
indoorHumidity: number;
@Column({ nullable: true })
outdoorHumidity: number;
@Column({ nullable: true })
indoorTemperature: number;
@Column({ nullable: true })
outdoorTemperature: number;
@Column({ nullable: true })
outdoorDewPoint: number;
@Column({ nullable: true })
windChillTemp: number;
@Column({ nullable: true })
windSpeed: number;
@Column({ nullable: true })
gustSpeed: number;
@Column({ nullable: true })
windDirection: string;
@Column({ nullable: true })
rainDiff: number;
@Column({ nullable: true })
totalRain: number;
@Column({ nullable: true })
absPressure: number;
fresh?: boolean;
}