Introduction
Since I started getting interested in amateur radio, I've become curious about every call sign I encounter and always want to find out the location (QTH) of those HAM operators. Existing online tools for finding QTHs require the operator to manually upload their location, so if they haven't done that, you can't find it. This led me to the idea of creating my own tool to search for locations, at least down to the province level.
This tool is based onRegulations for managing amateur radio call signsWritten in C++, this project is intended for beginners to practice with. I would appreciate any feedback or corrections you may have.Goal75KG/CallSignQuery。
Features
- Based on the call sign, we can extract national information (currently, only able to parse for China).
- Query radio types (amateur radio stations, beacon stations, satellite radio stations, etc.)
- Determine the province to which the call sign belongs.
- Types of radios for handling special situations
Example
Enter call sign:BA8MAA
Output Result:
Call sign: BA8MAA
Country: China
Radio type: Private amateur radio (Class 1)
Province: Guizhou
Implementation process
Mapping call sign per rule section
// Load country-specific prefix rules
std::map<std::string, std::string> loadCountryPrefixRules() {
std::map<std::string, std::string> countryPrefixRules;
countryPrefixRules["B"] = "China";
return countryPrefixRules;
// Load radio type rules
std::map<char, std::string> loadStationTypeRules() {
std::map<char, std::string> stationTypeRules;
stationTypeRules['A'] = "Amateur radio station (Level 1)";
stationTypeRules['D'] = "Amateur radio station (Level 2)";
stationTypeRules['E'] = "Amateur radio station (Level 2)";
stationTypeRules['G'] = "Amateur radio station (Levels 3, 4, and 5 (receiving stations))";
stationTypeRules['H'] = "Amateur radio station (Levels 3, 4, and 5 (receiving stations))";
stationTypeRules['I'] = "Amateur radio station (Levels 3, 4, and 5 (receiving stations))";
stationTypeRules['J'] = "Amateur beacon station";
stationTypeRules['L'] = "Amateur radio stations operated by foreign nationals and individuals from Hong Kong, Macau, and Taiwan in mainland China";
stationTypeRules['R'] = "Amateur repeater station";
stationTypeRules['T'] = "Specialized amateur radio station";
stationTypeRules['Y'] = "Collective amateur radio station";
return stationTypeRules;
// Load regional and provincial scope rules
std::map<char, std::map<std::string, std::pair<std::string, std::string> > > loadRegionProvinceRules() {
std::map<char, std::map<std::string, std::pair<std::string, std::string> > > ```javascript
function getRegionProvinceRules() {
var regionProvinceRules = {};
// Region 1: Beijing
regionProvinceRules['1'] = {
"Beijing": {"AA", "XZZ"}
};
// Region 2: Heilongjiang, Liaoning, Jilin
regionProvinceRules['2'] = {
"Heilongjiang": {"AA", "HZZ"},
"Jilin": {"IA", "PZZ"},
"Liaoning": {"QA", "XZZ"}
};
// Region 3: Hebei, Inner Mongolia, Shanxi, Tianjin
regionProvinceRules['3'] = {
"Tianjin": {"AA", "FZZ"},
"Inner Mongolia": {"GA", "LZZ"},
"Hebei": {"MA", "RZZ"},
"Shanxi": {"SA", "XZZ"}
};
// Region 4: Shandong, Jiangsu, Shanghai
regionProvinceRules['4'] = {
"Shanghai": {"AA", "HZZ"},
"Shandong": {"IA", "PZZ"},
"Jiangsu": {"QA", "XZZ"}
};
// Region 5: Zhejiang, Jiangxi, Fujian
regionProvinceRules['5'] = {
"Zhejiang": {"AA", "HZZ"},
"Jiangxi": {"IA", "PZZ"},
"Fujian": {"QA", "XZZ"}
};
// Region 6: Henan, Hubei, Anhui
regionProvinceRules['6'] = {
"Anhui": {"AA", "HZZ"},
"Henan": {"IA", "PZZ"},
"Hubei": {"QA", "XZZ"}
};
// Region 7: Hunan, Guangdong, Guangxi, Hainan
regionProvinceRules['7'] = {
"Hunan": {"AA", "HZZ"},
"Guangdong": {"IA", "PZZ"},
"Guangxi": {"QA", "XZZ"},
"Hainan": {"YA", "ZZZ"}
};
// Region 8: Sichuan, Guizhou, Yunnan, Chongqing
regionProvinceRules['8'] = {
"Sichuan": {"AA", "FZZ"},
"Chongqing": {"GA", "LZZ"},
"Guizhou": {"MA", "RZZ"},
"Yunnan": {"SA", "XZZ"}
};
// Region 9: Shaanxi, Gansu, Ningxia, Qinghai
regionProvinceRules['9'] = {
"Shaanxi": {"AA", "FZZ"},
"Gansu": {"GA", "LZZ"},
"Ningxia": {"MA", "RZZ"},
"Qinghai": {"SA", "XZZ"}
};
// Region 0: Xinjiang, Tibet
regionProvinceRules['0'] = {
"Xinjiang": {"AA", "FZZ"},
"Tibet": {"GA", "LZZ"}
};
return regionProvinceRules;
}
```
Determine if the specified suffix is within the allowed range.
bool isWithinRange(const std::string &suffix, const std::string &rangeStart, const std::string &if (rangeEnd) {
return suffix >= rangeStart && suffix <= rangeEnd;
}
Call sign matching
void queryCallSign(const std::string &```json
{
"callSign) {
// Load various rules
auto countryRules = loadCountryPrefixRules();
auto stationTypeRules = loadStationTypeRules();
auto regionProvinceRules = loadRegionProvinceRules();
// Ensure the call sign is at least 5 characters long
if (callSign.length() < 5) {
// Handle the case where the call sign is too short
// For example, you could return an error or log a warning
return false;
}
// Validate the call sign against the loaded rules
if (!isCallSignValid(callSign, countryRules, stationTypeRules, regionProvinceRules)) {
// Handle the case where the call sign is invalid
// For example, you could return an error or log a warning
return false;
}
// If the call sign is valid, proceed with further processing
return true;
}
}
``` < 5) {
std::cout << "Incorrect call sign format" << std::endl;
return;
}
// Parse the country prefix
std::string country = countryRules[callSign.substr(0, 1)];
// Parse the station type
char stationType = callSign[1];
std::string station = stationTypeRules[stationType];
// Parse the region
char region = callSign[2];
// Parse the suffix
std::string suffix = callSign.substr(3, 2); // Assuming a length of 2 for the suffix
// Find the province range for this region
std::string provinceName = "Unknown Province";
if (regionProvinceRules.find(region) != regionProvinceRules.end()) { &if (province: regionProvinceRules[region]) {
if (isWithinRange(suffix, province.second.first, province.second.second)) {
provinceName = province.first;
break;
}
}
Handling special cases (amateur radio stations, satellite amateur radio stations, specially designated amateur radio stations)
if (stationType == 'J') {
char suffix1 = callSign[3];
if (suffix1 == 'H' || suffix1 == 'V' || suffix1 == 'U') {
station = "HF, VHF, and UHV frequency beacon station";
} else if (suffix1 == 'D') {
station = "Dedicated directional beacon station for amateur radio";
} else if (suffix1 == 'S' && if (region == '1') {
station = "Satellite amateur radio station";
} else if (suffix1 == 'T') {
station = "Specialized amateur radio station";
}
Result output
if (country.length() > 0 && !station.is_empty() && if (provinceName != "Unknown Province"):
std::cout << "Call sign:" << callSign << std::endl;
std::cout << "Country:" << country << std::endl;
std::cout << "Radio types:" << station << std::endl;
std::cout << "Province:" << provinceName << std::endl;
} else {
std::cout << "No information found corresponding to the call sign" << std::endl;
}
Main program
int main() {
std::string callSign;
std::cout << "Please enter the call sign to search for: "
std::cin >> callSign;
std::cout << The search results are as follows: << std::endl;
// Query call sign information
queryCallSign(callSign);
system("pause");
return 0;
}
Source code
#include <iostream>
#include <map>
#include <string>
// Load country-specific prefix rules
std::map<std::string, std::string> loadCountryPrefixRules() {
std::map<std::string, std::string> // Load radio type rules
std::map<char, std::string> loadStationTypeRules() {
std::map<char, std::string> stationTypeRules;
stationTypeRules['A'] = "Amateur radio station (Level 1)";
stationTypeRules['D'] = "Amateur radio station (Level 2)";
stationTypeRules['E'] = "Amateur radio station (Level 2)";
stationTypeRules['G'] = "Amateur radio station (Levels 3, 4, and 5 (receiving stations))";
stationTypeRules['H'] = "Amateur radio station (Levels 3, 4, and 5 (receiving stations))";
stationTypeRules['I'] = "Amateur radio station (Levels 3, 4, and 5 (receiving stations))";
stationTypeRules['J'] = "Amateur beacon station";
stationTypeRules['L'] = "Amateur radio stations operated by foreign nationals and individuals from Hong Kong, Macau, and Taiwan in mainland China";
stationTypeRules['R'] = "Amateur repeater station";
stationTypeRules['T'] = "Specialized amateur radio station";
stationTypeRules['Y'] = "Collective amateur radio station";
return stationTypeRules;
}
// Load regional and provincial scope rules
std::map<char, std::map<std::string, std::pair<std::string, std::string> > > loadRegionProvinceRules() {
std::map<char, std::map<std::string, std::pair<std::string, std::string> > > ```javascript
function getRegionProvinceRules() {
var regionProvinceRules = {};
// Region 1: Beijing
regionProvinceRules['1'] = {
"Beijing": {"AA", "XZZ"}
};
// Region 2: Heilongjiang, Liaoning, Jilin
regionProvinceRules['2'] = {
"Heilongjiang": {"AA", "HZZ"},
"Jilin": {"IA", "PZZ"},
"Liaoning": {"QA", "XZZ"}
};
// Region 3: Hebei, Inner Mongolia, Shanxi, Tianjin
regionProvinceRules['3'] = {
"Tianjin": {"AA", "FZZ"},
"Inner Mongolia": {"GA", "LZZ"},
"Hebei": {"MA", "RZZ"},
"Shanxi": {"SA", "XZZ"}
};
// Region 4: Shandong, Jiangsu, Shanghai
regionProvinceRules['4'] = {
"Shanghai": {"AA", "HZZ"},
"Shandong": {"IA", "PZZ"},
"Jiangsu": {"QA", "XZZ"}
};
// Region 5: Zhejiang, Jiangxi, Fujian
regionProvinceRules['5'] = {
"Zhejiang": {"AA", "HZZ"},
"Jiangxi": {"IA", "PZZ"},
"Fujian": {"QA", "XZZ"}
};
// Region 6: Henan, Hubei, Anhui
regionProvinceRules['6'] = {
"Anhui": {"AA", "HZZ"},
"Henan": {"IA", "PZZ"},
"Hubei": {"QA", "XZZ"}
};
// Region 7: Hunan, Guangdong, Guangxi, Hainan
regionProvinceRules['7'] = {
"Hunan": {"AA", "HZZ"},
"Guangdong": {"IA", "PZZ"},
"Guangxi": {"QA", "XZZ"},
"Hainan": {"YA", "ZZZ"}
};
// Region 8: Sichuan, Guizhou, Yunnan, Chongqing
regionProvinceRules['8'] = {
"Sichuan": {"AA", "FZZ"},
"Chongqing": {"GA", "LZZ"},
"Guizhou": {"MA", "RZZ"},
"Yunnan": {"SA", "XZZ"}
};
// Region 9: Shaanxi, Gansu, Ningxia, Qinghai
regionProvinceRules['9'] = {
"Shaanxi": {"AA", "FZZ"},
"Gansu": {"GA", "LZZ"},
"Ningxia": {"MA", "RZZ"},
"Qinghai": {"SA", "XZZ"}
};
// Region 0: Xinjiang, Tibet
regionProvinceRules['0'] = {
"Xinjiang": {"AA", "FZZ"},
"Tibet": {"GA", "LZZ"}
};
return regionProvinceRules;
}
// Check if the suffix is within the range
function isWithinRange(const std::string &suffix, const std::string &rangeStart, const std::string &if (rangeEnd) {
return suffix >= rangeStart && suffix <```cpp
// Get the end of the range
rangeEnd = rangeEnd;
// Query the call sign
void queryCallSign(const std::string &```json
{
"callSign) {
// Load various rules
auto countryRules = loadCountryPrefixRules();
auto stationTypeRules = loadStationTypeRules();
auto regionProvinceRules = loadRegionProvinceRules();
// Ensure the call sign is at least 5 characters long
if (callSign.length() < 5) {
// Handle the case where the call sign is too short
// For example, you could return an error or log a warning
return false;
}
// Validate the call sign against the loaded rules
if (!isCallSignValid(callSign, countryRules, stationTypeRules, regionProvinceRules)) {
// Handle the case where the call sign is invalid
// For example, you could return an error or log a warning
return false;
}
// If the call sign is valid, proceed with further processing
return true;
}
}
``` < 5) {
std::cout << "Incorrect call sign format" << std::endl;
return;
}
// Parse the country prefix
std::string country = countryRules[callSign.substr(0, 1)];
// Parse the station type
char stationType = callSign[1];
std::string station = stationTypeRules[stationType];
// Parse the region
char region = callSign[2];
// Parse the suffix
std::string suffix = callSign.substr(3, 2); // Assuming a length of 2 for the suffix
// Find the province range for this region
std::string provinceName = "Unknown Province";
if (regionProvinceRules.find(region) != regionProvinceRules.end()) { &province: regionProvinceRules[region]) {
if (isWithinRange(suffix, province.second.first, province.second.second)) {
provinceName = province.first;
break;
}
}
}
// Handle special cases (amateur radio stations, satellite amateur radio stations, specially designated amateur radio stations)
if (stationType == 'J') {
char suffix1 = callSign[3];
if (suffix1 == 'H' || suffix1 == 'V' || suffix1 == 'U') {
station = "HF, VHF, and UHV frequency beacons";
} else if (suffix1 == 'D') {
station = "Amateur radio directional beacons";
} else if (suffix1 == 'S' && ```english
if (region == '1') {
station = "Satellite Amateur Radio Station";
} else if (suffix1 == 'T') {
station = "Specialized Amateur Radio Station";
}
// Output the result
if (!country.empty()
``` && !station.is_empty() && if (provinceName != "Unknown Province"):
std::cout << "Call sign:" << callSign << std::endl;
std::cout << "Country:" << country << std::endl;
std::cout << "Radio types:" << station << std::endl;
std::cout << "Province:" << provinceName << std::endl;
} else {
std::cout << "No information found corresponding to the call sign" << std::endl;
}
}
int main() {
std::string callSign;
std::cout << "Please enter the call sign to search for: "
std::cin >> callSign;
std::cout << The search results are as follows: << std::endl;
// Query call sign information
queryCallSign(callSign);
system("pause");
return 0;
}
Epilogue
Subsequent plans:
Do you have more ideas? We welcome discussion.👏