ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【编程思想】数据传输的通信接口以及通信协议的解耦设计

2020-12-20 22:30:07  阅读:193  来源: 互联网

标签:pContex 数据 TRANSFER void 通信协议 STATE 数据传输 DATA 通信接口


应用场景

在工作上经常会遇到需要对接多个外设,如离线语音识别芯片、NFC刷卡器芯片等等,这些大部分都是通过UART、SPI等接口进行通信,且具有各自的数据包通信协议。

除了通信接口和通信协议(即数据封包解包)有差异外,这些数据处理逻辑都一样,所以可以将数据处理逻辑统一,将通信差异部分抽离出来,分别根据不同的硬件实现。

整体框架

核心框架部分:

IDataStream:数据通信接口定义,用于统一各种通信接口,如 Serial 串口读写操作,实现数据收发。

IDataCodec:数据编解码接口定义,用于统一各种通信协议的调用接口,如离线识别语言芯片 Ci110x 系列,实现数据封包解包。

DataTransfer:依据外部传入的通信接口对象和数据编解码对象,实现数据传输处理的通用逻辑,如数据接收、数据缓存、数据编解码、数据回调,数据发送等。

设备功能接口:

DevieCi110x:通过创建 DataCodecCi110x、DataStreamSerial 对象,传入 DataTransfer 便可完成基础数据通信,再此基础上进一步封装高层命令,如进入或退出识别模式命令,又如前后端点事件、唤醒事件、音频数据等等具体的高级功能。

这样,主业务逻辑代码无论应对什么外设,都可以完全的复用代码,根据实际场景随意组合 DataStream 和 DataCodec。并且新增的外设,只需要实现 IDataCodec 定义的接口,即可完成数据包编解码部分,若是新增的通信接口,也可按照 IDataStream 定义的接口实现即可。如新增一个 XXXA 设备,设备自有通信协议,使用 Serial 通信接口,那么只需要按照 IDataCodec 定义的接口,实现 XXXA 的通信协议,通信接口复用现有的 DataStreamSerial,即可完成数据通信。

如果发现现有的某个通信协议很完善,支持数据包不定长数据封包解包,在进行大批量数据传输非常稳定,那么在新的项目,如需要与上位机传输音频、图像,都可以直接拿来用,不需要做过多的改动,大大的提高了开发效率。

IDataCodec

IDataCodec 接口定义

/**
******************************************************************************
* @文件		IDataCodec.h
* @版本		V1.0.0
* @日期
* @概要		数据编解码接口定义
* @作者		lmx
******************************************************************************
* @注意
******************************************************************************
*/

#ifndef __IDATA_CODEC_H
#define __IDATA_CODEC_H

#include <cstddef>

class IDataCodec
{
public:

	virtual ~IDataCodec() {}

	/*************************************************************
	*	函数: 				reset
	*	功能:				用于重置解码器状态
	*	参数:				无
	*	返回值:				无
	**************************************************************/
	virtual void reset() = 0;

	/*************************************************************
	*	函数: 				encode
	*	功能:				对数据进行编码
	*	参数:
	*		data:			要编码的数据
	*		length:			要编码的数据长度
	*		buffer:			存储编码后的数据缓冲区
	* 		byte:			存储编码后的数据缓冲区大小
	*
	*	返回值:
	*		>0:				编码成功, 数据存放在 buffer
	*		 0:				编码失败, 通常是缓冲区大小不足
	**************************************************************/
	virtual int encode(const void* data, size_t length, void* buffer, size_t size) = 0;

	/*************************************************************
	*	函数: 				decode
	*	功能:				对数据进行解码, 内部应使用状态机实现解析
	*	参数:
	*		data:			一字节数据
	*		buffer:			存放解码后的数据缓冲区
	* 		byte:			存放解码后的数据缓冲区大小
	*
	*	返回值:
	*		 0:				正在编码, 中间数据存放在 buffer
	*		>0:				解码成功, 返回有效数据的长度
	*		-1:				解码失败, 缓冲区不足
	*		-2:				解码失败, 数据校验不通过
	**************************************************************/
	virtual int decode(unsigned char data, void* buffer, size_t size) = 0;

};

#endif

IDataStream

