mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
1168 lines
49 KiB
C++
1168 lines
49 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <vector>
|
|
#include "nlohmann/json.hpp"
|
|
#include "core/exception.h"
|
|
|
|
namespace inmarsat
|
|
{
|
|
namespace stdc
|
|
{
|
|
std::string get_id_name(uint8_t id);
|
|
std::string get_sat_name(int sat);
|
|
std::string get_les_name(int sat, int lesId);
|
|
|
|
nlohmann::json get_services_short(uint8_t is8);
|
|
nlohmann::json get_services(int iss);
|
|
nlohmann::json get_stations(uint8_t *data, int stationCount);
|
|
|
|
std::string buf_to_hex_str(uint8_t *buf, int len);
|
|
bool is_binary(std::vector<uint8_t> data, bool checkAll);
|
|
std::string message_to_string(std::vector<uint8_t> buf, int presentation, bool egc);
|
|
std::string get_service_code_and_address_name(int code);
|
|
std::string get_priority(int priority);
|
|
int get_address_length(int messageType);
|
|
std::string string_from_ia5(uint8_t *buf, int len);
|
|
|
|
double parse_uplink_freq_mhz(uint8_t *b);
|
|
double parse_downlink_freq_mhz(uint8_t *b);
|
|
|
|
std::string service4_name(uint8_t service_b);
|
|
std::string direction2_name(uint8_t direction_b);
|
|
|
|
int get_packet_frm_id(nlohmann::json pkt);
|
|
|
|
namespace pkts
|
|
{
|
|
using namespace ::inmarsat::stdc;
|
|
|
|
// Common descriptor to all packets
|
|
struct PacketDescriptor
|
|
{
|
|
bool is_short; // 1 byte
|
|
bool is_medium; // 2 bytes
|
|
bool is_long; // 3 bytes
|
|
|
|
uint8_t type;
|
|
uint16_t length;
|
|
|
|
PacketDescriptor() {}
|
|
PacketDescriptor(uint8_t *pkt)
|
|
{
|
|
if (pkt[0] >> 7 == 0) // Short
|
|
{
|
|
type = (pkt[0] >> 4) & 0b111;
|
|
length = (pkt[0] & 0xF) + 1;
|
|
is_short = true;
|
|
is_medium = false;
|
|
is_long = false;
|
|
}
|
|
else if (pkt[0] >> 6 == 2) // Medium
|
|
{
|
|
type = pkt[0] & 0b111111;
|
|
length = pkt[1] + 2;
|
|
is_short = false;
|
|
is_medium = true;
|
|
is_long = false;
|
|
}
|
|
else if (pkt[0] >> 6 == 3) // Long
|
|
{
|
|
type = pkt[0] & 0b111111;
|
|
length = (pkt[1] << 8 | pkt[2]) + 3;
|
|
is_short = false;
|
|
is_medium = true;
|
|
is_long = false;
|
|
}
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketDescriptor, is_short, is_medium, is_long, type, length)
|
|
};
|
|
|
|
// Common packet format :
|
|
// - Descriptor
|
|
// - Data field
|
|
// - Checksum
|
|
struct PacketBase
|
|
{
|
|
PacketDescriptor descriptor;
|
|
|
|
uint16_t compute_crc(uint8_t *buf, int size)
|
|
{
|
|
short C0 = 0, C1 = 0;
|
|
uint8_t CB1, CB2, B;
|
|
int i = 0;
|
|
while (i < size)
|
|
{
|
|
if (i < size - 2)
|
|
B = buf[i];
|
|
else
|
|
B = 0;
|
|
C0 += B;
|
|
C1 += C0;
|
|
i++;
|
|
}
|
|
CB1 = (uint8_t)(C0 - C1);
|
|
CB2 = (uint8_t)(C1 - 2 * C0);
|
|
return (CB1 << 8) | CB2;
|
|
}
|
|
|
|
PacketBase() {}
|
|
PacketBase(uint8_t *pkt, int len_max)
|
|
{
|
|
descriptor = PacketDescriptor(pkt);
|
|
|
|
// Check length is valid
|
|
if (descriptor.length > len_max)
|
|
throw satdump_exception("Invalid PKT length!");
|
|
|
|
// Check CRC
|
|
uint16_t sent_crc = (pkt[descriptor.length - 2] << 8) | pkt[descriptor.length - 1];
|
|
uint16_t comp_crc = compute_crc(pkt, descriptor.length);
|
|
bool crc_valid = sent_crc == 0 || sent_crc == comp_crc;
|
|
|
|
if (!crc_valid)
|
|
throw satdump_exception("Invalid CRC!");
|
|
}
|
|
|
|
// NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketBase, descriptor)
|
|
};
|
|
|
|
// Bulletin Board packet
|
|
struct PacketBulletinBoard : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x07;
|
|
|
|
// Frame Descriptor
|
|
uint8_t network_version;
|
|
uint16_t frame_number;
|
|
uint8_t signalling_channels;
|
|
uint8_t frame_2_count;
|
|
bool empty_frame;
|
|
|
|
double seconds_of_day;
|
|
|
|
// TDM Descriptor
|
|
uint8_t channel_type;
|
|
uint8_t local_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t status_b;
|
|
uint16_t services_b;
|
|
uint8_t randomizing_interval;
|
|
|
|
std::string channel_type_name;
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
nlohmann::json status;
|
|
nlohmann::json services;
|
|
|
|
PacketBulletinBoard() {}
|
|
PacketBulletinBoard(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
// Parse frame desc.
|
|
network_version = pkt[1];
|
|
frame_number = pkt[2] << 8 | pkt[3];
|
|
signalling_channels = pkt[4] >> 2;
|
|
frame_2_count = (pkt[5] >> 4 & 0x0F) * 2;
|
|
empty_frame = (pkt[5] >> 3) & 1;
|
|
|
|
seconds_of_day = frame_number * 8.64;
|
|
|
|
// Parse TDM desc.
|
|
channel_type = pkt[6] >> 0x05;
|
|
local_id = pkt[6] >> 2 & 0x07;
|
|
sat_id = pkt[7] >> 6 & 0x03;
|
|
les_id = pkt[7] & 0x3F;
|
|
status_b = pkt[8];
|
|
services_b = pkt[9] << 8 | pkt[10];
|
|
randomizing_interval = pkt[11];
|
|
|
|
if (channel_type == 1)
|
|
channel_type_name = "NCS";
|
|
else if (channel_type == 2)
|
|
channel_type_name = "LES TDM";
|
|
else if (channel_type == 3)
|
|
channel_type_name = "Joint NCS and TDM";
|
|
else if (channel_type == 4)
|
|
channel_type_name = "ST-BY NCS";
|
|
else
|
|
channel_type_name = "Reserved";
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
|
|
status["return_link_speed"] = (status_b & 0x80) >> 7 == 1 ? 600 : 300;
|
|
status["operational_sat"] = (status_b & 0x40) >> 6 == 1;
|
|
status["in_service"] = (status_b & 0x20) >> 5 == 1;
|
|
status["clear"] = (status_b & 0x10) >> 4 == 1;
|
|
status["links_open"] = (status_b & 0x08) >> 3 == 1;
|
|
status["covert_alerting"] = (status_b & 1) == 1;
|
|
|
|
services = get_services(services_b);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketBulletinBoard, descriptor,
|
|
network_version, frame_number, signalling_channels, frame_2_count, empty_frame, seconds_of_day,
|
|
channel_type, local_id, sat_id, les_id, status_b, services_b, randomizing_interval, channel_type_name, sat_name, les_name, status, services)
|
|
};
|
|
|
|
// Signalling Channel packet
|
|
struct PacketSignallingChannel : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x06;
|
|
|
|
uint8_t services_b;
|
|
double uplink_freq_mhz;
|
|
std::vector<int> tdm_slots;
|
|
|
|
nlohmann::json services;
|
|
|
|
PacketSignallingChannel() {}
|
|
PacketSignallingChannel(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
services_b = pkt[1];
|
|
uplink_freq_mhz = parse_uplink_freq_mhz(&pkt[2]);
|
|
|
|
tdm_slots.resize(28);
|
|
for (int i = 0, j = 0; i < 28; i += 4, j++)
|
|
{
|
|
tdm_slots[i] = pkt[4 + j] >> 6;
|
|
tdm_slots[i + 1] = pkt[4 + j] >> 4 & 3;
|
|
tdm_slots[i + 2] = pkt[4 + j] >> 2 & 3;
|
|
tdm_slots[i + 3] = pkt[4 + j] & 3;
|
|
}
|
|
|
|
services = get_services_short(services_b);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketSignallingChannel, descriptor,
|
|
uplink_freq_mhz, tdm_slots, services_b, services)
|
|
};
|
|
|
|
// Acknowledgement packet
|
|
struct PacketAcknowledgement : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x10;
|
|
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t logical_channel_number;
|
|
uint8_t frame_length;
|
|
uint8_t duration;
|
|
uint16_t message_channel;
|
|
uint8_t frame_offset;
|
|
bool am_pm_bit;
|
|
uint8_t slot_number;
|
|
std::vector<int> errored_packet_numbers;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketAcknowledgement() {}
|
|
PacketAcknowledgement(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
sat_id = pkt[2] >> 6 & 0x03;
|
|
les_id = pkt[2] & 0x3F;
|
|
logical_channel_number = pkt[3];
|
|
frame_length = pkt[4];
|
|
duration = pkt[5];
|
|
message_channel = pkt[6] << 8 | pkt[7];
|
|
frame_offset = pkt[8];
|
|
am_pm_bit = pkt[9] >> 7;
|
|
slot_number = pkt[9] & 0b11111;
|
|
|
|
for (int i = 0; i < descriptor.length - 10 - 2; i++)
|
|
errored_packet_numbers.push_back(pkt[9 + i]);
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketAcknowledgement, descriptor,
|
|
sat_id, les_id, logical_channel_number, frame_length, duration, message_channel, frame_offset, am_pm_bit, slot_number, errored_packet_numbers,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// Acknowledgement Request packet
|
|
struct PacketAcknowledgementRequest : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x00;
|
|
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t logical_channel_number;
|
|
double uplink_freq_mhz;
|
|
uint8_t frame_offset;
|
|
bool am_pm_bit;
|
|
uint8_t slot_number;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketAcknowledgementRequest() {}
|
|
PacketAcknowledgementRequest(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
sat_id = pkt[1] >> 6 & 0x03;
|
|
les_id = pkt[1] & 0x3F;
|
|
logical_channel_number = pkt[2];
|
|
uplink_freq_mhz = parse_uplink_freq_mhz(&pkt[3]);
|
|
frame_offset = pkt[5];
|
|
am_pm_bit = pkt[6] >> 7;
|
|
slot_number = pkt[6] & 0b11111;
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketAcknowledgementRequest, descriptor,
|
|
sat_id, les_id, logical_channel_number, uplink_freq_mhz, frame_offset, am_pm_bit, slot_number,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// Announcement packet
|
|
struct PacketAnnouncement : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x01;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
double downlink_freq_mhz;
|
|
uint8_t service_b;
|
|
uint8_t direction_b;
|
|
uint8_t priority_b;
|
|
|
|
uint8_t logical_channel_number;
|
|
uint32_t message_reference_number;
|
|
uint8_t sub_address;
|
|
uint8_t presentation;
|
|
uint8_t number_of_packets;
|
|
uint8_t last_count;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
std::string service;
|
|
std::string direction;
|
|
std::string priority;
|
|
|
|
PacketAnnouncement() {}
|
|
PacketAnnouncement(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
downlink_freq_mhz = parse_downlink_freq_mhz(&pkt[6]);
|
|
service_b = pkt[8] >> 4;
|
|
direction_b = (pkt[8] >> 2) & 0b11;
|
|
priority_b = pkt[8] & 0b11;
|
|
|
|
if (direction_b == 0)
|
|
{
|
|
logical_channel_number = pkt[9];
|
|
message_reference_number = pkt[10] << 16 | pkt[11] << 8 | pkt[12];
|
|
sub_address = pkt[13];
|
|
presentation = pkt[14];
|
|
number_of_packets = pkt[15];
|
|
last_count = pkt[16];
|
|
}
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
|
|
service = service4_name(service_b);
|
|
direction = direction2_name(direction_b);
|
|
|
|
if (priority_b == 0)
|
|
priority = "Routine";
|
|
else if (priority_b == 3)
|
|
priority = "Distress";
|
|
else
|
|
priority = "Unknown";
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketAnnouncement, descriptor,
|
|
mes_id, sat_id, les_id, downlink_freq_mhz, service_b, direction_b, priority_b,
|
|
logical_channel_number, message_reference_number, sub_address, presentation, number_of_packets, last_count,
|
|
sat_name, les_name, service, direction, priority)
|
|
};
|
|
|
|
// LES Forced Clear packet
|
|
struct PacketLESForcedClear : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x19;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t logical_channel_number;
|
|
uint8_t reason_for_clear_b;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
std::string reason_for_clear;
|
|
|
|
PacketLESForcedClear() {}
|
|
PacketLESForcedClear(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
logical_channel_number = pkt[6];
|
|
reason_for_clear_b = pkt[7];
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
|
|
if (reason_for_clear_b == 1)
|
|
reason_for_clear = "LES Timeout";
|
|
else if (reason_for_clear_b == 2)
|
|
reason_for_clear = "MES Procotol Error";
|
|
else if (reason_for_clear_b == 3)
|
|
reason_for_clear = "LES Hardware Error";
|
|
else if (reason_for_clear_b == 4)
|
|
reason_for_clear = "Operator Forced Clear";
|
|
else if (reason_for_clear_b == 5)
|
|
reason_for_clear = "MES Forced Clear";
|
|
else if (reason_for_clear_b == 6)
|
|
reason_for_clear = "LES Protocol Error";
|
|
else if (reason_for_clear_b == 7)
|
|
reason_for_clear = "MES Hardware Error";
|
|
else if (reason_for_clear_b == 8)
|
|
reason_for_clear = "MES Timeout";
|
|
else if (reason_for_clear_b == 9)
|
|
reason_for_clear = "Unknown Presentation code";
|
|
else if (reason_for_clear_b == 0xd)
|
|
reason_for_clear = "Requested Service Temporarily Unavailable";
|
|
else if (reason_for_clear_b == 0xe)
|
|
reason_for_clear = "Access To Requested Service Denied";
|
|
else if (reason_for_clear_b == 0xf)
|
|
reason_for_clear = "Invalid Service";
|
|
else if (reason_for_clear_b == 0x10)
|
|
reason_for_clear = "Invalid Address";
|
|
else if (reason_for_clear_b == 0x11)
|
|
reason_for_clear = "Destination MES Not Commissioned";
|
|
else if (reason_for_clear_b == 0x12)
|
|
reason_for_clear = "Destination MES Not Logged In";
|
|
else if (reason_for_clear_b == 0x13)
|
|
reason_for_clear = "Destination MES Barred";
|
|
else if (reason_for_clear_b == 0x14)
|
|
reason_for_clear = "Requested Service Not Provided";
|
|
else if (reason_for_clear_b == 0xa)
|
|
reason_for_clear = "Unable To Decode: Specified Dictionary Version Not Available";
|
|
else if (reason_for_clear_b == 0xb)
|
|
reason_for_clear = "IWU Number Is Invalid";
|
|
else if (reason_for_clear_b == 0xc)
|
|
reason_for_clear = "MES Has Not Subscribed To This Service";
|
|
else if (reason_for_clear_b == 0x15)
|
|
reason_for_clear = "Protocol Version Not Supported";
|
|
else if (reason_for_clear_b == 0x16)
|
|
reason_for_clear = "Unrecognized PDU Type";
|
|
else
|
|
reason_for_clear = "Unknown";
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketLESForcedClear, descriptor,
|
|
mes_id, sat_id, les_id, logical_channel_number, reason_for_clear_b, reason_for_clear,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// Clear packet
|
|
struct PacketClear : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x02;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t logical_channel_number;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketClear() {}
|
|
PacketClear(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[1] << 16 | pkt[2] << 8 | pkt[3];
|
|
sat_id = pkt[4] >> 6 & 0x03;
|
|
les_id = pkt[4] & 0x3F;
|
|
logical_channel_number = pkt[5];
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketClear, descriptor,
|
|
mes_id, sat_id, les_id, logical_channel_number,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// Confirmation packet
|
|
struct PacketConfirmation : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x28;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint32_t message_reference_number;
|
|
|
|
uint8_t descriptor_length;
|
|
bool status;
|
|
uint8_t attempts_number;
|
|
std::string non_delivery_code;
|
|
std::string address_information;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketConfirmation() {}
|
|
PacketConfirmation(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
message_reference_number = pkt[6] << 16 | pkt[7] << 8 | pkt[8];
|
|
|
|
descriptor_length = pkt[9];
|
|
status = pkt[10] >> 7;
|
|
attempts_number = pkt[10] & 0b1111111;
|
|
non_delivery_code = string_from_ia5(&pkt[11], 3);
|
|
address_information = string_from_ia5(&pkt[14], descriptor_length - 5);
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketConfirmation, descriptor,
|
|
mes_id, sat_id, les_id, message_reference_number, descriptor_length, status, attempts_number, non_delivery_code, address_information,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// DistressAlertAcknowledgement packet
|
|
struct PacketDistressAlertAcknowledgement : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x11;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketDistressAlertAcknowledgement() {}
|
|
PacketDistressAlertAcknowledgement(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketDistressAlertAcknowledgement, descriptor,
|
|
mes_id, sat_id, les_id,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// PacketDistressTestRequest packet
|
|
struct PacketDistressTestRequest : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x20;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketDistressTestRequest() {}
|
|
PacketDistressTestRequest(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketDistressTestRequest, descriptor,
|
|
mes_id, sat_id, les_id,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// PacketEGCCommon packet
|
|
struct PacketEGCCommon : public PacketBase
|
|
{
|
|
uint8_t service_code_b;
|
|
bool continuation;
|
|
uint8_t priority_b;
|
|
uint8_t repetition_number;
|
|
uint16_t message_sequence_number;
|
|
uint8_t packet_sequence_number;
|
|
std::vector<uint8_t> address_raw;
|
|
uint8_t presentation;
|
|
std::vector<uint8_t> data;
|
|
|
|
std::string service_code_and_address_name;
|
|
std::string priority;
|
|
std::string message;
|
|
|
|
PacketEGCCommon() {}
|
|
PacketEGCCommon(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
service_code_b = pkt[2];
|
|
continuation = (pkt[3] & 0x80) >> 7;
|
|
priority_b = (pkt[3] & 0x60) >> 5;
|
|
repetition_number = pkt[3] & 0x1F;
|
|
message_sequence_number = pkt[4] << 8 | pkt[5];
|
|
packet_sequence_number = pkt[6];
|
|
presentation = pkt[7];
|
|
|
|
service_code_and_address_name = get_service_code_and_address_name(service_code_b);
|
|
priority = get_priority(priority_b);
|
|
|
|
int address_length = get_address_length(service_code_b);
|
|
|
|
// NAV/MET coordinator... area... TODO
|
|
if (8 + address_length >= descriptor.length)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
address_raw.resize(address_length);
|
|
memcpy(address_raw.data(), &pkt[8], address_length);
|
|
|
|
int payload_length = descriptor.length - 2 - 8 - address_length;
|
|
int k = 8 + address_length;
|
|
data.clear();
|
|
for (int i = 0; k < 8 + address_length + payload_length; i++)
|
|
{
|
|
data.push_back(pkt[k]);
|
|
k++;
|
|
}
|
|
|
|
message = message_to_string(data, presentation, true);
|
|
}
|
|
}
|
|
};
|
|
|
|
// PacketEGCSingleHeader packet
|
|
struct PacketEGCSingleHeader : public PacketEGCCommon
|
|
{
|
|
static const uint8_t FRM_ID = 0x30;
|
|
|
|
PacketEGCSingleHeader() {}
|
|
PacketEGCSingleHeader(uint8_t *pkt, int len_max) : PacketEGCCommon(pkt, len_max)
|
|
{
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketEGCSingleHeader, descriptor,
|
|
service_code_b, continuation, priority_b, repetition_number, message_sequence_number, packet_sequence_number, address_raw, presentation, data,
|
|
service_code_and_address_name, priority, message)
|
|
};
|
|
|
|
// PacketEGCDoubleHeader1 packet
|
|
struct PacketEGCDoubleHeader1 : public PacketEGCCommon
|
|
{
|
|
static const uint8_t FRM_ID = 0x31;
|
|
|
|
PacketEGCDoubleHeader1() {}
|
|
PacketEGCDoubleHeader1(uint8_t *pkt, int len_max) : PacketEGCCommon(pkt, len_max)
|
|
{
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketEGCDoubleHeader1, descriptor,
|
|
service_code_b, continuation, priority_b, repetition_number, message_sequence_number, packet_sequence_number, address_raw, presentation, data,
|
|
service_code_and_address_name, priority, message)
|
|
};
|
|
|
|
// PacketEGCDoubleHeader2 packet
|
|
struct PacketEGCDoubleHeader2 : public PacketEGCCommon
|
|
{
|
|
static const uint8_t FRM_ID = 0x32;
|
|
|
|
PacketEGCDoubleHeader2() {}
|
|
PacketEGCDoubleHeader2(uint8_t *pkt, int len_max) : PacketEGCCommon(pkt, len_max)
|
|
{
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketEGCDoubleHeader2, descriptor,
|
|
service_code_b, continuation, priority_b, repetition_number, message_sequence_number, packet_sequence_number, address_raw, presentation, data,
|
|
service_code_and_address_name, priority, message)
|
|
};
|
|
|
|
// PacketLogicalChannelAssignement packet
|
|
struct PacketLogicalChannelAssignement : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x03;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t service_b;
|
|
uint8_t direction_b;
|
|
|
|
uint8_t number_of_packets;
|
|
uint8_t last_count;
|
|
double uplink_freq_mhz;
|
|
uint8_t frame_offset;
|
|
bool am_pm_bit;
|
|
uint8_t slot_number;
|
|
|
|
uint8_t logical_channel_number;
|
|
uint8_t frame_length;
|
|
uint8_t duration;
|
|
double downlink_freq_mhz;
|
|
uint16_t message_channel;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
std::string service;
|
|
std::string direction;
|
|
|
|
PacketLogicalChannelAssignement() {}
|
|
PacketLogicalChannelAssignement(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
service_b = pkt[6] >> 4;
|
|
direction_b = (pkt[6] >> 2) & 0b11;
|
|
|
|
if (direction_b == 0)
|
|
{
|
|
number_of_packets = pkt[7];
|
|
last_count = pkt[8];
|
|
uplink_freq_mhz = parse_uplink_freq_mhz(&pkt[9]);
|
|
frame_offset = pkt[11];
|
|
am_pm_bit = pkt[12] >> 7;
|
|
slot_number = pkt[13] & 0b11111;
|
|
}
|
|
else
|
|
{
|
|
logical_channel_number = pkt[7];
|
|
frame_length = pkt[8];
|
|
duration = pkt[9];
|
|
downlink_freq_mhz = parse_downlink_freq_mhz(&pkt[10]);
|
|
message_channel = pkt[12] << 8 | pkt[13];
|
|
frame_offset = pkt[14];
|
|
am_pm_bit = pkt[15] >> 7;
|
|
slot_number = pkt[16] & 0b11111;
|
|
}
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
|
|
service = service4_name(service_b);
|
|
direction = direction2_name(direction_b);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketLogicalChannelAssignement, descriptor,
|
|
mes_id, sat_id, les_id, service_b, direction_b,
|
|
number_of_packets, last_count, uplink_freq_mhz, frame_offset, am_pm_bit, slot_number,
|
|
logical_channel_number, frame_length, duration, downlink_freq_mhz, message_channel,
|
|
sat_name, les_name, service, direction)
|
|
};
|
|
|
|
// PacketLoginAcknowledgment packet
|
|
struct PacketLoginAcknowledgment : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x12;
|
|
|
|
uint32_t mes_id;
|
|
double downlink_freq_mhz;
|
|
|
|
uint8_t network_version;
|
|
uint8_t les_total;
|
|
nlohmann::json stations;
|
|
|
|
PacketLoginAcknowledgment() {}
|
|
PacketLoginAcknowledgment(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
downlink_freq_mhz = parse_downlink_freq_mhz(&pkt[5]);
|
|
network_version = pkt[6];
|
|
if (descriptor.length > 7)
|
|
{
|
|
les_total = pkt[8];
|
|
stations = get_stations(&pkt[9], les_total);
|
|
}
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketLoginAcknowledgment, descriptor,
|
|
mes_id, downlink_freq_mhz, network_version, les_total, stations)
|
|
};
|
|
|
|
// PacketLogoutAcknowledgment packet
|
|
struct PacketLogoutAcknowledgment : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x13;
|
|
|
|
uint32_t mes_id;
|
|
|
|
PacketLogoutAcknowledgment() {}
|
|
PacketLogoutAcknowledgment(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketLogoutAcknowledgment, descriptor, mes_id)
|
|
};
|
|
|
|
// Message Data packet
|
|
struct PacketMessageData : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x2a;
|
|
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t logical_channel_number;
|
|
uint8_t packet_sequence_number;
|
|
std::vector<uint8_t> data;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
std::string message;
|
|
|
|
PacketMessageData() {}
|
|
PacketMessageData(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
sat_id = pkt[2] >> 6 & 0x03;
|
|
les_id = pkt[2] & 0x3F;
|
|
logical_channel_number = pkt[3];
|
|
packet_sequence_number = pkt[4];
|
|
|
|
data = std::vector<uint8_t>(descriptor.length - 2 - 4);
|
|
memcpy(data.data(), &pkt[5], descriptor.length - 2 - 5);
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
message = message_to_string(data, is_binary(data, true) ? 7 : 0, false);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketMessageData, descriptor,
|
|
sat_id, les_id, logical_channel_number, packet_sequence_number, data, sat_name, les_name, message);
|
|
};
|
|
|
|
// Message Status packet
|
|
struct PacketMessageStatus : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x29;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint32_t message_reference_number;
|
|
|
|
uint8_t descriptor_length;
|
|
bool status;
|
|
uint8_t attempts_number;
|
|
std::string non_delivery_code;
|
|
std::string address_information;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketMessageStatus() {}
|
|
PacketMessageStatus(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
message_reference_number = pkt[6] << 16 | pkt[7] << 8 | pkt[8];
|
|
|
|
descriptor_length = pkt[9];
|
|
status = pkt[10] >> 7;
|
|
attempts_number = pkt[10] & 0b1111111;
|
|
non_delivery_code = string_from_ia5(&pkt[11], 3);
|
|
address_information = string_from_ia5(&pkt[14], descriptor_length - 5);
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketMessageStatus, descriptor,
|
|
mes_id, sat_id, les_id, message_reference_number, descriptor_length, status, attempts_number, non_delivery_code, address_information,
|
|
sat_name, les_name)
|
|
};
|
|
|
|
// PacketNetworkUpdate packet
|
|
struct PacketNetworkUpdate : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x2B;
|
|
|
|
uint8_t network_version;
|
|
uint8_t les_total;
|
|
nlohmann::json stations;
|
|
|
|
PacketNetworkUpdate() {}
|
|
PacketNetworkUpdate(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
network_version = pkt[2];
|
|
les_total = pkt[3];
|
|
stations = get_stations(&pkt[4], les_total);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketNetworkUpdate, descriptor,
|
|
network_version, les_total, stations)
|
|
};
|
|
|
|
// Request Status packet
|
|
struct PacketRequestStatus : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x2c;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
bool pending_reject_flag_b;
|
|
uint8_t request_status_code_b;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
std::string pending_reject_flag;
|
|
std::string request_status_code;
|
|
|
|
PacketRequestStatus() {}
|
|
PacketRequestStatus(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
pending_reject_flag_b = pkt[6] >> 7;
|
|
request_status_code_b = pkt[6] & 0b1111111;
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
|
|
if (pending_reject_flag_b == 0)
|
|
pending_reject_flag = "Pending";
|
|
else
|
|
pending_reject_flag = "Rejected";
|
|
|
|
if (request_status_code_b == 1)
|
|
request_status_code = "LES Message Store Full";
|
|
else if (request_status_code_b == 2)
|
|
request_status_code = "Requested Destination Not Served";
|
|
else if (request_status_code_b == 3)
|
|
request_status_code = "Satellite Congestion";
|
|
else if (request_status_code_b == 4)
|
|
request_status_code = "Terrestrial Congestion";
|
|
else if (request_status_code_b == 5)
|
|
request_status_code = "Requested Service Not Provided";
|
|
else if (request_status_code_b == 6)
|
|
request_status_code = "Request In Queue";
|
|
else if (request_status_code_b == 7)
|
|
request_status_code = "Request Barred";
|
|
else if (request_status_code_b == 8)
|
|
request_status_code = "MES Not Logged In";
|
|
else if (request_status_code_b == 9)
|
|
request_status_code = "MES Not Commissioned";
|
|
else if (request_status_code_b == 0xa)
|
|
request_status_code = "Waiting TDM Assignment";
|
|
else if (request_status_code_b == 0xb)
|
|
request_status_code = "Illegal Request";
|
|
else if (request_status_code_b == 0xc)
|
|
request_status_code = "LES Not In Service";
|
|
else if (request_status_code_b == 0xd)
|
|
request_status_code = "Requested Service Temporarily Unavailable";
|
|
else if (request_status_code_b == 0xe)
|
|
request_status_code = "Access To Requested Service Denied";
|
|
else if (request_status_code_b == 0xf)
|
|
request_status_code = "Invalid Service";
|
|
else if (request_status_code_b == 0x10)
|
|
request_status_code = "Invalid Address";
|
|
else if (request_status_code_b == 0x15)
|
|
request_status_code = "PTSN Modem Type Not Supported";
|
|
else if (request_status_code_b == 0x11)
|
|
request_status_code = "Unable To Decode: Specified Dictionary Version Not Available";
|
|
else if (request_status_code_b == 0x12)
|
|
request_status_code = "IWU Number Is Invalid";
|
|
else if (request_status_code_b == 0x13)
|
|
request_status_code = "MES Has Not Subscribed To This Service";
|
|
else if (request_status_code_b == 0x14)
|
|
request_status_code = "Protocol Version Not Supported";
|
|
else if (request_status_code_b == 0x16)
|
|
request_status_code = "Unrecognized PDE Type";
|
|
else
|
|
request_status_code = "Unknown";
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketRequestStatus, descriptor,
|
|
mes_id, sat_id, les_id, pending_reject_flag_b, request_status_code_b,
|
|
sat_name, les_name, pending_reject_flag, request_status_code)
|
|
};
|
|
|
|
// Test Result packet
|
|
struct PacketTestResult : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x2d;
|
|
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
|
|
uint8_t attempts_b;
|
|
uint8_t bber_b;
|
|
uint8_t foward_attempts;
|
|
uint8_t return_attempts;
|
|
uint8_t distress_alert_test_b;
|
|
uint8_t signal_strength_b;
|
|
uint8_t overall_result_b;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
std::string attempts;
|
|
std::string bber;
|
|
std::string distress_alert_test;
|
|
std::string signal_strength;
|
|
std::string overall_result;
|
|
|
|
PacketTestResult() {}
|
|
PacketTestResult(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
|
|
attempts_b = pkt[6] >> 6 & 0b11;
|
|
bber_b = pkt[6] >> 4 & 0b11;
|
|
foward_attempts = pkt[6] >> 2 & 0b11;
|
|
return_attempts = pkt[6] & 0b11;
|
|
distress_alert_test_b = pkt[7] >> 4;
|
|
signal_strength_b = pkt[7] & 0xF;
|
|
overall_result_b = pkt[8] >> 4;
|
|
|
|
if (attempts_b == 0)
|
|
attempts = "Third Attempt Failed";
|
|
else if (attempts_b == 1)
|
|
attempts = "First Attempt";
|
|
else if (attempts_b == 2)
|
|
attempts = "Second Attempt";
|
|
else if (attempts_b == 3)
|
|
attempts = "Third Attempt";
|
|
|
|
if (bber_b == 1)
|
|
bber = "Pass";
|
|
else if (attempts_b == 2)
|
|
bber = "Fail Attempt";
|
|
else
|
|
bber = "Third Attempt";
|
|
|
|
if (distress_alert_test_b == 0)
|
|
distress_alert_test = "No Response";
|
|
else if (distress_alert_test_b == 1)
|
|
distress_alert_test = "Not Applicable";
|
|
else if (distress_alert_test_b == 2)
|
|
distress_alert_test = "Test OK";
|
|
else if (distress_alert_test_b == 3)
|
|
distress_alert_test = "Nature Of Distress Not Default";
|
|
else if (distress_alert_test_b == 4)
|
|
distress_alert_test = "Null Data";
|
|
else if (distress_alert_test_b == 5)
|
|
distress_alert_test = "Incorrect Protocol";
|
|
else if (distress_alert_test_b == 6)
|
|
distress_alert_test = "Invalid Data Format";
|
|
else if (distress_alert_test_b == 7)
|
|
distress_alert_test = "Automatically Activated";
|
|
else
|
|
distress_alert_test = "Unknown";
|
|
|
|
if (signal_strength_b == 0)
|
|
signal_strength = "Unreadable";
|
|
else if (signal_strength_b == 1)
|
|
signal_strength = "Less than X dB";
|
|
else if (signal_strength_b == 2)
|
|
signal_strength = "Over or at X dB";
|
|
else if (signal_strength_b == 3)
|
|
signal_strength = "Over X +3 dB";
|
|
else if (signal_strength_b == 4)
|
|
signal_strength = "Over X +6 dB";
|
|
else if (signal_strength_b == 5)
|
|
signal_strength = "Over X +10 dB";
|
|
else if (signal_strength_b == 6)
|
|
signal_strength = "Over X +13 dB";
|
|
else if (signal_strength_b == 7)
|
|
signal_strength = "Over X +16 dB";
|
|
|
|
if (overall_result_b == 0)
|
|
overall_result = "Applicable Tests Pass";
|
|
else if (overall_result_b == 1)
|
|
overall_result = "Applicable Tests Pass";
|
|
else if (overall_result_b == 2)
|
|
overall_result = "Applicable Tests Pass";
|
|
else if (overall_result_b == 3)
|
|
overall_result = "Applicable Tests Pass";
|
|
else if (overall_result_b == 4)
|
|
overall_result = "Forward Message Transfer Fail";
|
|
else if (overall_result_b == 5)
|
|
overall_result = "Return Message Transfer Fail";
|
|
else if (overall_result_b == 6)
|
|
overall_result = "Signal Unreadable";
|
|
else if (overall_result_b == 7)
|
|
overall_result = "Signal Level Excessive";
|
|
else if (overall_result_b == 8)
|
|
overall_result = "Distress Alert Test Fail";
|
|
else if (overall_result_b == 9)
|
|
overall_result = "Unspecified Fail";
|
|
else
|
|
overall_result = "Unknown";
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketTestResult, descriptor,
|
|
mes_id, sat_id, les_id, attempts_b, bber_b, foward_attempts, return_attempts, distress_alert_test_b, signal_strength_b, overall_result_b,
|
|
sat_name, les_name, attempts, bber, distress_alert_test, signal_strength, overall_result)
|
|
};
|
|
|
|
// Network Monitor packet
|
|
struct PacketNetworkMonitor : public PacketBase
|
|
{
|
|
static const uint8_t FRM_ID = 0x05;
|
|
|
|
uint8_t type;
|
|
uint32_t mes_id;
|
|
uint8_t sat_id;
|
|
uint8_t les_id;
|
|
uint8_t logical_channel_number;
|
|
uint32_t message_reference_number;
|
|
uint8_t number_of_message_packets;
|
|
uint8_t presentation_control;
|
|
uint8_t last_count;
|
|
|
|
std::string sat_name;
|
|
std::string les_name;
|
|
|
|
PacketNetworkMonitor() {}
|
|
PacketNetworkMonitor(uint8_t *pkt, int len_max) : PacketBase(pkt, len_max)
|
|
{
|
|
type = pkt[1] >> 4;
|
|
mes_id = pkt[2] << 16 | pkt[3] << 8 | pkt[4];
|
|
sat_id = pkt[5] >> 6 & 0x03;
|
|
les_id = pkt[5] & 0x3F;
|
|
logical_channel_number = pkt[6];
|
|
message_reference_number = pkt[7] << 16 | pkt[8] << 8 | pkt[9];
|
|
number_of_message_packets = pkt[10];
|
|
presentation_control = pkt[11];
|
|
last_count = pkt[12];
|
|
|
|
sat_name = get_sat_name(sat_id);
|
|
les_name = get_les_name(sat_id, les_id);
|
|
}
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PacketNetworkMonitor, descriptor,
|
|
type, mes_id, sat_id, les_id, logical_channel_number, message_reference_number, number_of_message_packets, presentation_control, last_count,
|
|
sat_name, les_name)
|
|
};
|
|
}
|
|
}
|
|
}
|