添加网口接口协议相关

This commit is contained in:
shuibing811
2025-07-03 19:44:06 +08:00
parent 9b2574f3f9
commit b3cb001103
5 changed files with 458 additions and 46 deletions

View File

@@ -26,6 +26,8 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
res.qrc
RecordQuery.h RecordQuery.cpp RecordQuery.ui
LoggerWidget.h LoggerWidget.cpp LoggerWidget.ui
msg.h
msg.cpp
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET Satellite APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR

View File

@@ -20,6 +20,9 @@
#include <QStackedBarSeries>
#include <QToolTip>
#include <QtEndian>
#include "msg.h"
qreal get_rand(qreal maxValue) { return rand() * 1.0 / RAND_MAX * maxValue; }
@@ -99,34 +102,7 @@ void MainWindow::readPendingDatagrams(){
qDebug() << "Received datagram from" << sender.toString() << ":" << senderPort;
qDebug() << "Data:" << datagram;
//有来电
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->show();
ui->btnCallReject->show();
ui->lblCallStatus->setText("来电中...");
ui->lblCallDuration->hide();
//通话中
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("通话中...");
ui->lblCallDuration->show();
StartupTalkingTimer();
//挂断电话
ui->cmbCallNumber->setEnabled(true);
ui->btnCallAnswer->show();
ui->btnCallReject->hide();
ui->lblCallStatus->setText("空闲中...");
ui->lblCallDuration->hide();
ShutdownTalkingTimer();
//拨号中
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("拨号中...");
ui->lblCallDuration->hide();
test1();
processCommand(datagram);
}
}
@@ -498,7 +474,7 @@ void MainWindow::on_rdbChannelS_clicked() {
}
void MainWindow::on_rdbChannelBeiDou_clicked() {
if (m_callStatus == CallStatus::Idle) {
if (m_callStatus == CallStatus::kIdle) {
ui->cmbCallNumber->setEnabled(false);
}
}
@@ -510,7 +486,7 @@ void MainWindow::on_rdbChannelAuto_clicked() {
void MainWindow::on_btnCallAnswer_clicked() {
switch (m_callStatus) {
case CallStatus::Idle: {
case CallStatus::kIdle: {
// 检查电话号码是否为空
QString number = ui->cmbCallNumber->currentText();
if (number.isEmpty()) { // TODO:进一步判断电话号码格式是否满足要求
@@ -522,29 +498,28 @@ void MainWindow::on_btnCallAnswer_clicked() {
// 呼叫
call(number);
} break;
case CallStatus::Incoming:
case CallStatus::kCallIsComing:
// 接听
acceptCall();
break;
case CallStatus::Calling:
case CallStatus::Talking:
default:
break;
}
}
void MainWindow::on_btnCallReject_clicked() {
switch (m_callStatus) {
case CallStatus::Idle:
case CallStatus::kIdle:
break;
case CallStatus::Calling:
case CallStatus::kDialing://拨号中
// 挂断
hangUpCall();
break;
case CallStatus::Incoming:
case CallStatus::kCallIsComing://来电中
// 拒接
rejectCall();
break;
case CallStatus::Talking:
case CallStatus::kOnLine://通话中
// 挂断
hangUpCall();
break;
@@ -636,6 +611,247 @@ bool MainWindow::sendShortMessage(const QString &number,
return sendUdpMessage(udpMessage.toUtf8());
}
//--------------------------------------------------------------------------------------
// 处理命令
//--------------------------------------------------------------------------------------
void MainWindow::processCommand(const QByteArray& cmd){
if(cmd.size() < 5){
return;
}
switch(cmd[COMMAND_TYPE_INDEX]){
case int(CommandType::kTianTongVoice):
processTianTongVoiceCmd(cmd);
break;
case int(CommandType::kUhfVoice):
processUhfVoiceCmd(cmd);
break;
case int(CommandType::kTianTongShortMessage):
processTianTongShortMessageCmd(cmd);
break;
case int(CommandType::kUhfShortMessage):
processUhfShortMessageCmd(cmd);
break;
case int(CommandType::kBeiDouShortMessage):
processBeiDouShortMessageCmd(cmd);
break;
case int(CommandType::kStatusReport):
processStatusReportCmd(cmd);
break;
case int(CommandType::kSearchSatelliteStatusReport):
processSearchSatelliteStatusReport(cmd);
break;
}
//有来电
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->show();
ui->btnCallReject->show();
ui->lblCallStatus->setText("来电中...");
ui->lblCallDuration->hide();
//通话中
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("通话中...");
ui->lblCallDuration->show();
StartupTalkingTimer();
//挂断电话
ui->cmbCallNumber->setEnabled(true);
ui->btnCallAnswer->show();
ui->btnCallReject->hide();
ui->lblCallStatus->setText("空闲中...");
ui->lblCallDuration->hide();
ShutdownTalkingTimer();
//拨号中
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("拨号中...");
ui->lblCallDuration->hide();
test1();
}
void MainWindow::processTianTongVoiceCmd(const QByteArray& cmd){
switch(cmd[SUB_COMMAND_TYPE_INDEX]){
case int(TianTongVoiceSubCommandType::kDial):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//拨号成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//拨号失败
}
break;
case int(TianTongVoiceSubCommandType::kHangUp):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//挂机成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//挂机失败
}
break;
case int(TianTongVoiceSubCommandType::kAnswer):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//接听成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//接听失败
}
break;
case int(TianTongVoiceSubCommandType::kSendKeysWhenOnLine):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//通话中发送按键成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//通话中发送按键失败
}
break;
}
}
void MainWindow::processUhfVoiceCmd(const QByteArray& cmd){
switch(cmd[SUB_COMMAND_TYPE_INDEX]){
case int(UhfVoiceSubCommandType::kDial):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//拨号成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//拨号失败
}
break;
case int(UhfVoiceSubCommandType::kHangUp):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//挂机成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//挂机失败
}
break;
case int(UhfVoiceSubCommandType::kAnswer):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//通话中发送按键成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//通话中发送按键失败
}
break;
}
}
void MainWindow::processTianTongShortMessageCmd(const QByteArray& cmd){
switch(cmd[SUB_COMMAND_TYPE_INDEX]){
case int(ShortMessageSubCommandType::kSendMessage):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//短消息发送成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//短消息发送失败
}
break;
case int(ShortMessageSubCommandType::kRecvMessage):
//接收到短消息
break;
}
}
void MainWindow::processUhfShortMessageCmd(const QByteArray& cmd){
switch(cmd[SUB_COMMAND_TYPE_INDEX]){
case int(ShortMessageSubCommandType::kSendMessage):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//短消息发送成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//短消息发送失败
}
break;
case int(ShortMessageSubCommandType::kRecvMessage):
//接收到短消息
break;
}
}
void MainWindow::processBeiDouShortMessageCmd(const QByteArray& cmd){
switch(cmd[SUB_COMMAND_TYPE_INDEX]){
case int(ShortMessageSubCommandType::kSendMessage):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//短消息发送成功
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//短消息发送失败
}
break;
case int(ShortMessageSubCommandType::kRecvMessage):
//接收到短消息
break;
}
}
void MainWindow::processStatusReportCmd(const QByteArray& cmd){
if(cmd[SUB_COMMAND_TYPE_INDEX] != 0){
return;
}
int data_index = COMMAND_DATA_BEGIN_INDEX;
//uhf状态
uint8_t uhf_module_status = cmd[data_index++];//模块状态
uint8_t uhf_connected_network_status = cmd[data_index++];//入网状态
uint8_t uhf_sim_card_status = cmd[data_index++];//sim卡状态
uint8_t uhf_m_card_status = cmd[data_index++];//m卡状态
uint8_t uhf_call_status = cmd[data_index++];//通话状态
uint8_t uhf_satellite_signal_strength = cmd[data_index++];
std::string uhf_number = std::string(cmd.data()+data_index,20);
data_index += 20;
//天通状态
uint8_t tiantong_module_status = cmd[data_index++];//模块状态
uint8_t tiantong_connected_network_status = cmd[data_index++];//入网状态
uint8_t tiantong_sim_card_status = cmd[data_index++];//sim卡状态
uint8_t tiantong_m_card_status = cmd[data_index++];//m卡状态
uint8_t tiantong_call_status = cmd[data_index++];//通话状态
uint8_t tiantong_satellite_signal_strength = cmd[data_index++];
std::string tiantong_number = std::string(cmd.constData()+data_index,20);
data_index += 20;
//北斗状态
uint8_t beidou_module_status = cmd[data_index++];//模块状态
uint8_t beidou_sim_card_status = cmd[data_index++];//sim卡状态
//位置
int32_t longitude_v = qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
float longitude = longitude_v * 0.000001;
int32_t latitude_v = qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
float latitude = latitude_v * 0.000001;
int32_t altitude_v = qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
float altitude = altitude_v * 0.1;
//液压缸升降高度状态
int16_t oil_level_position_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float oil_level_position = oil_level_position_v * 0.01;//米
//自检状态
//天线电源A电压
int16_t antenna_power_supply_a_voltage_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_a_voltage = antenna_power_supply_a_voltage_v * 0.001;//V
//天线电源A电流
int16_t antenna_power_supply_a_current_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_a_current = antenna_power_supply_a_current_v * 0.001;//A
//天线电源B电压
int16_t antenna_power_supply_b_voltage_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_b_voltage = antenna_power_supply_a_voltage_v * 0.001;//V
//天线电源B电流
int16_t antenna_power_supply_b_current_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_b_current = antenna_power_supply_a_current_v * 0.001;//A
//UHF发送锁相环频综状态
uint8_t phase_locked_loop_send = cmd[data_index++];
//UHF接收锁相环频综状态
uint8_t phase_locked_loop_recv = cmd[data_index++];
}
void MainWindow::processSearchSatelliteStatusReport(const QByteArray& cmd){
if(cmd[SUB_COMMAND_TYPE_INDEX] != 0){
return;
}
int data_index = COMMAND_DATA_BEGIN_INDEX;
uint8_t number_of_satellite = cmd[data_index++];//卫星数量
//TODO: 做长度检查
std::vector<SatelliteStatus> all_satellite_status;
for(int i = 0 ; i < number_of_satellite; ++i){
SatelliteStatus status;
status.number = cmd[data_index++];//卫星编号
status.locate_flag = cmd[data_index++];//卫星定位标志
status.snr = cmd[data_index++];//卫星信噪比
status.azimuth = qFromLittleEndian<quint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));//卫星方位角
data_index += 2;
status.pitch = cmd[data_index++];//卫星俯仰角
all_satellite_status.push_back(status);
}
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------

