embedded-framework/utils/McuProtocol/src/ProtocolHandle.h

209 lines
7.8 KiB
C++

/*
* Copyright (c) 2023 Fancy Code.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PROTOCOL_HANDLE_H
#define PROTOCOL_HANDLE_H
#include "ILog.h"
#include "StatusCode.h"
#include <functional>
#include <map>
#include <memory>
#include <mutex>
constexpr char ORDER_BIG_ENDIAN = 0x01;
constexpr char ORDER_LITTLE_ENDIAN = 0x02;
constexpr size_t KEY_HEAD_LENGTH = sizeof(short) + sizeof(unsigned int) + sizeof(short) + sizeof(short);
constexpr size_t CHECK_CODE_LENGTH = sizeof(short);
constexpr unsigned int SERIAL_NUMBER_NEED_TO_MAKE_A_LOCAL_ONE = 0;
#pragma pack(1)
typedef struct protocol_packet
{
short mHead;
unsigned int mSerialNumber;
short mCommand;
short mLength;
// char *mData;
short mCheckCode;
} ProtocolPacket;
#pragma pack()
constexpr unsigned short PROTOCOL_HEAD = 0xFAC1;
enum PROTOCOL_COMMAND
{
ASK_IPC_MISSION = 0x8101,
REPLY_IPC_MISSION = 0x0101,
ASK_CUT_OFF_PWOER_SUPPLY = 0x8102,
ASK_FEED_WATCH_DOG = 0x8103,
ASK_SET_FEEDING_CYCLE = 0x8104,
REPLY_SET_FEEDING_CYCLE = 0x0104,
ASK_SET_DATE_TIME = 0x8107,
REPLY_SET_DATE_TIME = 0x0107,
ASK_SET_PIR_SENSITIVITY = 0x8108,
REPLY_SET_PIR_SENSITIVITY = 0x0108,
ASK_CONTORL_INFRARED_LIGHT = 0x810A,
REPLY_CONTORL_INFRARED_LIGHT = 0x010A,
ASK_GET_PHOTOSENSITIVITY = 0x810B,
REPLY_GET_PHOTOSENSITIVITY = 0x010B,
/**
* @brief The protocol starting from here is a request sent from the other end.
*
*/
REPLY_OTHER_SIDE_ASK_SEND_IPC_MISSION = 0xC101,
OTHER_SIDE_ASK_SEND_IPC_MISSION = 0x4101,
PROTOCOL_COMMAND_END
};
constexpr unsigned char ZERO_MEANS_SHUTDOWN_WATCH_DOG = 0x00;
#pragma pack(1)
typedef struct watch_dog_param
{
watch_dog_param(const unsigned char &hour, const unsigned char &min, const unsigned char &second)
: mHour(hour), mMin(min), mSecond(second)
{
}
const unsigned char mHour;
const unsigned char mMin;
const unsigned char mSecond;
} WatchDogParam;
typedef struct set_date_time
{
set_date_time(const unsigned short &year, const unsigned char &mon, const unsigned char &day,
const unsigned char &hour, const unsigned char &min, const unsigned char &second)
: mYear(year), mMon(mon), mDay(day), mHour(hour), mMin(min), mSecond(second)
{
}
const unsigned short mYear;
const unsigned char mMon;
const unsigned char mDay;
const unsigned char mHour;
const unsigned char mMin;
const unsigned char mSecond;
} SetDateTime;
#pragma pack()
class VProtocolParam
{
public:
VProtocolParam(const PROTOCOL_COMMAND &command) : mCommand(command)
{
mSerialNumber = SERIAL_NUMBER_NEED_TO_MAKE_A_LOCAL_ONE;
}
virtual ~VProtocolParam() = default;
const PROTOCOL_COMMAND mCommand;
unsigned int mSerialNumber;
};
template <typename T>
class ProtocolParam : public VProtocolParam
{
public:
ProtocolParam(const PROTOCOL_COMMAND &command, T &value) : VProtocolParam(command), mData(value) {}
virtual ~ProtocolParam() = default;
public:
/**
* @brief
* Protocol data.
*/
T mData;
};
using MakePacketFunc = std::function<void(const std::shared_ptr<VProtocolParam> &)>;
using AnalyzePacketFunc = std::function<void(const ProtocolPacket &)>;
/**
* @brief Protocol processing classes need to focus on data size issues, and ProtocolHandle defaults to handling large
* end data.
*/
class ProtocolHandle
{
public:
ProtocolHandle(const std::shared_ptr<VProtocolParam> &param);
ProtocolHandle(const void *data, const size_t &length);
virtual ~ProtocolHandle();
void *GetProtocolDataBuff(void) { return mProtocolData; }
size_t GetProtocolDataLength(void) { return mProtocolDataLength; }
unsigned int GetSerialNumber(void) { return mProtocolSerialNumber; }
/**
* @brief These functions assemble scattered data into continuous memory protocol packets and complete the sending
* of protocol packets.
*/
private:
ProtocolPacket CreatePocketWithSerialNumber(void);
void MallocPacketDataBuff(const void *data, const size_t dataLength, const short &command);
void MakeProtocolPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeNoUserDataPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskIpcMissionPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskCutOffPowerSupplyPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskFeedWatchDogPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskSetFeedingCyclePacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskSetDateTimePacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskSetPirSensitivityPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskControlInfraredLightPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeAskGetPhotosensitivityPacket(const std::shared_ptr<VProtocolParam> &param);
void MakeReplyOtherSideSendIpcMissionPacket(const std::shared_ptr<VProtocolParam> &param);
template <typename T>
void MakeProtocolData(const std::shared_ptr<VProtocolParam> &param)
{
constexpr int PARAM_DATA_LENGTH = sizeof(T);
std::shared_ptr<ProtocolParam<T>> SetParam = std::dynamic_pointer_cast<ProtocolParam<T>>(param);
if (!SetParam) {
LogError("Invalid param.\n");
return;
}
MallocPacketDataBuff(&(SetParam->mData), PARAM_DATA_LENGTH, param->mCommand);
}
private:
/**
* @brief These function implementations parse the received frame by frame continuous data into the data required by
* the application, completing the protocol unpacking.
*/
void AnalyzeProtocolPacket(void);
unsigned char ReplyOneBytePacketResult(const ProtocolPacket &packet);
void AnalyzeReplyResultPacket(const ProtocolPacket &packet);
void AnalyzeReplyIpcMissionPacket(const ProtocolPacket &packet);
void AnalyzeOtherSideSendIpcMissionPacket(const ProtocolPacket &packet);
private:
virtual void BigEndianConversion(ProtocolPacket &packet) {}
virtual short BigEndianConversion(const short &number) { return number; }
virtual void HostByteOrderConversion(ProtocolPacket &packet) {}
virtual bool CheckoutTheCheckCode(const ProtocolPacket &packet);
protected:
std::shared_ptr<VProtocolParam> mParam;
std::map<PROTOCOL_COMMAND, MakePacketFunc> mMakePacketFunc;
std::map<PROTOCOL_COMMAND, AnalyzePacketFunc> mAnalyzePacketFunc;
unsigned char *mProtocolData;
size_t mProtocolDataLength;
/**
* @brief Single protocol package serial number.
*
*/
unsigned int mProtocolSerialNumber;
/**
* @brief The global protocol packet serial number is used to bind the data content of the one question one answer
* protocol.
*
*/
static unsigned int mSerialNumber;
static std::mutex mMutex;
public:
static void Init(void);
static void UnInit(void);
static std::shared_ptr<ProtocolHandle> CreateProtocolData(const std::shared_ptr<VProtocolParam> &param);
static void ProtocolAnalysis(const void *data, const size_t &length);
static size_t GetKeyHeadLength(void);
static StatusCode GetDataLength(const void *keyHead, const size_t &headLength, size_t &dataLength);
static char GetByteOrder(void);
static void PrintHexadecimalData(const void *buf, const size_t &bufLength, const char *log = nullptr);
};
#endif