mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
628 lines
No EOL
19 KiB
C++
628 lines
No EOL
19 KiB
C++
#include "packets_structs.h"
|
|
#include <sstream>
|
|
|
|
namespace inmarsat
|
|
{
|
|
namespace stdc
|
|
{
|
|
std::string get_id_name(uint8_t id)
|
|
{
|
|
if (id == 0x00)
|
|
return "Acknowledgement Request";
|
|
else if (id == 0x01)
|
|
return "Announcement";
|
|
else if (id == 0x02)
|
|
return "Logical Channel Clear";
|
|
else if (id == 0x03)
|
|
return "Logical Channel Assignment";
|
|
else if (id == 0x04)
|
|
return "LES TDM Channel Descriptor Packet";
|
|
else if (id == 0x05)
|
|
return "Network Monitor Packet";
|
|
else if (id == 0x06)
|
|
return "Signalling Channel";
|
|
else if (id == 0x07)
|
|
return "Bulletin Board";
|
|
////////////
|
|
else if (id == 0x10)
|
|
return "Acknowledgement";
|
|
else if (id == 0x11)
|
|
return "Distress Alert Acknowledgement";
|
|
else if (id == 0x12)
|
|
return "Login Acknowledgement";
|
|
else if (id == 0x13)
|
|
return "Logout Acknowledgement";
|
|
////////////
|
|
if (id == 0x19)
|
|
return "LES Forced Clear";
|
|
else if (id == 0x1a)
|
|
return "Enhanced Data Report Acknowledgement";
|
|
////////////
|
|
else if (id == 0x20)
|
|
return "Distress Test Request";
|
|
else if (id == 0x21)
|
|
return "Area Poll";
|
|
else if (id == 0x22)
|
|
return "Group Poll";
|
|
else if (id == 0x23)
|
|
return "Individual Poll";
|
|
else if (id == 0x24)
|
|
return "Mobile To Base Station Poll";
|
|
else if (id == 0x25)
|
|
return "Mobile To Mobile Poll";
|
|
////////////
|
|
else if (id == 0x28)
|
|
return "Confirmation";
|
|
else if (id == 0x29)
|
|
return "Message Status";
|
|
else if (id == 0x2a)
|
|
return "Message Data";
|
|
else if (id == 0x2b)
|
|
return "Network Update";
|
|
else if (id == 0x2c)
|
|
return "Request Status";
|
|
else if (id == 0x2d)
|
|
return "Test Result";
|
|
else if (id == 0x30)
|
|
return "EGC Packet, single header";
|
|
else if (id == 0x31)
|
|
return "EGC double header, part 1";
|
|
else if (id == 0x32)
|
|
return "EGC double header, part 2";
|
|
////////////
|
|
else if (id == 0x3D)
|
|
return "Multiframe Packet Start";
|
|
else if (id == 0x3E)
|
|
return "Multiframe Packet Continue";
|
|
else
|
|
return "Unknown";
|
|
}
|
|
|
|
std::string get_sat_name(int sat)
|
|
{
|
|
if (sat == 0)
|
|
return "Atlantic Ocean Region West (AOR-W)";
|
|
else if (sat == 1)
|
|
return "Atlantic Ocean Region East (AOR-E)";
|
|
else if (sat == 2)
|
|
return "Pacific Ocean Region (POR)";
|
|
else if (sat == 3)
|
|
return "Indian Ocean Region (IOR)";
|
|
else if (sat == 9)
|
|
return "All Ocean Regions Covered by the LES";
|
|
else
|
|
return "Unknown";
|
|
}
|
|
|
|
std::string get_les_name(int sat, int lesId)
|
|
{
|
|
int value = lesId + sat * 100;
|
|
std::string name;
|
|
switch (value)
|
|
{
|
|
case 001:
|
|
case 101:
|
|
case 201:
|
|
case 301:
|
|
name = "Vizada-Telenor, USA";
|
|
break;
|
|
|
|
case 002:
|
|
case 102:
|
|
case 302:
|
|
name = "Stratos Global (Burum-2), Netherlands";
|
|
break;
|
|
|
|
case 202:
|
|
name = "Stratos Global (Aukland), New Zealand";
|
|
break;
|
|
|
|
case 003:
|
|
case 103:
|
|
case 203:
|
|
case 303:
|
|
name = "KDDI Japan";
|
|
break;
|
|
|
|
case 004:
|
|
case 104:
|
|
case 204:
|
|
case 304:
|
|
name = "Vizada-Telenor, Norway";
|
|
break;
|
|
|
|
case 044:
|
|
case 144:
|
|
case 244:
|
|
case 344:
|
|
name = "NCS";
|
|
break;
|
|
|
|
case 105:
|
|
case 335:
|
|
name = "Telecom, Italia";
|
|
break;
|
|
|
|
case 305:
|
|
case 120:
|
|
name = "OTESTAT, Greece";
|
|
break;
|
|
|
|
case 306:
|
|
name = "VSNL, India";
|
|
break;
|
|
|
|
case 110:
|
|
case 310:
|
|
name = "Turk Telecom, Turkey";
|
|
break;
|
|
|
|
case 211:
|
|
case 311:
|
|
name = "Beijing MCN, China";
|
|
break;
|
|
|
|
case 012:
|
|
case 112:
|
|
case 212:
|
|
case 312:
|
|
name = "Stratos Global (Burum), Netherlands";
|
|
break;
|
|
|
|
case 114:
|
|
name = "Embratel, Brazil";
|
|
break;
|
|
|
|
case 116:
|
|
case 316:
|
|
name = "Telekomunikacja Polska, Poland";
|
|
break;
|
|
|
|
case 117:
|
|
case 217:
|
|
case 317:
|
|
name = "Morsviazsputnik, Russia";
|
|
break;
|
|
|
|
case 021:
|
|
case 121:
|
|
case 221:
|
|
case 321:
|
|
name = "Vizada (FT), France";
|
|
break;
|
|
|
|
case 127:
|
|
case 327:
|
|
name = "Bezeq, Israel";
|
|
break;
|
|
|
|
case 210:
|
|
case 328:
|
|
name = "Singapore Telecom, Singapore";
|
|
break;
|
|
|
|
case 330:
|
|
name = "VISHIPEL, Vietnam";
|
|
break;
|
|
|
|
default:
|
|
name = "Unknown";
|
|
break;
|
|
}
|
|
return std::to_string(value) + ", " + name;
|
|
}
|
|
|
|
nlohmann::json get_services_short(uint8_t is8)
|
|
{
|
|
nlohmann::json services;
|
|
services["MaritimeDistressAlerting"] = ((is8 & 0x80) >> 7 == 1);
|
|
services["SafetyNet"] = ((is8 & 0x40) >> 6 == 1);
|
|
services["InmarsatC"] = ((is8 & 0x20) >> 5 == 1);
|
|
services["StoreFwd"] = ((is8 & 0x10) >> 4 == 1);
|
|
services["HalfDuplex"] = ((is8 & 8) >> 3 == 1);
|
|
services["FullDuplex"] = ((is8 & 4) >> 2 == 1);
|
|
services["ClosedNetwork"] = ((is8 & 2) >> 1 == 1);
|
|
services["FleetNet"] = ((is8 & 1));
|
|
return services;
|
|
}
|
|
|
|
nlohmann::json get_services(int iss)
|
|
{
|
|
nlohmann::json services;
|
|
services["MaritimeDistressAlerting"] = ((iss & 0x8000) >> 15 == 1);
|
|
services["SafetyNet"] = ((iss & 0x4000) >> 14 == 1);
|
|
services["InmarsatC"] = ((iss & 0x2000) >> 13 == 1);
|
|
services["StoreFwd"] = ((iss & 0x1000) >> 12 == 1);
|
|
services["HalfDuplex"] = ((iss & 0x800) >> 11 == 1);
|
|
services["FullDuplex"] = ((iss & 0x400) >> 10 == 1);
|
|
services["ClosedNetwork"] = ((iss & 0x200) >> 9 == 1);
|
|
services["FleetNet"] = ((iss & 0x100) >> 8 == 1);
|
|
services["PrefixSF"] = ((iss & 0x80) >> 7 == 1);
|
|
services["LandMobileAlerting"] = ((iss & 0x40) >> 6 == 1);
|
|
services["AeroC"] = ((iss & 0x20) >> 5 == 1);
|
|
services["ITA2"] = ((iss & 0x10) >> 4 == 1);
|
|
services["DATA"] = ((iss & 0x08) >> 3 == 1);
|
|
services["BasicX400"] = ((iss & 0x04) >> 2 == 1);
|
|
services["EnhancedX400"] = ((iss & 0x02) >> 1 == 1);
|
|
services["LowPowerCMES"] = ((iss & 0x01) == 1);
|
|
return services;
|
|
}
|
|
|
|
nlohmann::json get_stations(uint8_t *data, int stationCount)
|
|
{
|
|
nlohmann::json stations;
|
|
int j = 0;
|
|
for (int i = 0; i < stationCount; i++)
|
|
{
|
|
// stations [": ]+=std::to_string(i) ;
|
|
int sat = data[j] >> 6 & 0x03;
|
|
stations[i]["sa_id"] = sat;
|
|
stations[i]["sat_name"] = get_sat_name(sat);
|
|
int lesId = data[j] & 0x3F;
|
|
stations[i]["les_id"] = lesId;
|
|
stations[i]["les_name"] = get_les_name(sat, lesId);
|
|
int servicesStart = data[j + 1];
|
|
stations[i]["servicesStart"] = servicesStart;
|
|
int iss = data[j + 2] << 8 | data[j + 3];
|
|
// stations ["Services;]
|
|
stations[i]["MaritimeDistressAlerting"] = ((iss & 0x8000) >> 15 == 1);
|
|
stations[i]["SafetyNet"] = ((iss & 0x4000) >> 14 == 1);
|
|
stations[i]["InmarsatC"] = ((iss & 0x2000) >> 13 == 1);
|
|
stations[i]["StoreFwd"] = ((iss & 0x1000) >> 12 == 1);
|
|
stations[i]["HalfDuplex"] = ((iss & 0x800) >> 11 == 1);
|
|
stations[i]["FullDuplex"] = ((iss & 0x400) >> 10 == 1);
|
|
stations[i]["ClosedNetwork"] = ((iss & 0x200) >> 9 == 1);
|
|
stations[i]["FleetNet"] = ((iss & 0x100) >> 8 == 1);
|
|
stations[i]["PrefixSF"] = ((iss & 0x80) >> 7 == 1);
|
|
stations[i]["LandMobileAlerting"] = ((iss & 0x40) >> 6 == 1);
|
|
stations[i]["AeroC"] = ((iss & 0x20) >> 5 == 1);
|
|
stations[i]["ITA2"] = ((iss & 0x10) >> 4 == 1);
|
|
stations[i]["DATA"] = ((iss & 0x08) >> 3 == 1);
|
|
stations[i]["BasicX400"] = ((iss & 0x04) >> 2 == 1);
|
|
stations[i]["EnhancedX400"] = ((iss & 0x02) >> 1 == 1);
|
|
stations[i]["LowPowerCMES"] = ((iss & 0x01) == 1);
|
|
double downlink_mhz = ((data[j + 4] << 8 | data[j + 4]) - 8000) * 0.0025 + 1530.5;
|
|
stations[i]["downlink_channel_mhz "] = (downlink_mhz);
|
|
j += 6;
|
|
}
|
|
return stations;
|
|
}
|
|
|
|
bool is_binary(std::vector<uint8_t> data, bool checkAll)
|
|
{
|
|
bool isBinary = false;
|
|
// try first 13 characters if not check all
|
|
int check = 13;
|
|
if (!checkAll)
|
|
check = std::min(check, (int)data.size() - 2);
|
|
else
|
|
check = data.size();
|
|
for (int i = 0; i < check; i++)
|
|
{
|
|
char chr = (char)(data[i] & 0x7F);
|
|
switch (chr)
|
|
{
|
|
case 0x01:
|
|
case 0x05:
|
|
case 0x06:
|
|
case 0x07:
|
|
case 0x08:
|
|
case 0x0B:
|
|
case 0x0C:
|
|
case 0x0E:
|
|
case 0x0F:
|
|
case 0x10:
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x13:
|
|
case 0x14:
|
|
case 0x15:
|
|
case 0x16:
|
|
case 0x17:
|
|
case 0x18:
|
|
case 0x19:
|
|
case 0x1A:
|
|
case 0x1C:
|
|
case 0x1D:
|
|
case 0x1E:
|
|
case 0x1F:
|
|
// case 0xA4:
|
|
case '$':
|
|
isBinary = true;
|
|
break;
|
|
}
|
|
}
|
|
return isBinary;
|
|
}
|
|
|
|
std::map<int, char> table_xia5 = {
|
|
//{0x00, 0},
|
|
{10, '\n'},
|
|
{13, '\r'},
|
|
//
|
|
{0x21, '!'},
|
|
{0x22, '"'},
|
|
{0x23, '#'},
|
|
//{0x24, '¤'},
|
|
{0x25, '%'},
|
|
{0x26, '&'},
|
|
{0x27, '\''},
|
|
{0x28, '('},
|
|
{0x29, ')'},
|
|
{0x2A, '*'},
|
|
{0x2B, '+'},
|
|
{0x2C, ','},
|
|
{0x2D, '-'},
|
|
{0x2E, '.'},
|
|
{0x2F, '/'},
|
|
//
|
|
{0x30, '0'},
|
|
{0x31, '1'},
|
|
{0x32, '2'},
|
|
{0x33, '3'},
|
|
{0x34, '4'},
|
|
{0x35, '5'},
|
|
{0x36, '6'},
|
|
{0x37, '7'},
|
|
{0x38, '8'},
|
|
{0x39, '9'},
|
|
{0x3A, ':'},
|
|
{0x3B, ';'},
|
|
{0x3C, '<'},
|
|
{0x3D, '='},
|
|
{0x3E, '>'},
|
|
{0x3F, '?'},
|
|
//
|
|
{0x40, '@'},
|
|
{0x41, 'A'},
|
|
{0x42, 'B'},
|
|
{0x43, 'C'},
|
|
{0x44, 'D'},
|
|
{0x45, 'E'},
|
|
{0x46, 'F'},
|
|
{0x47, 'G'},
|
|
{0x48, 'H'},
|
|
{0x49, 'I'},
|
|
{0x4A, 'J'},
|
|
{0x4B, 'K'},
|
|
{0x4C, 'L'},
|
|
{0x4D, 'M'},
|
|
{0x4E, 'N'},
|
|
{0x4F, 'O'},
|
|
//
|
|
{0x50, 'P'},
|
|
{0x51, 'Q'},
|
|
{0x52, 'R'},
|
|
{0x53, 'S'},
|
|
{0x54, 'T'},
|
|
{0x55, 'U'},
|
|
{0x56, 'V'},
|
|
{0x57, 'W'},
|
|
{0x58, 'X'},
|
|
{0x59, 'Y'},
|
|
{0x5A, 'Z'},
|
|
{0x5B, '['},
|
|
{0x5C, '\\'},
|
|
{0x5D, ']'},
|
|
{0x5E, '^'},
|
|
{0x5F, '_'},
|
|
//
|
|
{0x60, '`'},
|
|
{0x61, 'a'},
|
|
{0x62, 'b'},
|
|
{0x63, 'c'},
|
|
{0x64, 'd'},
|
|
{0x65, 'e'},
|
|
{0x66, 'f'},
|
|
{0x67, 'g'},
|
|
{0x68, 'h'},
|
|
{0x69, 'i'},
|
|
{0x6A, 'j'},
|
|
{0x6B, 'k'},
|
|
{0x6C, 'l'},
|
|
{0x6D, 'm'},
|
|
{0x6E, 'n'},
|
|
{0x6F, 'o'},
|
|
//
|
|
{0x70, 'p'},
|
|
{0x71, 'q'},
|
|
{0x72, 'r'},
|
|
{0x73, 's'},
|
|
{0x74, 't'},
|
|
{0x75, 'u'},
|
|
{0x76, 'v'},
|
|
{0x77, 'w'},
|
|
{0x78, 'x'},
|
|
{0x79, 'y'},
|
|
{0x7A, 'z'},
|
|
{0x7B, '{'},
|
|
{0x7C, '|'},
|
|
{0x7D, '}'},
|
|
//{0x7E, '‾'},
|
|
//{0x7F, '∇'}
|
|
};
|
|
|
|
std::string string_from_ia5(uint8_t *buf, int len)
|
|
{
|
|
std::string ret = "";
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
uint8_t b = buf[i] & 0x7F;
|
|
char c = ' ';
|
|
if (table_xia5.count(b))
|
|
c = table_xia5[b];
|
|
if (!isascii(c))
|
|
c = ' ';
|
|
ret.push_back(c);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
std::string message_to_string(std::vector<uint8_t> buf, int presentation, bool egc)
|
|
{
|
|
std::string ret = "";
|
|
|
|
if (presentation == 0)
|
|
{
|
|
for (int i = 0; i < (int)buf.size(); i++)
|
|
{
|
|
uint8_t b = buf[i] & 0x7F;
|
|
char c = ' ';
|
|
if (table_xia5.count(b))
|
|
c = table_xia5[b];
|
|
ret.push_back(c);
|
|
}
|
|
}
|
|
else if (presentation == 7)
|
|
{
|
|
for (int i = 0; i < (int)buf.size(); i++)
|
|
{
|
|
char c = *((char *)&buf[i]);
|
|
ret.push_back(c);
|
|
}
|
|
}
|
|
|
|
// Ensure it's all ASCII just in case
|
|
for (char &c : ret)
|
|
if (!isascii(c))
|
|
c = ' ';
|
|
|
|
// Remove duplicate spaces
|
|
// auto it = std::unique(ret.begin(), ret.end(), [](char const &lhs, char const &rhs)
|
|
// { return lhs == rhs && iswspace(lhs); });
|
|
// ret.erase(it, ret.end());
|
|
|
|
if (ret.size() > 0 && !egc)
|
|
ret.erase(ret.end() - 1, ret.end());
|
|
|
|
return ret;
|
|
}
|
|
|
|
std::string get_service_code_and_address_name(int code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case 0x00:
|
|
return "System, All ships (general call)";
|
|
case 0x02:
|
|
return "FleetNET, Group Call";
|
|
case 0x04:
|
|
return "SafetyNET, Navigational, Meteorological or Piracy Warning to a Rectangular Area";
|
|
case 0x11:
|
|
return "System, Inmarsat System Message";
|
|
case 0x13:
|
|
return "SafetyNET, Navigational, Meteorological or Piracy Coastal Warning";
|
|
case 0x14:
|
|
return "SafetyNET, Shore-to-Ship Distress Alert to Circular Area";
|
|
case 0x23:
|
|
return "System, EGC System Message";
|
|
case 0x24:
|
|
return "SafetyNET, Navigational, Meteorological or Piracy Warning to a Circular Area";
|
|
case 0x31:
|
|
return "SafetyNET, NAVAREA/METAREA Warning, MET Forecast or Piracy Warning to NAVAREA/METAREA";
|
|
case 0x33:
|
|
return "System, Download Group Identity";
|
|
case 0x34:
|
|
return "SafetyNET, SAR Coordination to a Rectangular Area";
|
|
case 0x44:
|
|
return "SafetyNET, SAR Coordination to a Circular Area";
|
|
case 0x72:
|
|
return "FleetNET, Chart Correction Service";
|
|
case 0x73:
|
|
return "SafetyNET, Chart Correction Service for Fixed Areas";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
std::string get_priority(int priority)
|
|
{
|
|
switch (priority)
|
|
{
|
|
case -1:
|
|
return "Message";
|
|
case 0:
|
|
return "Routine";
|
|
case 1:
|
|
return "Safety";
|
|
case 2:
|
|
return "Urgency";
|
|
case 3:
|
|
return "Distress";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
int get_address_length(int messageType)
|
|
{
|
|
switch (messageType)
|
|
{
|
|
case 0x00:
|
|
return 3;
|
|
case 0x11:
|
|
case 0x31:
|
|
return 4;
|
|
case 0x02:
|
|
case 0x72:
|
|
return 5;
|
|
case 0x13:
|
|
case 0x23:
|
|
case 0x33:
|
|
case 0x73:
|
|
return 6;
|
|
case 0x04:
|
|
case 0x14:
|
|
case 0x24:
|
|
case 0x34:
|
|
case 0x44:
|
|
return 7;
|
|
default:
|
|
return 3;
|
|
}
|
|
}
|
|
|
|
double parse_uplink_freq_mhz(uint8_t *b)
|
|
{
|
|
return ((b[0] << 8 | (uint16_t)b[1]) - 6000) * 0.0025 + 1626.5;
|
|
}
|
|
|
|
double parse_downlink_freq_mhz(uint8_t *b)
|
|
{
|
|
return ((b[0] << 8 | (uint16_t)b[1]) - 8000) * 0.0025 + 1530.5;
|
|
}
|
|
|
|
std::string service4_name(uint8_t service_b)
|
|
{
|
|
if (service_b == 0)
|
|
return "Store And Forward";
|
|
else if (service_b == 1)
|
|
return "Half Duplex Data";
|
|
else if (service_b == 2)
|
|
return "Circuit Switched Data (no ARQ)";
|
|
else if (service_b == 3)
|
|
return "Circuit Switched Data (ARQ)";
|
|
else if (service_b == 0xE)
|
|
return "Message Performance Verification";
|
|
else
|
|
return "Unknown";
|
|
}
|
|
|
|
std::string direction2_name(uint8_t direction_b)
|
|
{
|
|
if (direction_b == 0)
|
|
return "To Mobile";
|
|
else if (direction_b == 1)
|
|
return "From Mobile";
|
|
else if (direction_b == 3)
|
|
return "Both";
|
|
else
|
|
return "Unknown";
|
|
}
|
|
|
|
int get_packet_frm_id(nlohmann::json pkt)
|
|
{
|
|
return pkt["descriptor"].get<pkts::PacketDescriptor>().type;
|
|
}
|
|
}
|
|
} |