/**
******************************************************************************
* @文件		IDataStream.h
* @版本		V1.0.0
* @日期
* @概要		数据通信接口定义
* @作者		lmx
******************************************************************************
* @注意
*
******************************************************************************
*/

#ifndef __IDATA_STREAM_H
#define __IDATA_STREAM_H

#include <cstddef>

class IDataStream
{

public:

	virtual ~IDataStream() {}

	/*************************************************************
	*	函数: 				isOpen
	*	功能:				用于判断数据流是否已经被打开
	*	参数:				无
	*	返回值:
	*		true:  			数据流已经被打开
	*		false: 			数据流尚未被打开
	**************************************************************/
	virtual bool isOpen() = 0;

	/*************************************************************
	*	函数: 				open
	*	功能:				用于打开数据流
	*	参数:				无
	*	返回值:
	*		true:  			数据流打开成功
	*		false: 			数据流打开失败
	**************************************************************/
	virtual bool open() = 0;

	/*************************************************************
	*	函数: 				recv
	*	功能:				用于接收数据流
	*	参数:
	*		buffer: 		用于存储数据的缓冲区
	*		size:			用于指示该缓冲区的大小
	*	返回值:
	*		0:  			没有数据
	*		-1: 			接收数据出错
	*		>0:				收到有效数据
	**************************************************************/
	virtual int recv(void* buffer, size_t size) = 0;

	/*************************************************************
	*	函数: 				send
	*	功能:				用于发送数据流
	*	参数:
	*		data:  			指定要发送的数据
	*		length:			指定要发送数据的长度
	*	返回值:
	*		true: 			已成功发送数据
	*		false:			发送数据出错
	**************************************************************/
	virtual bool send(const void* data, size_t length) = 0;

	/*************************************************************
	*	函数: 				Close
	*	功能:				用于关闭数据流
	*	参数:				无
	*	返回值:				无
	**************************************************************/
	virtual void close() = 0;

};

#endif

DataCodecCi110x

/**
******************************************************************************
* @文件		DataCodecCi110x.h
* @版本		V1.0.0
* @日期
* @概要		Ci110x 系列芯片数据编解码实现
* @作者		lmx
******************************************************************************
* @注意
******************************************************************************
*/

#ifndef __DATA_CODEC_CI110X_H
#define __DATA_CODEC_CI110X_H

#include "IDataCodec.h"

class DataCodecCi110x : public IDataCodec
{

public: // 通过 IDataCodec 继承

	/*************************************************************
	*	函数: 				reset
	*	功能:				用于重置解码器状态
	*	参数:				无
	*	返回值:				无
	**************************************************************/
	virtual void reset() override;

	/*************************************************************
	*	函数: 				encode
	*	功能:				对数据进行编码
	*	参数:
	*		data:			要编码的数据
	*		length:			要编码的数据长度
	*		buffer:			存储编码后的数据缓冲区
	* 		byte:			存储编码后的数据缓冲区大小
	*
	*	返回值:
	*		>0:				编码成功, 数据存放在 buffer
	*		 0:				编码失败, 通常是缓冲区大小不足
	**************************************************************/
	virtual int encode(const void* data, size_t length, void* buffer, size_t size) override;

	/*************************************************************
	*	函数: 				decode
	*	功能:				对数据进行解码, 内部应使用状态机实现解析
	*	参数:
	*		data:			一字节数据
	*		buffer:			存放解码后的数据缓冲区
	* 		byte:			存放解码后的数据缓冲区大小
	*
	*	返回值:
	*		 0:				正在编码, 中间数据存放在 buffer
	*		>0:				解码成功, 返回有效数据的长度
	*		-1:				解码失败, 缓冲区不足
	*		-2:				解码失败, 数据校验不通过
	**************************************************************/
	virtual int decode(unsigned char data, void* buffer, size_t size) override;

};

#endif
/**
******************************************************************************
* @文件		DataCodecCi110x.h
* @版本		V1.0.0
* @日期
* @概要		Ci110x 系列芯片数据编解码实现
* @作者		lmx
******************************************************************************
* @注意
******************************************************************************
*/

#include <iostream>
#include "DataCodecCi110x.h"

void DataCodecCi110x::reset()
{
    std::cout << "DataCodecCi110x::reset()..." << std::endl;
}