View File

@@ -11,6 +11,7 @@
#include "RecordQuery.h"
#include "LoggerWidget.h"
#include "msg.h"
#include "spdlog/spdlog.h"
@@ -21,14 +22,6 @@ class MainWindow;
QT_END_NAMESPACE
enum class CallStatus{
Idle,
Calling,
Incoming,
Talking,
};
class QPolarChart;
class QChart;
class QBarCategoryAxis;
@@ -83,13 +76,21 @@ private:
bool acceptCall();
bool rejectCall();
bool sendShortMessage(const QString &number,const QString& message);
void processCommand(const QByteArray& cmd);
void processTianTongVoiceCmd(const QByteArray& cmd);
void processUhfVoiceCmd(const QByteArray& cmd);
void processTianTongShortMessageCmd(const QByteArray& cmd);
void processUhfShortMessageCmd(const QByteArray& cmd);
void processBeiDouShortMessageCmd(const QByteArray& cmd);
void processStatusReportCmd(const QByteArray& cmd);
void processSearchSatelliteStatusReport(const QByteArray& cmd);
void StartupTalkingTimer();
void ShutdownTalkingTimer();
void test();
private:
Ui::MainWindow *ui;
CallStatus m_callStatus = CallStatus::Idle;
CallStatus m_callStatus = CallStatus::kIdle;
std::vector<Record> m_msgList;
int m_unReadMsgCount = 0;
int m_callDuration = 0;

