import { Injectable, InternalServerErrorException, Logger, OnApplicationShutdown, } from '@nestjs/common'; import WS1080 from './module/ws1080'; import { 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'; @Injectable() export class AppService implements OnApplicationShutdown { private logger = new Logger(AppService.name); public station?: WS1080; constructor( @InjectRepository(WeatherEntity) private readonly weatherRepository: Repository, ) {} async getWeather() { try { // 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; } } async getWeatherHistory(query: HistoryQueryDto) { 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, order: { date: -1 }, take: pageSize, skip: (page - 1) * pageSize, }); const pageCount = Math.ceil(rowCount / pageSize); return { list, pagination: { page, pageSize, pageCount, rowCount, }, }; } @Cron('0 * * * *') scheduledPulls() { this.getWeather().catch(() => { // do nothing }); } onApplicationShutdown() { this.station?.close(); } }