int DataCodecCi110x::encode(const void* data, size_t length, void* buffer, size_t size)
{
    std::cout << "DataCodecCi110x::encode()..." << std::endl;

    return 0;
}

int DataCodecCi110x::decode(unsigned char data, void* buffer, size_t size)
{
    std::cout << "DataCodecCi110x::decode()..." << std::endl;

    return 0;
}

DataStreamSerial

/**
******************************************************************************
* @文件		DataStreamSerial.h
* @版本		V1.0.0
* @日期
* @概要		基于串口通信实现的数据通信功能
* @作者		lmx
******************************************************************************
* @注意
*
******************************************************************************
*/

#ifndef __DATA_STREAM_SERIAL_H
#define __DATA_STREAM_SERIAL_H

#include "IDataStream.h"

class DataStreamSerial : public IDataStream
{
private:

	volatile bool bOpen = false; // 为了方便模拟而定义的状态变量

public: // 串口通信特有的配置

	/*************************************************************
	*	函数: 				setParameter
	*	功能:				用于设置串口参数
	*	参数:				无
	*	返回值:
	*		devpath:  		串口设备节点
	*		baudrate: 		波特率(默认9600)
	*		databit:		数据位(默认8)
	*		stopbit:		停止位(默认1)
	**************************************************************/
	bool setParameter(const char* devpath, unsigned int baudrate = 9600, int databit = 8, int stopbit = 1);

public: // 通过 IDataStream 继承

	/*************************************************************
	*	函数: 				isOpen
	*	功能:				用于判断数据流是否已经被打开
	*	参数:				无
	*	返回值:
	*		true:  			数据流已经被打开
	*		false: 			数据流尚未被打开
	**************************************************************/
	virtual bool isOpen() override;

	/*************************************************************
	*	函数: 				open
	*	功能:				用于打开数据流
	*	参数:				无
	*	返回值:
	*		true:  			数据流打开成功
	*		false: 			数据流打开失败
	**************************************************************/
	virtual bool open() override;

	/*************************************************************
	*	函数: 				recv
	*	功能:				用于接收数据流
	*	参数:
	*		buffer: 		用于存储数据的缓冲区
	*		size:			用于指示该缓冲区的大小
	*	返回值:
	*		0:  			没有数据
	*		-1: 			接收数据出错
	*		>0:				收到有效数据
	**************************************************************/
	virtual int recv(void* buffer, size_t size) override;

	/*************************************************************
	*	函数: 				send
	*	功能:				用于发送数据流
	*	参数:
	*		data:  			指定要发送的数据
	*		length:			指定要发送数据的长度
	*	返回值:
	*		true: 			已成功发送数据
	*		false:			发送数据出错
	**************************************************************/
	virtual bool send(const void* data, size_t length) override;

	/*************************************************************
	*	函数: 				Close
	*	功能:				用于关闭数据流
	*	参数:				无
	*	返回值:				无
	**************************************************************/
	virtual void close() override;

};

#endif
/**
******************************************************************************
* @文件		DataStreamSerial.cpp
* @版本		V1.0.0
* @日期
* @概要		基于串口通信实现的数据通信功能
* @作者		lmx
******************************************************************************
* @注意
*
******************************************************************************
*/
#include <windows.h>
#include <iostream>
#include "DataStreamSerial.h"

bool DataStreamSerial::setParameter(const char* devpath, unsigned int baudrate, int databit, int stopbit)
{
	std::cout << "DataStreamSerial::setParameter()..." << std::endl;

	return true;
}

bool DataStreamSerial::isOpen()
{
	std::cout << "DataStreamSerial::isOpen()..." << std::endl;

	return bOpen;
}

bool DataStreamSerial::open()
{
	std::cout << "DataStreamSerial::open()..." << std::endl;
	bOpen = true;

	return bOpen;
}

int DataStreamSerial::recv(void* buffer, size_t size)
{
	std::cout << "DataStreamSerial::recv()..." << std::endl;
	Sleep(5000);
	return 100;
}

bool DataStreamSerial::send(const void* data, size_t length)
{
	std::cout << "DataStreamSerial::send()..." << std::endl;

	return true;
}