87
msg.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include "msg.h"
#include <QtEndian>
#define FRAME_MIN_LEN 5
void pack_len(QByteArray& cmd,uint16_t len){
uint16_t v = qToBigEndian(len);
memcpy(&cmd[0],reinterpret_cast<const char*>(&v),2);
}
QByteArray pack_tiantong_dial_cmd(const std::string& number){
assert(number.size() <= 20);
QByteArray cmd(FRAME_MIN_LEN+20, '\0');
pack_len(cmd,2+20);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kTianTongVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kDial);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],number.c_str(),number.size());
return cmd;
}
QByteArray pack_tiantong_hang_up_cmd(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
pack_len(cmd,2);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kTianTongVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kHangUp);
return cmd;
}
QByteArray pack_tiantong_answer(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
pack_len(cmd,2);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kTianTongVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kAnswer);
return cmd;
}
QByteArray pack_tiantong_send_keys_when_on_line_cmd(const std::string& keys){
assert(keys.size() <= 12);
QByteArray cmd(FRAME_MIN_LEN + 12, '\0');
pack_len(cmd,2 + 12);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kTianTongVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kSendKeysWhenOnLine);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],keys.c_str(),keys.size());
return cmd;
}
QByteArray pack_uhf_dial_cmd(const std::string& number){
assert(number.size() <= 20);
QByteArray cmd(FRAME_MIN_LEN+20, '\0');
pack_len(cmd,2 + 20);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kUhfVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(UhfVoiceSubCommandType::kDial);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],number.c_str(),number.size());
return cmd;
}
QByteArray pack_uhf_hang_up_cmd(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
pack_len(cmd,2);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kUhfVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(UhfVoiceSubCommandType::kHangUp);
return cmd;
}
QByteArray pack_uhf_answer(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
pack_len(cmd,2);
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kUhfVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(UhfVoiceSubCommandType::kAnswer);
return cmd;
}
QByteArray pack_short_message_cmd(CommandType cmd_type,const std::string& number, const std::string& message){
assert(number.size() <= 20);
QByteArray cmd(FRAME_MIN_LEN+20+message.size(), '\0');
pack_len(cmd,2 + 20 + message.size());
cmd[COMMAND_TYPE_INDEX] = uint8_t(cmd_type);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(ShortMessageSubCommandType::kSendMessage);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],number.c_str(),number.size());
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX+20],message.c_str(),message.size());
return cmd;
}
QByteArray pack_tiantong_short_message_cmd(const std::string& number, const std::string& message){
return pack_short_message_cmd(CommandType::kTianTongShortMessage,number,message);
}
QByteArray pack_uhf_short_message_cmd(const std::string& number, const std::string& message){
return pack_short_message_cmd(CommandType::kUhfShortMessage,number,message);
}
QByteArray pack_beidou_short_message_cmd(const std::string& number, const std::string& message){
return pack_short_message_cmd(CommandType::kBeiDouShortMessage,number,message);
}

