Skip to content

Commit

Permalink
feat: make sondehub uploader library working
Browse files Browse the repository at this point in the history
  • Loading branch information
raska-vilem committed Jan 24, 2025
1 parent 39217e4 commit 627c2df
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 80 deletions.
10 changes: 8 additions & 2 deletions GAPP/apps/gapp-server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { app } from './app/app';
import { getConfig } from './config';
import { Uploader } from '@gapp/sondehub';

const uploader = new Uploader({ uploaderCallsign: 'node-sondehub', uploaderPosition: [50.01, 15.01, 200] });
const uploader = new Uploader({ uploader_callsign: 'node-sondehub' });

uploader.addTelemetry({
payload_callsign: 'test-payload',
payload_callsign: 'cesilko-payload',
datetime: new Date().toISOString(),
lat: 50,
lon: 15,
Expand All @@ -15,6 +15,12 @@ uploader.addTelemetry({

uploader.uploadTelemetry();

uploader.uploadStationPosition({
uploader_callsign: 'cesilko-car',
uploader_position: [50.01, 15.01, 185],
mobile: true
});

const config = getConfig(process.env);

const server = Fastify({
Expand Down
154 changes: 76 additions & 78 deletions GAPP/libs/sondehub/src/lib/uploader.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,76 @@
// Import required modules
import axios from 'axios';
import { gzipSync } from 'node:zlib';

export type Position = [number, number, number];
// Base interface containing common properties
interface BasePacket {
software_name: string;
software_version: string;
uploader_callsign: string;
uploader_position?: [number, number, number];
uploader_antenna?: string;
}

interface TelemetryPacket {
// Telemetry packet interface
interface TelemetryPacket extends Partial<BasePacket> {
dev?: string;
time_received?: string; // ISO 8601 timestamp
payload_callsign: string;
datetime: string;
datetime: string; // ISO 8601 timestamp
lat: number;
lon: number;
alt: number;
frame?: number;
time_received?: string;
sats?: number;
batt?: number;
frequency?: number;
temp?: number;
humidity?: number;
pressure?: number;
vel_h?: number;
vel_v?: number;
pressure?: number;
heading?: number;
tx_frequency?: number;
modulation?: string;
batt?: number;
sats?: number;
snr?: number;
frequency?: number;
rssi?: number;
uploader_callsign?: string;
uploader_position?: Position;
telemetry_hidden?: boolean;
historical?: boolean;
upload_time?: string; // ISO 8601 timestamp
}

type StationBasePayload = Partial<Omit<BasePacket, 'uploader_callsign' | 'uploader_position'>> &
Required<Pick<BasePacket, 'uploader_callsign' | 'uploader_position'>>;

// Station position packet interface
interface StationPositionPacket extends StationBasePayload {
uploader_radio?: string;
uploader_antenna?: string;
software_name?: string;
software_version?: string;
[key: string]: any;
uploader_contact_email?: string;
mobile?: boolean;
}

interface UploaderConfig {
uploaderCallsign: string;
uploaderPosition?: Position;
uploaderRadio?: string;
uploaderAntenna?: string;
softwareName: string;
softwareVersion: string;
interface UploaderConfig extends BasePacket {
uploadRate: number;
uploadTimeout: number;
uploadRetries: number;
developerMode: boolean;
dev: boolean;
}

export type UploaderOptions = Partial<Omit<UploaderConfig, 'uploaderCallsign'>> & Pick<UploaderConfig, 'uploaderCallsign'>;
type MinimalUploaderConfig = Partial<Omit<UploaderConfig, 'uploader_Callsign'>> & Pick<UploaderConfig, 'uploader_callsign'>;

export class Uploader {
private uploaderConfig: UploaderConfig = {
uploaderCallsign: '',
uploader_callsign: '',
uploadRate: 2,
uploadTimeout: 20_000,
uploadRetries: 5,
developerMode: false,
softwareName: 'node-sondehub',
softwareVersion: '0.0.1',
dev: false,
software_name: 'node-sondehub',
software_version: '0.0.1',
};

private inputQueue: TelemetryPacket[] = [];

public static readonly SONDEHUB_AMATEUR_URL = 'https://api.v2.sondehub.org/amateur/telemetry';
public static readonly SONDEHUB_AMATEUR_STATION_POSITION_URL = 'https://api.v2.sondehub.org/amateur/listeners';

constructor(options: UploaderOptions) {
constructor(options: MinimalUploaderConfig) {
this.uploaderConfig = {
...this.uploaderConfig,
...options,
Expand Down Expand Up @@ -101,10 +106,9 @@ export class Uploader {
this.inputQueue = [];

try {
console.log(packets);
const compressedPayload = gzipSync(JSON.stringify(packets));
const headers = {
'User-Agent': `${this.uploaderConfig.softwareName}-${this.uploaderConfig.softwareVersion}`,
'User-Agent': `${this.uploaderConfig.software_name}-${this.uploaderConfig.software_version}`,
'Content-Encoding': 'gzip',
'Content-Type': 'application/json',
};
Expand All @@ -125,58 +129,52 @@ export class Uploader {
}
}

// public async uploadStationPosition(
// callsign: string,
// position: Position,
// radio?: string,
// antenna?: string,
// contactEmail?: string,
// mobile = false
// ): Promise<void> {
// const payload = {
// software_name: this.softwareName,
// software_version: this.softwareVersion,
// uploader_callsign: callsign,
// uploader_position: position,
// uploader_radio: radio || this.uploaderRadio,
// uploader_antenna: antenna || this.uploaderAntenna,
// uploader_contact_email: contactEmail || '',
// mobile,
// dev: this.developerMode,
// };

// try {
// const response = await axios.put(Uploader.SONDEHUB_AMATEUR_STATION_POSITION_URL, payload, {
// headers: {
// 'User-Agent': `${this.softwareName}-${this.softwareVersion}`,
// 'Content-Type': 'application/json',
// },
// timeout: this.uploadTimeout * 1000,
// });

// if (response.status === 200) {
// this.logInfo('Station position uploaded successfully.');
// } else {
// this.logError(`Failed to upload station position. Status: ${response.status}, Message: ${response.statusText}`);
// }
// } catch (error) {
// this.logError(`Error uploading station position: ${error}`);
// }
// }
//
public async uploadStationPosition(stationPacket: StationPositionPacket): Promise<void> {
const payload = {
software_name: this.uploaderConfig.software_name,
software_version: this.uploaderConfig.software_version,
uploader_callsign: stationPacket.uploader_callsign,
uploader_position: stationPacket.uploader_position,
uploader_radio: stationPacket.uploader_radio,
uploader_antenna: stationPacket.uploader_antenna || this.uploaderConfig.uploader_antenna,
uploader_contact_email: stationPacket.uploader_contact_email,
mobile: stationPacket.mobile ?? false,
dev: this.uploaderConfig.dev,
};

try {
const compressedPayload = gzipSync(JSON.stringify(payload));
const headers = {
'User-Agent': `${this.uploaderConfig.software_name}-${this.uploaderConfig.software_version}`,
'Content-Encoding': 'gzip',
'Content-Type': 'application/json',
};
const response = await axios.put(Uploader.SONDEHUB_AMATEUR_STATION_POSITION_URL, compressedPayload, {
headers,
timeout: this.uploaderConfig.uploadTimeout,
});

if (response.status === 200) {
this.logInfo('Station position uploaded successfully.');
} else {
this.logError(`Failed to upload station position. Status: ${response.status}, Message: ${response.statusText}`);
}
} catch (error) {
this.logError(`Error uploading station position: ${error}`);
}
}

private enhanceTelemetryPacket(packet: TelemetryPacket): TelemetryPacket {
console.log('Config: ', this.uploaderConfig);
const enhancedPacket = { ...packet };
enhancedPacket.software_name = this.uploaderConfig.softwareName;
enhancedPacket.software_version = this.uploaderConfig.softwareVersion;
enhancedPacket.software_name = this.uploaderConfig.software_name;
enhancedPacket.software_version = this.uploaderConfig.software_version;

if (!packet.uploader_callsign) {
enhancedPacket.uploader_callsign = this.uploaderConfig.uploaderCallsign;
enhancedPacket.uploader_callsign = this.uploaderConfig.uploader_callsign;
}

if (!packet.uploader_position) {
enhancedPacket.uploader_position = this.uploaderConfig.uploaderPosition;
enhancedPacket.uploader_position = this.uploaderConfig.uploader_position;
}

if (!packet.time_received) {
Expand Down

0 comments on commit 627c2df

Please sign in to comment.