void DataStreamSerial::close()
{
	std::cout << "DataStreamSerial::close()..." << std::endl;
	bOpen = false;

	return;
}

DataTransfer

/**
******************************************************************************
* @文件		DataTransfer.h
* @版本		V1.0.0
* @日期
* @概要		数据传输实现
* @作者		lmx
******************************************************************************
* @注意
******************************************************************************
*/

#ifndef __DATA_TRANSFER_H
#define __DATA_TRANSFER_H

#include <queue>
#include <mutex>
#include <thread>
#include <cstddef>
#include <functional> 
#include <condition_variable>

#include "DataCodec/IDataCodec.h"
#include "DataStream/IDataStream.h"

class DataTransfer
{

public:

	// 传输状态定义
	typedef enum {
		DATA_TRANSFER_STATE_NORMAL = 0,							// 传输正常
		DATA_TRANSFER_STATE_START = 1,							// 传输启动
		DATA_TRANSFER_STATE_STOP = 2,							// 传输停止
		DATA_TRANSFER_STATE_OTHER_ERROR = 3,					// 传输失败, 其它错误
		DATA_TRANSFER_STATE_VERIFY_ERROR = 4,					// 传输失败, 校验错误
		DATA_TRANSFER_STATE_MEMORY_ERROR = 5,					// 传输失败, 申请内存空间失败
		DATA_TRANSFER_STATE_RAWDATA_ERROR = 6,					// 传输失败, 原始数据接收错误
	}DATA_TRANSFER_STATE_E;
	const char* toString(DATA_TRANSFER_STATE_E state);			// 传输状态转换为可读性更高的字符串

	// 接收到数据通知回调原型
	typedef std::function<void(DATA_TRANSFER_STATE_E state, void* pdata, size_t length)> TDataRecvNotice;

private:

	std::shared_ptr<IDataStream>	pDataStream;				// 具体的数据流(可以是网络\串口\USB\I2C等等)
	std::shared_ptr<IDataCodec>		pDataCodec;					// 具体的数据编解码(对应不同的通讯协议)
	size_t							nConfigBufferSize;			// 数据收发缓冲区大小

private:

	TDataRecvNotice onDataRecvNotice;							// 数据接收状态通知回调
	void notice(DATA_TRANSFER_STATE_E state, void* pdata = NULL, size_t length = 0);

private:

	void* pSendBuffer;											// 发送数据缓冲区
	std::mutex						mMutexTransfer;				// 传输数据互斥体, 实现线程安全

	std::queue<uint8_t>				mQueueRawData;				// 存储原始数据的队列
	std::mutex						mMutexQueueRawData;			// 原始数据队列互斥体, 用于同步接收线程和处理线程
	std::condition_variable			mCondQueueDataReady;		// 用于通知和唤醒处理线程, 表明数据已经就绪

	std::thread						mThreadRecvRawData;			// 原始数据接收线程
	std::thread						mThreadRecvDataProcess;		// 数据解码处理线程

	static void onThreadRecvRawData(DataTransfer* pContex);
	static void onThreadRecvDataProcess(DataTransfer* pContex);

public:

	/*************************************************************
	*	函数: 					DataTransfer
	*	功能:					初始化数据传输对象
	*	参数:
	*		pStream:			具体的数据流对象
	*		pCodec:				具体的数据编解码器
	*		onNotice:			数据接收通知, 有数据时或传输状态变化时会通过此回调回传
	*		nBufferSize:		数据缓冲区的大小, 用于指定接收和发送缓冲区
	*	返回值:					无
	**************************************************************/
	DataTransfer(std::shared_ptr<IDataStream> pStream, std::shared_ptr<IDataCodec> pCodec, TDataRecvNotice onNotice, size_t nBufferSize = 2048);

	/*************************************************************
	*	函数: 					InitAndStart
	*	功能:					初始化并启动数据监听
	*	参数:					无
	*	返回值:					无
	**************************************************************/
	bool initAndStart();

	/*************************************************************
	*	函数: 					StopAndRelease
	*	功能:					停止数据监听并释放相关资源
	*	参数:					无
	*	返回值:					无
	**************************************************************/
	bool stopAndRelease();