106
msg.h Normal file
View File

@@ -0,0 +1,106 @@
#ifndef MSG_H
#define MSG_H
#include <cstdint>
#include <vector>
#include <string>
#include <QByteArray>
#define COMMAND_TYPE_INDEX 2
#define SUB_COMMAND_TYPE_INDEX 3
#define COMMAND_DATA_BEGIN_INDEX 4
enum class CommandType : uint8_t{
kTianTongVoice = 0xA0,
kUhfVoice = 0xA1,
kTianTongShortMessage = 0xB0,
kUhfShortMessage = 0xB1,
kBeiDouShortMessage = 0xB2,
kStatusReport = 0x80,
kSearchSatelliteStatusReport = 0x90,
};
enum class TianTongVoiceSubCommandType: uint8_t{
kDial = 0x01, //拨号
kHangUp = 0x02,//挂机
kAnswer = 0x03,//接听
kSendKeysWhenOnLine = 0x04, //通话时发送按键值
};
enum class UhfVoiceSubCommandType: uint8_t{
kDial = 0x01, //拨号
kHangUp = 0x02,//挂机
kAnswer = 0x03,//接听
};
enum class ShortMessageSubCommandType: uint8_t{
kSendMessage = 0x01, //发送短消息
kRecvMessage = 0x02, //接收短消息
};
enum class VoiceAndShortMessageReponse{
kSucess = 0x00,
kFailure = 0x01,
};
enum class ModuleStatus: uint8_t{
kChecking = 0x00,//检测中
kNormal = 0x01, //正常
kFault = 0x02, //故障
kUpgrading = 0x03, //升级中
};
enum class ConnectedNetworkStatus: uint8_t{
kNotConnected = 0x00, //未入网
kConnecting = 0x01, //正在入网
kConnectedDataIsNotActivated = 0x02, //已入网, 数据未激活
kConnectedDataIsActivated = 0x03, //已入网, 数据已激活
};
enum class SimCardStatus: uint8_t{
kChecking = 0x00,//正在检测
kExist = 0x01,//存在
kNotExist = 0x02,//不存在
};
enum class MCardStatus: uint8_t{
kChecking = 0x00,//正在检测
kExistNotEncryted = 0x01,//存在未注密
kExistEncryted = 0x02,//存在已注密码
kNotExist = 0x03,//不存在
};
enum class CallStatus: uint8_t{
kIdle = 0x00, //空闲
kDialing = 0x01,//拨号中
kPeerRingTheBell = 0x02,//对方振铃
kOnLine = 0x03,//通话中
kCallIsComing = 0x04,//来电中
};
enum class PhaseLockedLoopStatus{
kUnlocked = 0x00,//失锁
kLocked = 0x01, //锁定
};
struct SatelliteStatus{
uint8_t number;
uint8_t locate_flag;
uint8_t snr;
uint16_t azimuth;
uint8_t pitch;
};
QByteArray pack_tiantong_dial_cmd(const std::string& number);
QByteArray pack_tiantong_hang_up_cmd();
QByteArray pack_tiantong_answer();
QByteArray pack_tiantong_send_keys_when_on_line_cmd(const std::string& keys);
QByteArray pack_uhf_dial_cmd(const std::string& number);
QByteArray pack_uhf_hang_up_cmd();
QByteArray pack_uhf_answer();
QByteArray pack_tiantong_short_message_cmd(const std::string& number,const std::string& message);
QByteArray pack_uhf_short_message_cmd(const std::string& number, const std::string& message);
QByteArray pack_beidou_short_message_cmd(const std::string& number, const std::string& message);
#endif // MSG_H