sql commands for querying the frequency bands and segments

This commit is contained in:
2026-08-31 13:19:50 +02:00
parent 2aa0ae3d9a
commit 7acb2aabd4
6 changed files with 1580 additions and 4 deletions
+112 -2
View File
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <sqlite3.h>
#include <stdint.h>
#include <hammy/types.h>
@@ -15,14 +16,30 @@
#define HAMMY_CALLSIGN_MAX 32
#define HAMMY_ENTITY_NAME_MAX 64
#define HAMMY_COUNTRY_MAX 4
// Longest code in the morse table is '$' ('...-..-'), seven characters.
#define HAMMY_MORSE_MAX 16
// A country has at most a handful of licence classes, each with at most a
// couple of segments covering one exact frequency. 24 is generous.
#define HAMMY_FREQ_PRIVS_MAX 24
#define HAMMY_FREQ_IARU_MAX 8
#define HAMMY_FREQ_COUNTRIES_MAX 64
struct hammy_refdb_t {
sqlite3* handle;
sqlite3_stmt* stExact;
sqlite3_stmt* stPrefix;
sqlite3_stmt* stMorse;
sqlite3_stmt* stFreqMain;
sqlite3_stmt* stFreqIaru;
sqlite3_stmt* stFreqNearest;
sqlite3_stmt* stFreqSegEdge;
sqlite3_stmt* stCountryKnown;
sqlite3_stmt* stCountryList;
char morseCode[HAMMY_MORSE_MAX]; // Scratch for the last hammy_refdb_get_morse() hit
char version[64];
};
@@ -39,6 +56,64 @@ struct hammy_dxcc_t {
char matchedPrefix[HAMMY_CALLSIGN_MAX];
bool exact;
};
// ---------------------------------------------------------------------------
// Frequency lookup
// ---------------------------------------------------------------------------
struct hammy_freq_priv_t {
char code[8]; // 'E', 'G', 'T'
char name[48]; // 'Amateur Extra'
int rank;
bool permitted; // false = this class may NOT transmit here
char modes[64]; // 'CW,DATA' - empty when !permitted
int64_t segLowHz;
int64_t segHighHz;
int maxPowerW; // 0 = national default, no specific limit
char notes[160];
};
struct hammy_freq_iaru_t {
int region; // 1, 2 or 3
int64_t lowHz;
int64_t highHz;
char modes[32];
};
struct hammy_freq_t {
int64_t freqHz;
bool inBand;
char band[16]; // '20m'
int64_t bandLowHz;
int64_t bandHighHz;
// The frequency sits exactly on a band or segment boundary. Worth saying
// out loud: a signal of any width centred there straddles both sides.
bool atBandEdge;
bool atSegmentEdge;
// False when the bundle carries no licence data for this country at all.
// The band and IARU results are still valid; only the privilege table is
// missing. Say so rather than showing an empty table.
bool countryKnown;
char country[HAMMY_COUNTRY_MAX];
hammy_freq_priv_t privs[HAMMY_FREQ_PRIVS_MAX];
size_t nPrivs;
hammy_freq_iaru_t iaru[HAMMY_FREQ_IARU_MAX];
size_t nIaru;
// Only meaningful when !in_band.
char nearestBand[16];
int64_t nearestLowHz;
int64_t nearestHighHz;
int64_t nearestDistanceHz;
};
// ---------------------------------------------------------------------------
// Lifecycle
// ---------------------------------------------------------------------------
// Opens the bundle read-only and prepares the hot statements.
// Returns NULL and logs on failure.
@@ -47,6 +122,13 @@ hammy_refdb_t* hammy_refdb_open(const char* path);
// Finalises statements and closes the connection. NULLs the passing reference.
bool hammy_refdb_close(hammy_refdb_t** db);
// Bundle version string from ref_meta, or NULL. Owned by the refdb.
const char* hammy_refdb_version(hammy_refdb_t* db);
// ---------------------------------------------------------------------------
// Queries
// ---------------------------------------------------------------------------
// Resolves a callsign to a DXCC entity.
//
// Uses candidate-prefix equality seeks rather than "? GLOB prefix || '*'". The
@@ -63,8 +145,36 @@ bool hammy_refdb_dxcc(hammy_refdb_t* db, const char* callsign, hammy_dxcc_t* out
// On a hit *out points at storage owned by the refdb and is only valid until
// the NEXT call on the same handle - copy it if it has to outlive that.
bool hammy_refdb_get_morse(hammy_refdb_t* db, char c, const char** out);
// What band is freq_hz in, and who may transmit there.
//
// country is an ISO 3166-1 alpha-2 code; NULL or empty means "US". Always
// returns true unless the arguments are bad: "not in a band" and "no data for
// that country" are results, not failures. Check out->in_band and
// out->country_known.
bool hammy_refdb_freq(hammy_refdb_t* db, int64_t freqHz, const char* country,
hammy_freq_t* out);
// Bundle version string from ref_meta, or NULL. Owned by the refdb.
const char* hammy_refdb_version(hammy_refdb_t* db);
// Which countries have licence data, for the "no data for XX yet" message.
// Writes up to cap codes and returns how many were written.
size_t hammy_refdb_countries(hammy_refdb_t* db,
char out[][HAMMY_COUNTRY_MAX], size_t cap);
// ---------------------------------------------------------------------------
// Input parsing
// ---------------------------------------------------------------------------
// Parses a user-supplied frequency into integer Hz. Accepts "14.150",
// "14150 kHz", "146.52 MHz", "1.2 GHz", "14150000 Hz". A bare number with no
// unit is read as MHz, which is what people type.
//
// Deliberately avoids floating point: "14.150" is converted digit by digit to
// 14150000 exactly. Going via double gives 14150000.000000002, which compares
// wrong against an integer column at exactly a band edge - the one case where
// being right matters most.
//
// Returns false on unparseable input or a value outside 1 Hz .. 300 GHz.
bool hammy_freq_parse(const char* text, int64_t* outHz);
#endif
+3
View File
@@ -8,5 +8,8 @@ typedef struct hammy_command_t hammy_command_t;
typedef struct hammy_bot_t hammy_bot_t;
typedef struct hammy_refdb_t hammy_refdb_t;
typedef struct hammy_dxcc_t hammy_dxcc_t;
typedef struct hammy_freq_priv_t hammy_freq_priv_t;
typedef struct hammy_freq_iaru_t hammy_freq_iaru_t;
typedef struct hammy_freq_t hammy_freq_t;
#endif