	/*************************************************************
	*	函数: 					Transfer
	*	功能:					要传输的数据, 会通过初始化指定的编码器进行编码, 并通过初始化指定的数据流对象发送出去
	*	参数:
	*		pdata:				要发送的数据
	*		length:				所发送数据的长度
	*	返回值:					无
	**************************************************************/
	bool transfer(const void* pdata, size_t length);

};

#endif
/**
******************************************************************************
* @文件		DataTransfer.cpp
* @版本		V1.0.0
* @日期
* @概要		数据传输
* @作者		lmx
******************************************************************************
* @注意
*
******************************************************************************
*/
#include <stdlib.h>
#include <string.h>
#include "DataTransfer.h"

/*************************************************************
*	函数: 					DataTransfer
*	功能:					初始化数据传输对象
*	参数:
*		pStream:			具体的数据流对象
*		pCodec:				具体的数据编解码器
*		onNotice:			数据接收通知, 有数据时或传输状态变化时会通过此回调回传
*		nBufferSize:		数据缓冲区的大小, 用于指定接收和发送缓冲区
*	返回值:					无
**************************************************************/
DataTransfer::DataTransfer(std::shared_ptr<IDataStream> pStream, std::shared_ptr<IDataCodec> pCodec, TDataRecvNotice onNotice, size_t nBufferSize)
{
	pSendBuffer = NULL;
	pDataStream = pStream;
	pDataCodec = pCodec;
	onDataRecvNotice = onNotice;
	nConfigBufferSize = nBufferSize;
}

// 接收数据通知
void DataTransfer::notice(DATA_TRANSFER_STATE_E state, void* pdata, size_t length)
{
	if (onDataRecvNotice) {
		onDataRecvNotice(state, pdata, length);
	}
}

// 原始数据接收线程
void DataTransfer::onThreadRecvRawData(DataTransfer* pContex)
{
	void* pRecvBuffer = NULL;
	int nRecvByte = 0;

	// 申请内存空间用于存储原始数据
	pRecvBuffer = (void*)malloc(pContex->nConfigBufferSize);
	if (NULL == pRecvBuffer) {
		pContex->notice(DATA_TRANSFER_STATE_MEMORY_ERROR);
		pContex->notice(DATA_TRANSFER_STATE_STOP);
		return;
	}

	while (pContex->pDataStream->isOpen())
	{
		// 从数据流中接收原始数据
		memset(pRecvBuffer, 0, pContex->nConfigBufferSize);
		nRecvByte = pContex->pDataStream->recv(pRecvBuffer, pContex->nConfigBufferSize);
		if (!pContex->pDataStream->isOpen()) {
			break;
		}

		// 如果出错则通知业务逻辑
		if (nRecvByte < 0) {
			pContex->notice(DATA_TRANSFER_STATE_RAWDATA_ERROR);
			continue;
		}

		// 将收到的数据, 写入队列
		std::unique_lock< std::mutex > lock(pContex->mMutexQueueRawData);
		for (int i = 0; i < nRecvByte; i++) {
			pContex->mQueueRawData.push(((uint8_t*)pRecvBuffer)[i]);
		}
		lock.unlock();

		// 通知数据解析线程
		pContex->mCondQueueDataReady.notify_one();
	}

	pContex->notice(DATA_TRANSFER_STATE_STOP);
	free(pRecvBuffer);

	return;
}

