update function
This commit is contained in:
parent
375412545f
commit
a71606de2e
317
protocol.c
317
protocol.c
@ -117,56 +117,13 @@ void InitDeviceStatus() {
|
||||
updateInitStatus(INIT_SUCCESS);
|
||||
}
|
||||
|
||||
// 定时1s更新设备状态
|
||||
// 活度计通过网口获取
|
||||
// 下挂设备通过485获取
|
||||
void UpdateDeviceStatus() {
|
||||
// 更新设备状态
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 状态查询处理
|
||||
static uint8_t HandleStatusQuery(uint8_t *txBuf) {
|
||||
// 填充并返回数据
|
||||
memcpy(txBuf, &deviceStatus, sizeof(DeviceStatus));
|
||||
return sizeof(DeviceStatus);
|
||||
}
|
||||
|
||||
//modBUS RTU 写命令
|
||||
void writeCMD(uint8_t *txBuf, uint16_t *txLen) {
|
||||
}
|
||||
|
||||
|
||||
// 三通阀控制处理
|
||||
static uint8_t HandleValveControl(uint8_t index, ValveAngle_t angle) {
|
||||
// 实现三通阀控制逻辑
|
||||
|
||||
updateValveStatus(index, angle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 泵时长控制处理
|
||||
static uint8_t HandlePumpTimeControl(uint8_t *rxBuf, uint8_t *txBuf, uint16_t *txLen) {
|
||||
// 实现泵时长控制逻辑
|
||||
*txLen = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 泵速度设置处理
|
||||
static uint8_t HandlePumpSpeedControl(uint8_t *rxBuf, uint8_t *txBuf, uint16_t *txLen) {
|
||||
// 实现泵速度设置逻辑
|
||||
*txLen = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 软急停功能处理
|
||||
static uint8_t HandleSoftStop(uint8_t *rxBuf, uint8_t *txBuf, uint16_t *txLen) {
|
||||
// 实现软急停功能逻辑
|
||||
*txLen = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 判断系统大端序还是小端序
|
||||
static uint8_t IsBigEndian() {
|
||||
@ -200,7 +157,7 @@ static void FillBigEndian16(uint8_t *data, uint16_t value) {
|
||||
}
|
||||
|
||||
// 泵加速、减速处理
|
||||
static uint8_t HandlePumpAccDec(uint8_t index, uint8_t acc, uint8_t dec) {
|
||||
static uint8_t WritePumpAccDec(uint8_t index, uint8_t acc, uint8_t dec) {
|
||||
// 实现泵加速、减速逻辑
|
||||
|
||||
RTU_Frame frame;
|
||||
@ -225,7 +182,7 @@ static uint8_t HandlePumpAccDec(uint8_t index, uint8_t acc, uint8_t dec) {
|
||||
}
|
||||
|
||||
// 泵速度设置处理
|
||||
static uint8_t HandlePumpSpeed(uint8_t index, uint8_t speed) {
|
||||
static uint8_t WritePumpSpeed(uint8_t index, uint8_t speed) {
|
||||
// 实现泵速度设置逻辑
|
||||
|
||||
RTU_Frame frame;
|
||||
@ -247,7 +204,7 @@ static uint8_t HandlePumpSpeed(uint8_t index, uint8_t speed) {
|
||||
}
|
||||
|
||||
// 泵步进设置处理
|
||||
static uint8_t HandlePumpStep(uint8_t index, int32_t step) {
|
||||
static uint8_t WritePumpStep(uint8_t index, int32_t step) {
|
||||
// 实现泵步进设置逻辑
|
||||
|
||||
RTU_Frame frame;
|
||||
@ -279,48 +236,274 @@ static uint8_t HandlePumpStep(uint8_t index, int32_t step) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 初始化处理
|
||||
static uint8_t HandleInit(uint8_t *rxBuf, uint8_t *txBuf, uint16_t *txLen) {
|
||||
// 实现初始化逻辑
|
||||
*txLen = 1;
|
||||
// pump 读寄存器
|
||||
uint16_t ReadPump1Reg(uint8_t index, uint16_t reg) {
|
||||
|
||||
// 读取保存寄存器不能直接使用RTU_Frame,因为无数据位
|
||||
uint8_t data[8] = {0};
|
||||
data[0] = index;
|
||||
data[1] = RTU_PUMP_FUNC_READ_REG;
|
||||
FillBigEndian16(&data[2], reg);
|
||||
FillBigEndian16(&data[4], 1);
|
||||
|
||||
uint16_t crc = CalculateCRC16(data, 6);
|
||||
// 大端序填充
|
||||
FillBigEndian16(&data[6], crc);
|
||||
|
||||
writeCMD(data, 8);
|
||||
}
|
||||
|
||||
// 获取泵状态
|
||||
void ReadPumpStatus(uint8_t index) {
|
||||
ReadPump1Reg(index, RTU_PUMP_CMD_SC);
|
||||
}
|
||||
|
||||
// 获取泵告警信息
|
||||
void ReadPumpAlarm(uint8_t index) {
|
||||
ReadPump1Reg(index, RTU_PUMP_CMD_AL);
|
||||
}
|
||||
|
||||
// 解码告警信息
|
||||
void DecodePumpAlarmMsg(uint16_t reg4001) {
|
||||
static AlarmCode_t alarmCode = {0};
|
||||
// 与上次告警信息相同,则不更新,仅打印一次
|
||||
if (alarmCode.all == reg4001)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
alarmCode.all = reg4001;
|
||||
|
||||
if(alarmCode.all == 0) {
|
||||
//暂时屏蔽,避免刷屏
|
||||
// printf("\r\n%s无报警信息\r\n", pumpName[index]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 打印表格头部
|
||||
printf("\r\n+--------+------------------+\r\n");
|
||||
printf("| 告警位 | 告警信息 |\r\n");
|
||||
printf("+--------+------------------+\r\n");
|
||||
|
||||
for(uint16_t i = 0; i < 16; i++) {
|
||||
if(alarmCode.all & (1 << i)) {
|
||||
printf("| %6d | %-14s |\r\n", i, alarmInfo[i]);
|
||||
printf("+--------+------------------+\r\n");
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 主命令处理函数
|
||||
uint8_t ProcessCommand(uint8_t *rxBuf, uint16_t rxLen, uint8_t *txBuf, uint16_t *txLen) {
|
||||
uint16_t cmdCode = (rxBuf[0] << 8) | rxBuf[1];
|
||||
uint8_t dataLen = rxBuf[2];
|
||||
uint8_t *data = &rxBuf[3];
|
||||
uint8_t result = 0;
|
||||
// 解码状态信息
|
||||
void DecodePumpStatusMsg(uint16_t reg4002) {
|
||||
static StatusCode_t statusCode = {0};
|
||||
// 与上次状态信息相同,则不更新,仅打印一次
|
||||
if (statusCode.all == reg4002)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
statusCode.all = reg4002;
|
||||
|
||||
printf("\r\n+--------+------------------+\r\n");
|
||||
printf("| 状态位 | 状态信息 |\r\n");
|
||||
printf("+--------+------------------+\r\n");
|
||||
|
||||
for(uint16_t i = 0; i < 16; i++) {
|
||||
if(statusCode.all & (1 << i)) {
|
||||
printf("| %6d | %-14s |\r\n", i, statusInfo[i]);
|
||||
printf("+--------+------------------+\r\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 定时1s更新设备状态
|
||||
// 活度计通过网口获取
|
||||
// 下挂设备通过485获取
|
||||
void UpdatePumpStatus() {
|
||||
// 更新设备状态
|
||||
ReadPumpStatus(0);
|
||||
ReadPumpStatus(1);
|
||||
ReadPumpAlarm(0);
|
||||
ReadPumpAlarm(1);
|
||||
}
|
||||
|
||||
|
||||
// 初始化处理
|
||||
static uint8_t HandleInit(uint8_t *rxBuf, uint8_t *txBuf, uint16_t *txLen) {
|
||||
// 实现初始化逻辑
|
||||
InitDeviceStatus();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 状态查询处理
|
||||
static uint8_t HandleStatusQuery(uint8_t *txBuf) {
|
||||
// 填充并返回数据
|
||||
memcpy(txBuf, &deviceStatus, sizeof(DeviceStatus));
|
||||
return sizeof(DeviceStatus);
|
||||
}
|
||||
|
||||
// 三通阀控制处理
|
||||
static uint8_t HandleValveControl(uint8_t *Buff, uint8_t len) {
|
||||
// 实现三通阀控制逻辑
|
||||
|
||||
if(len != 8) {
|
||||
printf("三通阀控制错误\r\n");
|
||||
return 0;
|
||||
}
|
||||
uint8_t index = Buff[0];
|
||||
uint8_t direction = Buff[1];
|
||||
uint16_t angle = (Buff[2]<<8) | Buff[3];
|
||||
if(angle > 360) {
|
||||
printf("三通阀控制错误\r\n");
|
||||
return 1;
|
||||
}
|
||||
if (angle != VALVE_ANGLE_120 && angle != VALVE_ANGLE_210) {
|
||||
printf("三通阀控制错误\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 具体实现
|
||||
|
||||
|
||||
// 更新三通阀状态
|
||||
updateValveStatus(index, angle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 泵时长控制处理
|
||||
static uint8_t HandlePumpTimeControl(uint8_t *Buff, uint8_t len) {
|
||||
// 实现泵时长控制逻辑
|
||||
|
||||
// 暂未知控制方法,是直接设置泵运行时间,还是设置泵运行步数
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 泵速度设置处理
|
||||
static uint8_t HandlePumpSpeedControl(uint8_t *Buff, uint8_t len) {
|
||||
// 实现泵速度设置逻辑
|
||||
if(len != 4) {
|
||||
printf("泵速度设置错误\r\n");
|
||||
return 0;
|
||||
}
|
||||
uint8_t index = Buff[0];
|
||||
uint8_t speed = Buff[1];
|
||||
if (speed > 100) {
|
||||
printf("泵速度设置错误\r\n");
|
||||
return 0;
|
||||
}
|
||||
WritePumpSpeed(index, speed);
|
||||
|
||||
index = Buff[2];
|
||||
speed = Buff[3];
|
||||
if (speed > 100) {
|
||||
printf("泵速度设置错误\r\n");
|
||||
return 0;
|
||||
}
|
||||
WritePumpSpeed(index, speed);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t HandlePumpStepControl(uint8_t *Buff, uint8_t len) {
|
||||
if(len != 10) {
|
||||
printf("泵步进设置错误\r\n");
|
||||
return 0;
|
||||
}
|
||||
uint8_t index = Buff[0];
|
||||
int32_t step = (Buff[1]<<24) | (Buff[2]<<16) | (Buff[3]<<8) | Buff[4];
|
||||
WritePumpStep(index, step);
|
||||
|
||||
index = Buff[5];
|
||||
step = (Buff[6]<<24) | (Buff[7]<<16) | (Buff[8]<<8) | Buff[9];
|
||||
WritePumpStep(index, step);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 软急停功能处理
|
||||
static uint8_t HandleSoftStop(uint8_t *rxBuf, uint16_t rxLen) {
|
||||
if(rxLen != 1) {
|
||||
printf("软急停设置错误\r\n");
|
||||
return 1;
|
||||
}
|
||||
// 实现软急停功能逻辑
|
||||
if(rxBuf[0] == 0) {
|
||||
// 正常状态
|
||||
updateEmergencyStop(ESTOP_NORMAL);
|
||||
}
|
||||
else {
|
||||
// 急停状态
|
||||
updateEmergencyStop(ESTOP_PRESSED);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
CmdFrameError_t checkHostCmd(uint8_t *rxBuf, uint16_t rxLen) {
|
||||
// 检查命令是否正确
|
||||
if (memcmp(rxBuf, FRAME_HEADER, 4) != 0)
|
||||
{
|
||||
return CMD_FRAME_HEADER_ERROR;
|
||||
}
|
||||
if (memcmp(rxBuf + rxLen - 4, FRAME_TAIL, 4) != 0)
|
||||
{
|
||||
return CMD_FRAME_TAIL_ERROR;
|
||||
}
|
||||
uint16_t crc = CalculateCRC16(rxBuf+4, rxLen - 8);// 计算crc,不包含帧头和帧尾
|
||||
if (memcmp(rxBuf + rxLen - 4, &crc, 2) != 0)
|
||||
{
|
||||
return CMD_FRAME_CHECK_ERROR;
|
||||
}
|
||||
return CMD_FRAME_OK;
|
||||
}
|
||||
|
||||
|
||||
// 上位机命令处理函数,采用的自定协议,非modbus协议
|
||||
// rxBuf: 接收到的数据
|
||||
// rxLen: 接收到的数据长度
|
||||
CmdFrameError_t ProcessHostCommand(uint8_t *rxBuf, uint16_t rxLen) {
|
||||
|
||||
CmdFrameError_t error = checkHostCmd(rxBuf, rxLen);
|
||||
if (error != CMD_FRAME_OK)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t cmdCode = (rxBuf[sizeof(FRAME_HEADER)] << 8) | rxBuf[sizeof(FRAME_HEADER)+1];//提取命令码
|
||||
uint8_t dataLen = rxBuf[sizeof(FRAME_HEADER)+2];//提取数据长度
|
||||
uint8_t *data = &rxBuf[sizeof(FRAME_HEADER)+3];//提取数据
|
||||
|
||||
switch(cmdCode) {
|
||||
case CMD_STATUS_QUERY:
|
||||
result = HandleStatusQuery(data, txBuf, txLen);
|
||||
error = HandleStatusQuery(data, dataLen);
|
||||
break;
|
||||
case CMD_VALVE_CTRL:
|
||||
result = HandleValveControl(data, txBuf, txLen);
|
||||
error = HandleValveControl(data, dataLen);
|
||||
break;
|
||||
case CMD_PUMP_RUN_TIME:
|
||||
result = HandlePumpTimeControl(data, txBuf, txLen);
|
||||
error = HandlePumpTimeControl(data, dataLen);
|
||||
break;
|
||||
case CMD_PUMP_RUN_SPEED:
|
||||
result = HandlePumpSpeedControl(data, txBuf, txLen);
|
||||
error = HandlePumpSpeedControl(data, dataLen);
|
||||
break;
|
||||
case CMD_SOFT_STOP:
|
||||
result = HandleSoftStop(data, txBuf, txLen);
|
||||
error = HandleSoftStop(data, dataLen);
|
||||
break;
|
||||
case CMD_PUMP_RUN_STEP:
|
||||
result = HandlePumpStep(data, txBuf, txLen);
|
||||
error = HandlePumpStep(data, dataLen);
|
||||
break;
|
||||
case CMD_SYSTEM_INIT:
|
||||
result = HandleInit(data, txBuf, txLen);
|
||||
error = HandleInit(data, dataLen);
|
||||
break;
|
||||
default:
|
||||
*txLen = 1;
|
||||
txBuf[0] = 0;
|
||||
result = 0;
|
||||
error = CMD_FRAME_CMD_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
return error;
|
||||
}
|
107
protocol.h
107
protocol.h
@ -15,6 +15,15 @@
|
||||
#define CMD_SOFT_STOP 0x0005 // 软急停功能
|
||||
#define CMD_PUMP_RUN_STEP 0x0006 // 泵步进设置
|
||||
#define CMD_SYSTEM_INIT 0x0007 // 系统初始化
|
||||
// 命令帧错误码定义
|
||||
typedef enum {
|
||||
CMD_FRAME_OK = 0,
|
||||
CMD_FRAME_HEADER_ERROR = -1,
|
||||
CMD_FRAME_TAIL_ERROR = -2,
|
||||
CMD_FRAME_CHECK_ERROR = -3,
|
||||
CMD_FRAME_CMD_ERROR = -4,
|
||||
} CmdFrameError_t;
|
||||
|
||||
|
||||
|
||||
// MOONS’驱动器支持的Modbus功能码如下:
|
||||
@ -46,26 +55,33 @@
|
||||
14 调用的Q程序段为空
|
||||
15 存储器错误
|
||||
*/
|
||||
// 使用联合体表示
|
||||
|
||||
typedef enum {
|
||||
ALARM_POSITION_ERROR = 0,
|
||||
ALARM_CCW_LIMIT = 1,
|
||||
ALARM_CW_LIMIT = 2,
|
||||
ALARM_OVER_TEMP = 3,
|
||||
ALARM_INTERNAL_VOLTAGE_ERROR = 4,
|
||||
ALARM_OVER_VOLTAGE = 5,
|
||||
ALARM_UNDER_VOLTAGE = 6,
|
||||
ALARM_OVER_CURRENT = 7,
|
||||
ALARM_MOTOR_WINDING_SWITCH = 8,
|
||||
ALARM_MOTOR_ENCODER_ERROR = 9,
|
||||
ALARM_COMMUNICATION_ERROR = 10,
|
||||
ALARM_PARAMETER_SAVE_FAILED = 11,
|
||||
ALARM_MOTOR_UNDER_LOAD = 13,
|
||||
ALARM_EMPTY_Q_PROGRAM = 14,
|
||||
ALARM_MEMORY_ERROR = 15,
|
||||
} AlarmCode_t;
|
||||
// 告警寄存器联合体定义
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t position_error:1; // 位0: 位置误差超限
|
||||
uint16_t ccw_limit:1; // 位1: CCW方向禁止限位
|
||||
uint16_t cw_limit:1; // 位2: CW方向禁止限位
|
||||
uint16_t over_temp:1; // 位3: 驱动器过温
|
||||
uint16_t voltage_error:1; // 位4: 驱动器内部电压错误
|
||||
uint16_t over_voltage:1; // 位5: 驱动器过压
|
||||
uint16_t under_voltage:1; // 位6: 驱动器欠压
|
||||
uint16_t over_current:1; // 位7: 驱动器过流
|
||||
uint16_t winding_switch:1; // 位8: 电机绕组开关
|
||||
uint16_t encoder_error:1; // 位9: 电机编码器信号错误
|
||||
uint16_t comm_error:1; // 位10: 通讯异常
|
||||
uint16_t param_save_failed:1; // 位11: 参数保存失败
|
||||
uint16_t motor_disabled:1; // 位12: 在电机未使能时命令其运转
|
||||
uint16_t motor_overload:1; // 位13: 电机重载状态
|
||||
uint16_t empty_q_program:1; // 位14: 调用的Q程序段为空
|
||||
uint16_t memory_error:1; // 位15: 存储器错误
|
||||
} bits;
|
||||
uint16_t all; // 访问完整的16位寄存器
|
||||
}AlarmCode_t;
|
||||
|
||||
const uint8_t armInfo[16][32]={
|
||||
// 用于输出具体的告警信息字符串
|
||||
const uint8_t alarmInfo[16][32]={
|
||||
"位置误差超限",
|
||||
"CCW方向禁止限位",
|
||||
"CW方向禁止限位",
|
||||
@ -109,22 +125,25 @@ const uint8_t armInfo[16][32]={
|
||||
15 初始化(步进系),伺服准备好(伺服系)
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
STATUS_ENABLE = 0,
|
||||
STATUS_SAMPLE = 1,
|
||||
STATUS_FAULT = 2,
|
||||
STATUS_POSITION_REACHED = 3,
|
||||
STATUS_MOVING = 4,
|
||||
STATUS_POINT_MOVE = 5,
|
||||
STATUS_DECELERATING = 6,
|
||||
STATUS_WAIT_INPUT = 7,
|
||||
STATUS_PARAMETER_SAVE = 8,
|
||||
STATUS_ALARM = 9,
|
||||
STATUS_RETURN_HOME = 10,
|
||||
STATUS_WAIT_TIME = 11,
|
||||
STATUS_ENCODER_CHECK = 13,
|
||||
STATUS_Q_PROGRAM_RUN = 14,
|
||||
STATUS_INIT = 15,
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t enable:1; // 位0: 使能
|
||||
uint16_t sample:1; // 位1: 采样中(软件示波器功能开启)
|
||||
uint16_t fault:1; // 位2: 驱动器报故障
|
||||
uint16_t position_reached:1; // 位3: 运动到位
|
||||
uint16_t moving:1; // 位4: 运动中
|
||||
uint16_t point_move:1; // 位5: 点动运行中
|
||||
uint16_t decelerating:1; // 位6: 减速中
|
||||
uint16_t wait_input:1; // 位7: 等待输入信号(例如执行WI指令)
|
||||
uint16_t parameter_save:1; // 位8: 参数保存中
|
||||
uint16_t alarm:1; // 位9: 驱动器报警告
|
||||
uint16_t return_home:1; // 位10: 回原点中
|
||||
uint16_t wait_time:1; // 位11: 等待时间(例如执行WT、WD指令)
|
||||
uint16_t encoder_check:1; // 位12: 编码器检测中
|
||||
uint16_t q_program_run:1; // 位13: Q程序运行中
|
||||
uint16_t init:1; // 位14: 初始化(步进系),伺服准备好(伺服系)
|
||||
} bits;
|
||||
uint16_t all;
|
||||
} StatusCode_t;
|
||||
const uint8_t statusInfo[16][32]={
|
||||
"使能",
|
||||
@ -170,6 +189,8 @@ const uint8_t statusInfo[16][32]={
|
||||
#define RTU_PUMP_CMD_VE 0x001D // 速度
|
||||
#define RTU_PUMP_CMD_DI 0x001E // 目标位置
|
||||
|
||||
#define RTU_PUMP_CMD_SC 0x4002 // 状态寄存器
|
||||
#define RTU_PUMP_CMD_AL 0x4001 // 告警寄存器
|
||||
|
||||
// 错误码定义
|
||||
typedef enum {
|
||||
@ -249,6 +270,11 @@ typedef struct {
|
||||
} DeviceStatus;
|
||||
|
||||
|
||||
static uint8_t pumpName[2][10] = {
|
||||
"Pump1",
|
||||
"Pump2"
|
||||
};
|
||||
|
||||
// 定义协议消息结构
|
||||
typedef struct {
|
||||
uint8_t device_id;
|
||||
@ -256,13 +282,16 @@ typedef struct {
|
||||
uint8_t reg_addr[2];
|
||||
uint8_t reg_cnt[2];
|
||||
uint8_t data_cnt;
|
||||
uint8_t data[0];//柔性数组,大小由data_cnt决定
|
||||
uint8_t crc[2];
|
||||
uint8_t data[];//柔性数组,大小由data_cnt决定
|
||||
// uint8_t crc[2];
|
||||
} RTU_Frame;
|
||||
|
||||
|
||||
// 函数声明
|
||||
uint8_t ProcessCommand(uint8_t *rxBuf, uint16_t rxLen, uint8_t *txBuf, uint16_t *txLen);
|
||||
uint16_t CalculateCRC16(uint8_t *data, uint16_t length);
|
||||
|
||||
CmdFrameError_t ProcessHostCommand(uint8_t *rxBuf, uint16_t rxLen);
|
||||
// uint16_t CalculateCRC16(uint8_t *data, uint16_t length);
|
||||
void InitDeviceStatus();
|
||||
void DecodePumpAlarmMsg(uint16_t reg4001);
|
||||
void DecodePumpStatusMsg(uint16_t reg4002);
|
||||
void UpdatePumpStatus();
|
||||
#endif // PROTOCOL_H
|
Loading…
Reference in New Issue
Block a user