// 数据解码线程
void DataTransfer::onThreadRecvDataProcess(DataTransfer* pContex)
{
	std::queue<uint8_t>		mQueueRawData;
	void* pDataBuffer = NULL;
	unsigned char			data = 0;
	int 					nDecodeByte = 0;

	// 用于存储解码出来的数据
	pDataBuffer = malloc(pContex->nConfigBufferSize);
	if (NULL == pDataBuffer) {
		pContex->notice(DATA_TRANSFER_STATE_MEMORY_ERROR);
		pContex->notice(DATA_TRANSFER_STATE_STOP);
		return;
	}

	// 进入数据解码流程
	pContex->pDataCodec->reset();
	while (pContex->pDataStream->isOpen())
	{
		// 获得锁之后判断数据流是否有效, 无效则需要退出, 避免线程在 wait 之前被 notify_all 
		std::unique_lock< std::mutex > lock(pContex->mMutexQueueRawData);
		if (!pContex->pDataStream->isOpen()) {
			break;
		}

		// 再次确认队列数据中没有数据了, 再进入等待状态, 如果有则意味着解码的过程仍收到数据, 需要继续解码
		if (pContex->mQueueRawData.empty()) {
			pContex->mCondQueueDataReady.wait(lock);
			if (!pContex->pDataStream->isOpen()) { // 被唤醒之后仍需要先判断数据流是否有效, 无效则直接退出循环
				break;
			}
		}

		// 拷贝数据及时释放数据锁, 避免影响数据接收线程的实时性
		mQueueRawData = pContex->mQueueRawData;
		pContex->mQueueRawData = std::queue<uint8_t>();
		lock.unlock();

		// 开始进行数据解码
		while (!mQueueRawData.empty())
		{
			data = mQueueRawData.front();
			mQueueRawData.pop();

			// 逐个字节进行解码
			nDecodeByte = pContex->pDataCodec->decode(data, pDataBuffer, pContex->nConfigBufferSize);
			if (nDecodeByte > 0) {
				pContex->notice(DATA_TRANSFER_STATE_NORMAL, pDataBuffer, nDecodeByte);
				continue;
			}

			// 解码的数据超出缓冲区大小
			if (-1 == nDecodeByte) {
				pContex->notice(DATA_TRANSFER_STATE_MEMORY_ERROR);
				continue;
			}

			// 解码的数据校验不通过
			if (-2 == nDecodeByte) {
				pContex->notice(DATA_TRANSFER_STATE_VERIFY_ERROR);
				continue;
			}

			// 其它错误
			if (nDecodeByte < 0) {
				pContex->notice(DATA_TRANSFER_STATE_OTHER_ERROR);
				continue;
			}
		}
	}

	free(pDataBuffer);

	return;
}

// 数据传输
bool DataTransfer::transfer(const void* pdata, size_t length)
{
	int nEncodeByte = 0;
	bool bSendResult = false;

	// 此接口极有可能是被并发调用, 因此需要上锁确保共享缓冲区不被破坏
	// 也可以避免同时调用了 StopAndRelease() 接口所引发的异常
	mMutexTransfer.lock();
	if (pDataStream->isOpen()) {
		nEncodeByte = pDataCodec->encode(pdata, length, pSendBuffer, nConfigBufferSize);
		if (nEncodeByte) {
			bSendResult = pDataStream->send(pSendBuffer, nEncodeByte);
		}
	}
	mMutexTransfer.unlock();

	return bSendResult;
}

/*************************************************************
*	函数: 					InitAndStart
*	功能:					初始化并启动数据监听
*	参数:					无
*	返回值:					无
**************************************************************/
bool DataTransfer::initAndStart()
{
	// 参数检查
	if (NULL == pDataStream || NULL == pDataCodec || 0 == nConfigBufferSize || pSendBuffer) {
		return false;
	}

	// 打开数据流
	if (pDataStream->open() == false) {
		return false;
	}

	// 申请内存空间用于发送数据缓冲区
	pSendBuffer = malloc(nConfigBufferSize);
	if (NULL == pSendBuffer) {
		pDataStream->close();
		return false;
	}

	// 创建数据流处理线程
	mThreadRecvRawData = std::thread(onThreadRecvRawData, this);
	mThreadRecvDataProcess = std::thread(onThreadRecvDataProcess, this);
	notice(DATA_TRANSFER_STATE_START);

	return true;
}

/*************************************************************
*	函数: 					StopAndRelease
*	功能:					停止数据监听并释放相关资源
*	参数:					无
*	返回值:					无
**************************************************************/
bool DataTransfer::stopAndRelease()
{
	mMutexTransfer.lock();
	if (pDataStream->isOpen())
	{
		mMutexQueueRawData.lock();
		pDataStream->close();
		mCondQueueDataReady.notify_all();
		mMutexQueueRawData.unlock();

		mThreadRecvRawData.join();
		mThreadRecvDataProcess.join();

		if (pSendBuffer) {
			free(pSendBuffer);
			pSendBuffer = NULL;
		}
	}
	mMutexTransfer.unlock();

	return true;
}


/*************************************************************
*	函数: 					toString
*	功能:					用于将状态转换为字符串的方式输出
*	参数:
*			state:			传入要转换字符串的状态
*	返回值:					无
**************************************************************/
const char* DataTransfer::toString(DATA_TRANSFER_STATE_E state)
{
	switch (state)
	{
	case DATA_TRANSFER_STATE_NORMAL:
		return "DATA_TRANSFER_STATE_NORMAL";

	case DATA_TRANSFER_STATE_START:
		return "DATA_TRANSFER_STATE_START";

	case DATA_TRANSFER_STATE_STOP:
		return "DATA_TRANSFER_STATE_STOP";

	case DATA_TRANSFER_STATE_OTHER_ERROR:
		return "DATA_TRANSFER_STATE_OTHER_ERROR";

	case DATA_TRANSFER_STATE_VERIFY_ERROR:
		return "DATA_TRANSFER_STATE_VERIFY_ERROR";

	case DATA_TRANSFER_STATE_MEMORY_ERROR:
		return "DATA_TRANSFER_STATE_MEMORY_ERROR";

	case DATA_TRANSFER_STATE_RAWDATA_ERROR:
		return "DATA_TRANSFER_STATE_RAWDATA_ERROR";
	}

	return "Undefined String";
}

应用示例

/**
******************************************************************************
* @文件		DeviceCi110x.h
* @版本		V1.0.0
* @日期
* @概要		Ci110x 设备操作接口
* @作者		lmx
******************************************************************************
* @注意
******************************************************************************
*/

#ifndef __DEVICE_CI110X_H
#define __DEVICE_CI110X_H

#include "../DataTransfer/DataTransfer.h"
#include "../DataTransfer/DataCodec/DataCodecCi110x.h"
#include "../DataTransfer/DataStream/DataStreamSerial.h"

class DeviceCi110x
{
private:

	#define DATA_TRANSFER_BUFFER_SIZE	(2048)
	std::shared_ptr<DataTransfer>		spDataTransfer;
	void onDataRecvNotice(DataTransfer::DATA_TRANSFER_STATE_E state, void* pdata, size_t length);

public:

	bool init(const char* devpath);
	void release();

	bool setAsrMode(bool en);

};

#endif
/**
******************************************************************************
* @文件		DeviceCi110x.h
* @版本		V1.0.0
* @日期
* @概要		Ci110x 设备操作接口
* @作者		lmx
******************************************************************************
* @注意
******************************************************************************
*/
#include <iostream>
#include "DeviceCi110x.h"

void DeviceCi110x::onDataRecvNotice(DataTransfer::DATA_TRANSFER_STATE_E state, void* pdata, size_t length)
{
	std::cout << "DataTransfer State:" << spDataTransfer->toString(state) << std::endl;
}

bool DeviceCi110x::init(const char* devpath)
{
	std::shared_ptr<DataCodecCi110x>	pCodecCi110x = std::make_shared<DataCodecCi110x>();
	std::shared_ptr<DataStreamSerial>	pStreamSerial = std::make_shared<DataStreamSerial>();
	DataTransfer::TDataRecvNotice		onDataRecvNotice = std::bind(&DeviceCi110x::onDataRecvNotice, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

	pStreamSerial->setParameter(devpath, 115200, 8, 1);
	spDataTransfer = std::make_shared<DataTransfer>(pStreamSerial, pCodecCi110x, onDataRecvNotice, DATA_TRANSFER_BUFFER_SIZE);
	return spDataTransfer->initAndStart();
}

void DeviceCi110x::release()
{
	spDataTransfer->stopAndRelease();
}


bool DeviceCi110x::setAsrMode(bool en)
{
	const char data[10] = { 0 };
	return spDataTransfer->transfer(data, sizeof(data));
}
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include "Devices/DeviceCi110x.h"

int main()
{
    DeviceCi110x mDeviceCi110x;

    mDeviceCi110x.init("/dev/ttyS1");
    mDeviceCi110x.setAsrMode(true);
    mDeviceCi110x.release();

    return 0;
}


 

标签:pContex,数据,TRANSFER,void,通信协议,STATE,数据传输,DATA,通信接口
来源: https://blog.csdn.net/lovemengx/article/details/111446534

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有