C++反射实现

内容来自别人的内容 记录下

1.需要一个单例模式Singleton.h

#pragma once

 
template <typename T>
class Singleton
{
public:
    static T * instance()
    {
        if (m_instance == NULL)
            m_instance = new T();
        return m_instance;
    }
 
private:
    Singleton() {}
    Singleton(const Singleton<T> &);
    Singleton<T> & operator = (const Singleton<T> &);
    ~Singleton() {std::cout<<"Descontructor :"<<m_instance<<std::endl;}
 
private:
    static T * m_instance;
};
 
template <typename T>
T * Singleton<T>::m_instance = NULL;

2.类成员 ClassField.h

#pragma once
 
#include <string>
using namespace std;
 
 
class ClassField
{
public:
    ClassField() : m_name(""), m_type(""), m_offset(0) {}
    ClassField(const string & name, const string & type, size_t offset) : m_name(name), m_type(type), m_offset(offset) {}
    ~ClassField() {}
 
    const string & name()
    {
        return m_name;
    }
 
    const string & type()
    {
        return m_type;
    }
 
    size_t offset()
    {
        return m_offset;
    }
 
private:
    string m_name;
    string m_type;
    size_t m_offset;
};
 

3.类方法 ClassMethod.h

#pragma once
 
#include <string>
using namespace std;
 
 
class ClassMethod
{
public:
    ClassMethod() : m_name(""), m_method(0) {}
    ClassMethod(const string & name, uintptr_t method) : m_name(name), m_method(method) {}
    ~ClassMethod() {}
 
    const string & name()
    {
        return m_name;
    }
 
    uintptr_t method()
    {
        return m_method;
    }
 
private:
    string m_name;
    uintptr_t m_method;
};
 

4.注册类 ClassReg.h

#pragma once

#include "ReflexBase.h"

 

class ClassRegister
{
public:
    ClassRegister(const string & className, create_object method)
    {
        // register class
        Singleton<ClassFactory>::instance()->register_class(className, method);
    }
 
    ClassRegister(const string & className, const string & fieldName, const string & fieldType, uintptr_t offset)
    {
        // register class field
        Singleton<ClassFactory>::instance()->register_class_field(className, fieldName, fieldType, offset);
    }
 
    ClassRegister(const string & className, const string & methodName, uintptr_t method)
    {
        // register class method
        Singleton<ClassFactory>::instance()->register_class_method(className, methodName, method);
    }
};
 

#if 0

#define REGISTER_CLASS(className)                                       \
    Object * createObject##className()                                  \
    {                                                                   \
        Object * obj = new className();                                 \
        obj->set_class_name(#className);                                \
        return obj;                                                     \
    }                                                                  	\
    ClassRegister classRegister##className(#className, createObject##className)
#else
#define REGISTER_CLASS(className)                                       \
		  IQMCY * createObject##className()											 \
		  {																						 \
				IQMCY * obj = new className();											 \
				obj->set_class_name(#className); 										 \
				return obj; 																	 \
		  }																						 \
		  ClassRegister classRegister##className(#className, createObject##className)

#endif
 
#define REGISTER_CLASS_FIELD(className, fieldName, fieldType) \
    className className##fieldName; \
    ClassRegister classRegister##className##fieldName(#className, #fieldName, #fieldType, (size_t)(&(className##fieldName.fieldName)) - (size_t)(&className##fieldName))
 
#define REGISTER_CLASS_METHOD(className, methodName, returnType, ...) \
    std::function<returnType(className *, ##__VA_ARGS__)> className##methodName##method = &className::methodName; \
    ClassRegister classRegister##className##methodName(#className, #methodName, (uintptr_t)&(className##methodName##method))

5.基类ReflexBase.h

#pragma once

#include <iostream>
#include <atomic>
#include<vector>
#include<unordered_map>
#include<map>

#include<tuple>
#include <thread>
#include <memory>
#include <mutex>



#include<functional>

#include "httplib.h"

#include "md5.h"
#include "base64.h"
#include "des.h"
#include "utils.h"



#include "zlog.h" 



#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <functional>





using namespace std;
 
#include "Singleton.h"

 
#include "ClassField.h"
#include "ClassMethod.h"
 
#if 1

#include "zlog.h"
#include "IBase.h"


#endif
 
class IQMCY
{
public:
    IQMCY();
    virtual ~IQMCY();

	
    void set_class_name(const string & className);
    const string & get_class_name() const;
 
    int get_field_count();
    ClassField * get_field(int pos);
    ClassField * get_field(const string & fieldName);
 
    template <typename T>
    void get(const string & fieldName, T & value);
 
    template <typename T>
    void set(const string & fieldName, const T & value);
    void set(const string & fieldName, const char * value);
    
    template <typename R = void, typename ...Args>
    R call(const string & methodName, Args... args);


#if 1 

	using MessageWatcher = std::function<void (std::string &)>;
	using LedResponse = std::function<void (int,unsigned char *,int )>;


	virtual int LED_Open(std::string snid,std::string ip,std::string resolution,int port,std::string bmsid,std::string server_ip,int server_port,bool encrypt,bool isDebugMode) = 0;
	virtual STATUS_CODE NVR_SetLED(PLAYLIST *playlist) = 0;		
	virtual STATUS_CODE NVR_GetLEDState() = 0;				
	virtual std::string NVR_GetBrand() = 0;		
	virtual std::pair<int ,std::string> NVR_GetStatus() = 0; 			
	std::pair<long ,int> NVR_GetActiveTime() ;

	void NVR_SetKeepLiveTime(int time) ;		
public:		

	MessageWatcher m_cb;
	LedResponse m_socket_cb = nullptr;	
	bool m_run_flag;						
	bool m_debug_mode;			
	uint64_t m_counter = 0;
protected:		
	virtual int NVR_Close(void) =0; 	
	virtual void NVR_UpdateActiveTime() final;
	void NVR_SetCB(MessageWatcher);
	void NVR_SetRecvCB(LedResponse); 	
	void NVR_Response(std::string &content);		
	void NVR_DefaultCB(std::string &content);
	int NVR_Fly2LEDEx(int cmd,char *data,int len);		
	int NVR_Fly2LED(int cmd,char *data,int len);

	int NVR_CreateSocket(const char *led_ip,int port);
	int CreateAsyncSocket(const char *led_ip,int port, int time_out);

	void PrintHex(unsigned char *data,int len);
	unsigned short NVR_GetCRC( unsigned char* buffer, int buffer_length);
	std::string m_ip;
	std::string m_resolution;
	std::string m_bmsid; 	
	std::string m_task_id;				
	
	std::mutex m_led_mutex;
	
	std::string m_server_ip;
	std::string m_snid;
	std::string m_fault_msg;
	int m_server_port;
	int m_led_socket;
	bool m_encrypt = false;

	int	m_status;
	int	m_result;		
	int	m_port;

	std::atomic<long> m_last_acess_time;
	int m_keep_live_time;
#endif
	 
protected:
    string m_className;
};
 
typedef IQMCY * (*create_object)(void);
 
class ClassFactory
{
    friend class Singleton<ClassFactory>;
public:
    // reflect class
    void register_class(const string & className, create_object method);
    IQMCY * create_class(const string & className);
 
    // reflect class field
    void register_class_field(const string & className, const string & fieldName, const string & fieldType, size_t offset);
    int get_class_field_count(const string & className);
    ClassField * get_class_field(const string & className, int pos);
    ClassField * get_class_field(const string & className, const string & fieldName);
 
    // reflect class method
    void register_class_method(const string & className, const string &methodName, uintptr_t method);
    int get_class_method_count(const string & className);
    ClassMethod * get_class_method(const string & className, int pos);
    ClassMethod * get_class_method(const string & className, const string & methodName);
 
private:
    ClassFactory() {}
    ~ClassFactory() {std::cout<<__func__<<std::endl;}
 
private:
    std::map<string, create_object> m_classMap;
    std::map<string, std::vector<ClassField *>> m_classFields;
    std::map<string, std::vector<ClassMethod *>> m_classMethods;
};
 
template <typename T>
void IQMCY::get(const string & fieldName, T & value)
{
    ClassField * field = Singleton<ClassFactory>::instance()->get_class_field(m_className, fieldName);
    size_t offset = field->offset();
    value = *((T *)((unsigned char *)(this) + offset));
}
 
template <typename T>
void IQMCY::set(const string & fieldName, const T & value)
{
    ClassField * field = Singleton<ClassFactory>::instance()->get_class_field(m_className, fieldName);
    size_t offset = field->offset();
    *((T *)((unsigned char *)(this) + offset)) = value;
}
 
template <typename R, typename ...Args>
R IQMCY::call(const string & methodName, Args... args)
{
    ClassFactory * factory = Singleton<ClassFactory>::instance();
    ClassMethod * method = factory->get_class_method(m_className, methodName);
    auto func = method->method();
    typedef std::function<R(decltype(this), Args...)> class_method;
    return (*((class_method *)func))(this, args...);
}
 

6.基类CPPReflexBase.cpp

#include "ReflexBase.h"

#include <sys/time.h>
#include "json.hpp"
#include <sys/ioctl.h>

 
void IQMCY::set_class_name(const string & className)
{
    m_className = className;
}
 
const string & IQMCY::get_class_name() const
{
    return m_className;
}
 
int IQMCY::get_field_count()
{
    return Singleton<ClassFactory>::instance()->get_class_field_count(m_className);
}
 
ClassField * IQMCY::get_field(int pos)
{
    return Singleton<ClassFactory>::instance()->get_class_field(m_className, pos);
}
 
ClassField * IQMCY::get_field(const string & fieldName)
{
    return Singleton<ClassFactory>::instance()->get_class_field(m_className, fieldName);
}
 
void IQMCY::set(const string & fieldName, const char * value)
{
    ClassField * field = Singleton<ClassFactory>::instance()->get_class_field(m_className, fieldName);
    size_t offset = field->offset();
    *((string *)((unsigned char *)(this) + offset)) = string(value);
}
 
void ClassFactory::register_class(const string & className, create_object method)
{
	 std::cout<<"register_class "<<className<<std::endl;

    m_classMap[className] = method;
}
 
IQMCY * ClassFactory::create_class(const string & className)
{
    auto it = m_classMap.find(className);
    if (it == m_classMap.end())
    {
    		std::cout<<"can not find class"<<std::endl;
        return nullptr;
    }
	std::cout<<"Find class:"<<it->second()<<std::endl;	 
    return it->second();
}
 
void ClassFactory::register_class_field(const string & className, const string & fieldName, const string & fieldType, size_t offset)
{
    m_classFields[className].push_back(new ClassField(fieldName, fieldType, offset));
}
 
int ClassFactory::get_class_field_count(const string & className)
{
    return m_classFields[className].size();
}
 
ClassField * ClassFactory::get_class_field(const string & className, int pos)
{
    int size = m_classFields[className].size();
    if (pos < 0 || pos >= size)
    {
        return nullptr;
    }
    return m_classFields[className][pos];
}
 
ClassField * ClassFactory::get_class_field(const string & className, const string & fieldName)
{
    auto fields = m_classFields[className];
    for (auto it = fields.begin(); it != fields.end(); it++)
    {
        if ((*it)->name() == fieldName)
        {
            return *it;
        }
    }
    return nullptr;
}
 
void ClassFactory::register_class_method(const string & className, const string &methodName, uintptr_t method)
{
    m_classMethods[className].push_back(new ClassMethod(methodName, method));
}
 
int ClassFactory::get_class_method_count(const string & className)
{
    return m_classMethods[className].size();
}
 
ClassMethod * ClassFactory::get_class_method(const string & className, int pos)
{
    int size = m_classMethods[className].size();
    if (pos < 0 || pos >= size)
    {
        return nullptr;
    }
    return m_classMethods[className][pos];
}
 
ClassMethod * ClassFactory::get_class_method(const string & className, const string & methodName)
{
    auto methods = m_classMethods[className];
    for (auto it = methods.begin(); it != methods.end(); it++)
    {
        if ((*it)->name() == methodName)
        {
            return *it;
        }
    }
    return nullptr;
}

#if 1

void IQMCY::NVR_DefaultCB(std::string &content)
{
	std::cout<<__FUNCTION__<<content<<std::endl;
}


IQMCY::IQMCY()
{
	m_last_acess_time.store(0);
	m_keep_live_time = 120;
	m_led_socket	 = 0;
	NVR_SetCB(std::bind(&IQMCY::NVR_DefaultCB, this, std::placeholders::_1));
	
}


std::pair<long ,int> IQMCY::NVR_GetActiveTime()
{
	std::pair<long ,int>ret;
	return std::make_pair(m_last_acess_time.load(),m_keep_live_time);
}


unsigned short IQMCY::NVR_GetCRC(unsigned char* buffer, int buffer_length)
{
	unsigned char c, treat, bcrc;
	unsigned short wcrc = 0;
	int i,j;
    for (i = 0; i < buffer_length; i++) 
	{
        c = buffer[i];
        for (j = 0; j < 8; j++) 
		{
            treat = c & 0x80;
            c <<= 1;
            bcrc = (wcrc >> 8) & 0x80;
            wcrc <<= 1;
            if (treat != bcrc)
                wcrc ^= 0x1021;
        }
    }
    return wcrc;
}


void IQMCY::PrintHex(unsigned char *data,int len)
{
	printf("~~~~~~~~~~~~~~~~~~~~~~~~\n");
	for(int i = 0;i<len;i++)
	{
		printf("%02X ",data[i]);
		if((i+1) %16 == 0) printf("\n");
	}
	printf("\n~~~~~~~~~~~~~~~~~~~~~~~~\n");	
}


int IQMCY::NVR_CreateSocket(const char *led_ip,int port)
{

	int socket_fd = socket(AF_INET,SOCK_STREAM,0);


	if (socket_fd == INVALID_SOCKET) 
	{
		printf("Create socket error\n");
		zlog_fatal(g_zlog,"Create socket error\n");
		return -1;
	}

	struct timeval timeout = {3,0};
	
	const char *server_ip = led_ip;
 	struct sockaddr_in server_addr;
 
	bzero(&server_addr,sizeof(server_addr));
 
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(port);
	inet_pton(AF_INET,server_ip,&server_addr.sin_addr);


	int syncnt = 3;	//1+2+4+8+16+32+64
	setsockopt(socket_fd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(syncnt));

	//设置发送超时
	
	setsockopt(socket_fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
	
	//设置接收超时
	
	setsockopt(socket_fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

	if(m_debug_mode)
	{
		printf("Send data to led [%s %s:%d]\n",m_bmsid.c_str(),m_ip.c_str(),m_port);				
		//PrintHex((unsigned char *)data,len); 		
	}


	auto ret = connect(socket_fd,(struct sockaddr*)&server_addr,sizeof(server_addr));

	if(ret != 0) 
	{
		//printf("Connect to led [%s %s:%d] failed\n",m_bmsid.c_str(),m_ip.c_str(),m_port);			
		return -1;
	}

	return socket_fd;

}


int IQMCY::CreateAsyncSocket(const char *led_ip,int port, int time_out)
{
    int flag, old_flag;


	 int socket_fd = socket(AF_INET,SOCK_STREAM,0);
	 
	 
	 if (socket_fd == INVALID_SOCKET) 
	 {
		 printf("Create socket error\n");
		 zlog_fatal(g_zlog,"Create socket error\n");
		 return -1;
	 }
 
	 struct timeval timeout = {time_out,0};
	 
	 const char *server_ip = led_ip;
	 struct sockaddr_in server_addr;
  
	 bzero(&server_addr,sizeof(server_addr));
  
	 server_addr.sin_family = AF_INET;
	 server_addr.sin_port = htons(port);
	 inet_pton(AF_INET,server_ip,&server_addr.sin_addr);
	 
 
	 //设置发送超时
	 
	 setsockopt(socket_fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
	 
	 //设置接收超时
	 
	 setsockopt(socket_fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));
 
	 if(m_debug_mode)
	 {
		 printf("Send data to led [%s %s:%d]\n",m_bmsid.c_str(),m_ip.c_str(),m_port); 			 
		 //PrintHex((unsigned char *)data,len);		 
	 }




	 
    old_flag = flag = fcntl(socket_fd, F_GETFL, 0);
    flag |= O_NONBLOCK;
    fcntl(socket_fd, F_SETFL, flag);

	 int v = 1;
	 ioctl(socket_fd, FIONBIO, (unsigned long*)&v);


    int ret = -1;
    ret = ::connect(socket_fd, (struct sockaddr*)&server_addr,sizeof(server_addr));
    if (ret != 0) {
        if (errno != EINPROGRESS) {
            printf("connect failed,err(%d)\n", errno);
        } else {
            struct timeval tm;
            tm.tv_sec = time_out;
            tm.tv_usec = 0;
            fd_set set,rset;
            FD_ZERO(&set);
            FD_ZERO(&rset);
            FD_SET(socket_fd, &set);
            FD_SET(socket_fd, &rset);

            int res;
            res = ::select(socket_fd+1, &rset, &set, NULL, &tm);
            if (res < 0) 
				{
					printf("select:network error in connect.errno:%d\n", errno);
            } 
				else if(res == 0) 
				{
                printf("select:connect timeout.errno:%d\n", errno);
            } 
				else if (res == 1) 
				{
                if (FD_ISSET(socket_fd, &set)) {
                    printf("Connect select success\n");
                    ret = 0;
                }
            } else 
           	{
                printf("other error when select: %s\n", strerror(errno));
            }
        }
    }


    return ret;
}



int IQMCY::NVR_Fly2LEDEx(int cmd,char *data,int len)
{
	unsigned char buffer[2048]={0};
	int recv_len = 0;


	int socket_fd = socket(AF_INET,SOCK_STREAM,0);


	if (socket_fd == INVALID_SOCKET) 
	{
		printf("Create socket error\n");
		zlog_fatal(g_zlog,"Create socket error\n");		
		return -1;
	}

	struct timeval timeout = {8,0};
	
	const char *server_ip = m_ip.c_str();
 	struct sockaddr_in server_addr;
 
	bzero(&server_addr,sizeof(server_addr));
 
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(m_port);
	inet_pton(AF_INET,server_ip,&server_addr.sin_addr);


	int syncnt = 3;	//1+2+4+8+16+32+64
	setsockopt(socket_fd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(syncnt));

	//设置发送超时
	
	setsockopt(socket_fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
	
	//设置接收超时
	
	setsockopt(socket_fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

	if(m_debug_mode)
	{
		printf("Send data to led [%s %s:%d]\n",m_bmsid.c_str(),m_ip.c_str(),m_port);				
		PrintHex((unsigned char *)data,len); 		
	}


	auto ret = connect(socket_fd,(struct sockaddr*)&server_addr,sizeof(server_addr));
	
	if(ret != 0) 
	{
		//printf("[%s] Connect to led [%s %s:%d] failed\n",__func__,m_bmsid.c_str(),m_ip.c_str(),m_port);		


		if(m_socket_cb)
		{
			buffer[0] = ERROR_NETWORK;
			m_socket_cb(cmd,buffer,1);
		}
		
		close(socket_fd);
		
		return -2;
	}


	ret = write(socket_fd,data,len);

	if(ret <len)
	{
		printf("[%s] write failed ret = [%d]\n",__func__,ret);
		zlog_fatal(g_zlog,"[%s] write failed ret = [%d]\n",__func__,ret);		
	}

	usleep(1000*100);
	
	recv_len = recv(socket_fd,buffer,sizeof(buffer),0);
	if(recv_len >0)
	{

		if(m_socket_cb)
		{
			m_socket_cb(cmd,buffer,recv_len);
		}
	}
	else
	{
		printf("\nCan not get reply from Server\n");		
		close(socket_fd);
		if(m_socket_cb)
		{
			buffer[0] = ERROR_NODATA;
			m_socket_cb(cmd,buffer,1);
		}		
		return -3;
	}

	close(socket_fd);

	return 0;
}



int IQMCY::NVR_Fly2LED(int cmd,char *data,int len)
{
	unsigned char buffer[2048]={0};
	int recv_len = 0,ret = 0;


	ret = write(m_led_socket,data,len);

	if(ret <len)
	{
		printf("[%s] write failed ret = [%d]\n",__func__,ret);
	}


	usleep(1000*10);
	
	recv_len = recv(m_led_socket,buffer,sizeof(buffer),0);
	if(recv_len >0)
	{
		if(m_socket_cb)
		{
			m_socket_cb(cmd,buffer,recv_len);
		}
	}
	else
	{
		printf("\nCan not get reply from Server\n");		
		//close(socket_fd);
		if(m_socket_cb)
		{
			buffer[0] = ERROR_NODATA;
			m_socket_cb(cmd,buffer,1);
		}		
		return -3;
	}

	//close(socket_fd);

	//std::cout<<__func__ <<" exit !!!!"<<std::endl;
	return 0;
}


void IQMCY::NVR_SetKeepLiveTime(int time)
{
	m_keep_live_time = time;
}

void IQMCY::NVR_UpdateActiveTime()
{
	struct timeval time_v;
	gettimeofday(&time_v,0);
	m_last_acess_time.store(time_v.tv_sec*1000+time_v.tv_usec/1000);
}

void IQMCY::NVR_SetCB(MessageWatcher f)
{
	m_cb = f;
}

void IQMCY::NVR_SetRecvCB(LedResponse f)
{
	m_socket_cb = f;
}


void IQMCY::NVR_Response(std::string & content)
{
	std::cout<<content<<std::endl;
	m_cb(content);
}



IQMCY::~IQMCY() 
{
	std::cout<<"~IQMCY ip:"<<m_ip<<" port:"<<m_port<<std::endl;
};

#endif

7.子类头文件

#pragma once
 
#include <string>
using namespace std;
 
#include "ClassReg.h"
 


class LED_3SV6:public IQMCY
{
public:
    LED_3SV6() : m_name("a"), m_age(18) {
		m_key_id = 0;
		m_status = -1;
		m_fault_msg.clear();
		std::cout<<__func__<<std::endl;
	 }
	 ~LED_3SV6();

	virtual int NVR_Open(std::string snid,std::string ip,std::string resolution,int port,std::string bmsid,std::string server_ip,int server_port,bool encrypt,bool isDebugMode) ;
	virtual STATUS_CODE NVR_SetLED(PLAYLIST *playlist);			
	virtual STATUS_CODE NVR_GetLEDState(); 		

	virtual std::string NVR_GetBrand(); 
	virtual std::pair<int ,std::string>NVR_GetStatus();



protected:		
	virtual int NVR_Close() ;

private:

	bool m_is_last_packet;
	int m_led_status;
	CameraItem<int> m_cameras; //camera index,ip 			

	//std::future<int> m_exec_result;			
	std::string m_playlist;
	std::string m_playFilename;

	int m_key_id;
	enum OP_TYPE
	{
		OP_UPDATE =1,
		OP_TRANSFER,
	};
	
	OP_TYPE m_op;
	
	bool SendCommand(unsigned code, std::string &sendData);
	bool SendAsync(unsigned code, std::string &sendData); 	
	int UploadData(char *filedata,char *filename,int filelen);
	int TransferData(char *data,char *filename,int len);
	int BuildPacket(unsigned char devAddr, unsigned char cmd, char* data, int len, char** dest);
	unsigned char * BuildEncryptPacket(unsigned char*in_data, int in_len, int *out_len);		
	int Convert2LedData(unsigned char devAddr, unsigned char cmd, char* data, int len, char** dest);		
	int encode_frame(char* source, int sourceLength, char* dest, int* destLength);
	int decode_frame(char* source, int sourceLength, char* dest, int* destLength);
	int make_file_data_pkt(unsigned char devAddr, char* szFileName, int nFileOffset, char* data, int len, char** pFrame);
	int make_download_pkt(unsigned char devAddr, char* szFileName, int nFileOffset, char** pFrame); 	
	void ReceiveCB(int,unsigned char *data,int len);
	void DisplayResponse(unsigned char *data,int len);
	void GetStatusResponse(unsigned char *data,int len);
	void UploadResponse(unsigned char *data,int len);		
	int GetPlayList();
	int GetBright();


public:
    string m_name;
    int m_age;
};


8.子类cpp文件 


#include"LED_3SV6.h"

using namespace std;


#define FRAME_HEDAD_BYTE 0x02 // 帧头
#define FRAME_TAIL_BYTE 0x03 // 帧尾
#define SWAP_DWORD(w) (((((unsigned int)w) >> 24) & 0xFF) | ((((unsigned int)w) >> 8) & 0x0000FF00) | ((((unsigned int)w) << 8) & 0x00FF0000) | ((((unsigned int)w) << 24) & 0xFF000000))

#define MAX_BUF_SIZE 	4096

#define CMD_DISPLAY		0
#define CMD_GETSTATUS	1
#define CMD_DOWNLOAD		2
#define CMD_UPLOAD		3



static const char *g_keys[10]={
"microvid",
"microvid",
"microvid",
"microvid",
"microvid",
"microvid",
"microvid",
"microvid",
"microvid",
"microvid"
};



static const char *g_fault_info[10]={
	"",
	"控制器故障",
	"显示模组故障",
	"",
	"单像素管故障",
	"检测系统故障",
	"输入交流电220V故障",
	"防雷器故障",
	"光敏部件故障",
	"温度异常故障"
};


static unsigned char reply_data[]={
	0xFB,0xFB,0xFB,0xFB,0xAA,0x00,0x00,0x00,0x02,0x00,
	0x33,0x69,0x7E,0xED,0xDA,0x6A,0x8C,0x4F,0x6D,0xAC,
	0xB9,0x3C,0xDE,0x85,0x97,0xCE,0x40,0x59,0xA9,0x97,
	0xDB,0xD7,0x23,0xBE,0xC3,0x80,0x83,0xE5,0xA5,0x4C,
	0xE4,0xB4,0xFD,0x65,0x2B,0x55,0x64,0xBF,0x8E,0x4A,
	0x01,0x7B,0x4E,0xA3,0xDA,0xCB,0xE2,0x8B,0xB3,0xB9,
	0xB7,0x7E,0x39,0xAB,0x86,0x82,0x0F,0x1F,0x25,0x41,
	0x31,0x5A,0xE8,0x06,0x87,0xB3,0x69,0x24,0xB7,0xB0,
	0xA7,0x6C,0x27,0x2E,0xF5,0x92,0xC5,0x85,0xAC,0x0B,
	0xD4,0xD1,0xE4,0x77,0x90,0x3B,0x00,0x3F,0x37,0x4A,
	0xC1,0x35,0xE1,0xA5,0x9F,0x4B,0xC4,0x3C,0x8E,0x55,
	0x1E,0xFA,0xD3,0xAE,0x19,0x58,0x40,0x86,0x09,0x74,
	0x7A,0xC2,0x31,0xB5,0x24,0x0A,0x27,0xCF,0xFB,0xC6,
	0x37,0xEB,0xB9,0x2B,0x1C,0x09,0xDD,0x10,0x37,0x4A,
	0xC1,0x35,0xE1,0xA5,0x9F,0x4B,0xA9,0x94,0xD1,0x9F,
	0x6B,0xBE,0xE0,0xC4,0x53,0xD0,0xAC,0xBE,0x6A,0x27,
	0x42,0xD1,0xB0,0xEA,0x2D,0xD7,0x1B,0x91,0x4B,0x55,
	0x8B,0xAF,0xB9,0xA2,0xBB,0xB4,0x04,0x78,0xFE,0xFE,0xFE,0xFE
};


static unsigned char reply_test_data[]={

	0xFB,0xFB,0xFB,0xFB,0x12,0x00,0x00,0x00,0x00,0x00,
	0x15,0x5F,0xF7,0x8F,0x8F,0x33,0x24,0x94,0x86,0x53,
	0x49,0xC9,0xBD,0x9D,0x5B,0x41,0xFE,0xFE,0xFE,0xFE
};

static unsigned char* ParseData(unsigned char * data,int len,int* out_len,int key_id)
{
	char valid_data = 0;
	unsigned char *parse_result=NULL;
	int encrypt_size = 0;
	*out_len = 0;	

	printf("ParseData encrypted begin*************************\n");

	printf("(uint32_t*)data = %08X\n",*((uint32_t*)data));

	if(*((uint32_t*)data) == 0xFBFBFBFB)
	{
		printf("Find head flag\n");
		if(*((uint32_t *)(data+len-4)) == 0xFEFEFEFE)
		{
			printf("Find end flag valid data\n");			
			valid_data = 1;
		}
	}


	if(valid_data)
	{
		encrypt_size = len-14;
		
		unsigned char *encrypt_data = (unsigned char *)malloc(len-14);
		memcpy(encrypt_data,data+10,encrypt_size);


		printf("Get encryptdata:\n");
		for(int i = 0;i<encrypt_size;i++)
		{
			printf("%02X",encrypt_data[i]);
		}

		if(des_decode(DES_ECB,(unsigned char*)g_keys[key_id],10,NULL,encrypt_data,&parse_result,&encrypt_size) == RESULT_OK)
		{
			printf("\n size =%d =====================DES ECB DECODE OK==================\n",encrypt_size);
			for(int i = 0;i<encrypt_size;i++)
			{
				printf("%02X",parse_result[i]);
			}			
		}

		free(encrypt_data);
		
	}
	else
	{
		#if 0
		//Only for test

		len = sizeof(reply_test_data);
		encrypt_size = len-14;

		//printf("(uint32_t*)data = %08X",*((uint32_t*)reply_test_data));
		std::cout<<"encrypt_size =: "<<encrypt_size<<std::endl;

		unsigned char *encrypt_data = (unsigned char *)malloc(len-14);
		memcpy(encrypt_data,reply_test_data+10,encrypt_size);

		std::cout<<"222encrypt_size =: "<<encrypt_size<<std::endl;


		if(des_decode(DES_ECB,(unsigned char*)g_keys[key_id],10,NULL,encrypt_data,&parse_result,&encrypt_size) == RESULT_OK)
		{
			printf("\n size =%d =====================DES ECB DECODE OK==================\n",encrypt_size);
			for(int i = 0;i<encrypt_size;i++)
			{
				printf("%02X",parse_result[i]);
			}			
		}
		free(encrypt_data);		
		#endif
	}


	*out_len = encrypt_size;
	return parse_result;	
}


static unsigned char* GetEncryptData(unsigned char *data,int len,const char* key,int *out_len)
{
	unsigned char *out_data = NULL;
	printf("\n---------------input len =%d-------------\n",len);
	
	for(int i = 0;i<len;i++)
	{
		printf("%02X",data[i]);
	}

	printf("\n----------------------------\n");
	if(des_encode(DES_ECB,(unsigned char *)key,strlen(key),NULL,data,&out_data,&len) ==RESULT_OK)
	{

		printf("key:%s outlen:%d\n",key,len);

		for(int i = 0;i<len;i++)
		{
			printf("%02x",out_data[i]);
		}

		printf("\n----------------------------\n");

	}

	*out_len = len;

	return out_data;
} 

LED_3SV6::~LED_3SV6()
{

	NVR_Close();
	std::cout<<__func__<<std::endl;

}



void LED_3SV6::DisplayResponse(unsigned char *data,int len)
{
	int destLength = 0;
	int out_len = 0;
	unsigned char *plain_data = NULL;

	STATUS_CODE error_code = ERROR_SUCCESS;

	char preset_data[200]={0};

	int preset_data_size = 200;
	
	
	if(len  == 1)
	{
		if(data[0] == ERROR_NETWORK)
		{
			//Socket connect 函数失败 网络或者端口不通
			error_code = ERROR_NETWORK;
			zlog_fatal(g_zlog,"Socket connect 函数失败 网络或者端口不通!!!!");									
		}
		else if (data[0] == ERROR_NODATA)
		{
			//recv函数 无数据返回		
			error_code = ERROR_NODATA	;	
			zlog_fatal(g_zlog,"recv函数 无数据返回!!!!");						
		}

		if(m_led_socket> 0)
		{
			close(m_led_socket);
			m_led_socket = 0;
			m_is_last_packet = true;					
		}

	}
	else
	{
		if(m_encrypt)
		{
			//如果启动加密 需要先解密
			plain_data = ParseData(data,len,&out_len,m_key_id);
			if(plain_data == NULL)
			{
				std::cout<<"ParseData get null data"<<std::endl;
			}
		}
		else
		{
			plain_data = data;
			out_len = len;
		}

		if(plain_data == NULL || len == 0) 
		{
			printf("No valid data\n!!!");
			error_code = ERROR_PROTOCOL;						
			close(m_led_socket);
			m_led_socket = 0;
			m_is_last_packet = true;			
			goto END;
		}

		if(out_len>preset_data_size)
		{
			std::cout<<"Receive data is too large!!!!"<<std::endl;
			error_code = ERROR_PROTOCOL;			
			close(m_led_socket);
			m_led_socket = 0;
			m_is_last_packet = true;
			zlog_fatal(g_zlog,"Receive data is too large!!!!");			

			goto END;

		}


		if(plain_data[0]!= FRAME_HEDAD_BYTE || plain_data[out_len-1] != FRAME_TAIL_BYTE)
		{
			//Protocol does not match with document
			//协议和文档不匹配
			
			std::cout<<__func__<<" Receive data is not valid:"<<std::endl;
			error_code = ERROR_PROTOCOL;			
			close(m_led_socket);
			m_led_socket = 0;
			m_is_last_packet = true;			
			zlog_fatal(g_zlog,"Protocol does not match with document");			
			goto END;

		}


		//PrintHex((unsigned char *)plain_data, out_len);	


		memset(preset_data,0,preset_data_size);
		decode_frame((char *)(plain_data+3), out_len-4, preset_data, &destLength);
		if(m_debug_mode)
		{
			printf("After decode \n");
			PrintHex((unsigned char *)preset_data, destLength);	
		}
		

		if(preset_data[0] == 0x30)
		{
			error_code = ERROR_SUCCESS;
		}
		else
		{
			error_code = ERROR_EXEC;
			std::cout<<"Error:"<<preset_data+1<<std::endl;
			zlog_fatal(g_zlog,"Failed Send data error");
			PrintHex((unsigned char *)plain_data, out_len);				
		}
	}

	
	END:

	if(m_encrypt && plain_data)
	{
		free(plain_data);
		plain_data = NULL;
	}


	if(m_is_last_packet)
	{
		FeedBack2Server(m_server_ip, m_server_port,m_bmsid ,m_task_id,error_code);
	}



}


void LED_3SV6::GetStatusResponse(unsigned char *data,int len)
{

	int destLength = 0;
	unsigned char *plain_data = NULL;
	int out_len = 0;

	char preset_data[200]={0};

	int preset_data_size = 200;

	int original_status = m_status;
	//m_status =1;
	
	m_fault_msg.clear();

	if(len  == 1)
	{
		if(data[0] == ERROR_NETWORK)
		{
			//Socket connect 函数失败 网络或者端口不通
			m_fault_msg.append(LED_NETWORK_ERROR);
		}
		else if (data[0] == ERROR_NODATA)
		{
			//recv函数 无数据返回		
			m_fault_msg.append(LED_NO_DATA);			
		}
		else
		{
			m_fault_msg.append(LED_NOT_MATCH);						
		}
		m_status = 1;
	}
	else
	{
		if(m_encrypt)
		{
			//如果启动加密 需要先解密
			plain_data = ParseData(data,len,&out_len,m_key_id);
			if(plain_data == NULL)
			{
				std::cout<<"ParseData get null data"<<std::endl;
			}
		}
		else
		{
			plain_data = data;
			out_len = len;
		}

		if(plain_data == NULL || len == 0) 
		{
			printf("No valid data\n!!!");
			m_fault_msg.append(LED_NOT_MATCH);			
			m_status = 1;
			goto END;
		}


		if(out_len>preset_data_size)
		{
			std::cout<<"Receive data is too large!!!!"<<std::endl;
			m_status = 1;

			m_fault_msg.append(LED_NOT_MATCH);			
			goto END;

		}


		if(plain_data[0]!= FRAME_HEDAD_BYTE || plain_data[out_len-1] != FRAME_TAIL_BYTE)
		{
			//Protocol does not match with document
			//协议和文档不匹配
			m_status = 1;
			std::cout<<__func__<<" Receive data is not valid:"<<std::endl;
			m_fault_msg.append(LED_NOT_MATCH);
			goto END;

		}


		memset(preset_data,0,preset_data_size);
		decode_frame((char *)(plain_data+3), out_len-4, preset_data, &destLength);
		if(m_debug_mode)
		{
			printf("After decode \n");
			PrintHex((unsigned char *)preset_data, destLength);	
		}

		if(destLength == 6)
		{
			unsigned short status = 0;
			status |= (preset_data[0]-0x30)<<12;
			status |= (preset_data[1]-0x30)<<8;			
			status |= (preset_data[2]-0x30)<<4;						
			status |= (preset_data[3]-0x30)<<0;									

			//printf("status is %04X\n",status);
			
			if(status == 0)
			{
				m_status = 0;
				m_fault_msg.append(LED_ONLINE);
			}
			else
			{
				m_status =3;
				
				for(int i = 0;i<10;i++)
				{
					if(((status>>i) & 1 )== 1)
					{
						m_fault_msg.append(g_fault_info[i]);
						m_fault_msg.append("/");						
					}
				}
			}
		}
		else
		{
			std::cout<<"Get status data is not valid :["<<m_ip<<":"<<m_port<<"]"<<std::endl;
			PrintHex((unsigned char *)preset_data, destLength);
			m_fault_msg.append(LED_NOT_MATCH);
		}

	}


	END:

	if(m_encrypt && plain_data)
	{
		free(plain_data);
		plain_data = NULL;
	}

	if(original_status != m_status)
	{
		zlog_fatal(g_zlog,"LED [%s]----[%s]:[%d] state changed from[%d]to[%d]",
			m_bmsid.c_str(),m_ip.c_str(),m_port,original_status,m_status);
	}	

	//std::cout<<m_bmsid<<" Status ["<<m_status <<"] Result:"<<m_fault_msg<<std::endl; 		
	
}

void LED_3SV6::UploadResponse(unsigned char *data,int len)
{
	
}


void LED_3SV6::ReceiveCB(int cmd,unsigned char *data,int len)
{

	switch (cmd)
	{
	case CMD_DISPLAY:
		DisplayResponse(data,len);
		break;
	case CMD_UPLOAD:
		UploadResponse(data,len);
		break;
	case CMD_GETSTATUS:
		GetStatusResponse(data,len);
	}
	
}



int LED_3SV6::NVR_Open(std::string snid,std::string ip,std::string resolution,int port,std::string bmsid,std::string server_ip,int server_port,bool encrypt,bool isDebugMode)
{

	NVR_UpdateActiveTime();
	m_counter = 0;
	m_debug_mode = isDebugMode;

	m_encrypt = encrypt;



	m_ip = ip;
	m_resolution = resolution;
	m_port = port;
	m_bmsid = bmsid;
	m_server_ip = server_ip;
	m_server_port = server_port;
	m_snid = snid;

	m_playlist = "playlist";
	m_playFilename = "play.lst";

	NVR_SetRecvCB(std::bind(&LED_3SV6::ReceiveCB, this, std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));

	printf("%s ip[%s] port[%d] bmsid[%s]\n",__func__,m_ip.c_str(),m_port,m_bmsid.c_str());					

	return 0;
}



// 协议数据转义
// 0x02 转换为 0x1B, 0xE7
// 0x03 转换为 0x1B, 0xE8
// 0x1B 转换为 0x1B, 0x00
int LED_3SV6::encode_frame(char* source, int sourceLength, char* dest, int* destLength)
{
    int i = 0;
    int destIndex = 0;
    if (source == (char*)0 || sourceLength <= 0 || (dest == (char*)0)) {
        return -1;
    }
    for (i = 0; i < sourceLength; i++) {
        if ((unsigned char)source[i] == (unsigned char)FRAME_HEDAD_BYTE) {
            dest[destIndex++] = (char)0x1B;
            dest[destIndex++] = (char)0xE7;
        } else if ((unsigned char)source[i] == (unsigned char)FRAME_TAIL_BYTE) {
            dest[destIndex++] = (char)0x1B;
            dest[destIndex++] = (char)0xE8;
        } else if ((unsigned char)source[i] == (unsigned char)0x1B) {
            dest[destIndex++] = (char)0x1B;
            dest[destIndex++] = (char)0x00;
        } else {
            dest[destIndex++] = source[i];
        }
    }
    *destLength = destIndex;
    return *destLength;
}

int LED_3SV6::decode_frame(char* source, int sourceLength, char* dest, int* destLength)
{
    int i = 0;
    int destIndex = 0;
    for (i = 0; i < sourceLength - 1; i++) {
        if (((unsigned char)source[i] == (unsigned char)0x1B) && ((unsigned char)source[i + 1] == (unsigned char)0xE7)) {
            dest[destIndex++] = (char)FRAME_HEDAD_BYTE;
            i++;
        } else if (((unsigned char)source[i] == (unsigned char)0x1B) && ((unsigned char)source[i + 1] == (unsigned char)0xE8)) {
            dest[destIndex++] = (char)FRAME_TAIL_BYTE;
            i++;
        } else if (((unsigned char)source[i] == (unsigned char)0x1B) && ((unsigned char)source[i + 1] == (unsigned char)0x00)) {
            dest[destIndex++] = (char)0x1B;
            i++;
        } else {
            dest[destIndex++] = source[i];
        }
    }

    if (i == sourceLength - 1) {
        dest[destIndex++] = source[sourceLength - 1];
    }

    *destLength = destIndex;

    return destIndex;
}





int LED_3SV6::Convert2LedData(unsigned char devAddr, unsigned char cmd, char* data, int len, char** dest)
{
	if(!data || len<1)
	{
		return -1;
	}

    // 帧类型范围为 0-99,转换为两个 ASCII 码
    // 地址范围为 1-99,转换为两个 ASCII 码
    // 帧头(1) + 地址(2 ASCII 码) + 帧类型(2 ASCII 码) + 帧数据(不定长) + 帧校验(2 大端) + 帧尾(1)
    char szFrameAddr[3] = { 0 };
    char szFrameType[3] = { 0 };
    int destLength = 0;
    char* pDest = new char[8 + len * 2 + 1];
    if (pDest == 0) {
        return -1;
    }
    *dest = pDest;

    // 帧头(1字节)
    *pDest++ = (char)FRAME_HEDAD_BYTE;

    // 帧地址(2字节)
    sprintf(szFrameAddr, "%02d", (int)devAddr);
    *pDest++ = szFrameAddr[0];
    *pDest++ = szFrameAddr[1];

    // 帧类型(2字节)
    sprintf(szFrameType, "%02d", (int)cmd);
    *pDest++ = szFrameType[0];
    *pDest++ = szFrameType[1];



    // 检验(2字节)
    // 计算范围包括地址、帧类型和未经转义的帧数据
    int crc_data_len = 2 + 2 + len;
    char* crc_data = new char[crc_data_len];
    memcpy(crc_data + 0, szFrameAddr, 2);
    memcpy(crc_data + 2, szFrameType, 2);

    memcpy(crc_data + 4, data, len);

	
    unsigned short wCRCValue = NVR_GetCRC((unsigned char*)crc_data, crc_data_len);


	char *temp = new char [len+3];

	memcpy(temp,data,len);
	temp[len+0] = (wCRCValue / 256);
	temp[len+1] = (wCRCValue % 256);
	

	//temp[len+0] = 0x02;
	//temp[len+1] = 0x1B;


	//需要转义的包括帧数据+CRC校验码

    encode_frame(temp, len+2, pDest, &destLength);

    pDest += destLength;


    // 帧尾(1字节)
    *pDest++ = (char)FRAME_TAIL_BYTE;

	delete []temp;

    delete []crc_data;

    return (short)(pDest - *dest);

}



unsigned char * LED_3SV6::BuildEncryptPacket(unsigned char*in_data, int in_len, int *out_len)
{
	unsigned char * packet_buff = NULL;
	int encrypt_size;
	unsigned char *encrypt_data=GetEncryptData((unsigned char *)in_data,in_len,g_keys[m_key_id],&encrypt_size);	

	if(encrypt_size== 0)
	{
		printf("Encrypt data failed\n");
		*out_len = 0;		
		return NULL;
	}

	if(m_debug_mode)
	{
		printf("encrypt_size =%d \n",encrypt_size);		
	}


	int packet_size = 14+encrypt_size;


	packet_buff = (unsigned char *)malloc(packet_size);

	if(packet_buff == NULL)
	{
		free(encrypt_data);
		printf("Memory alloc failed\n");
		*out_len = 0;
		return NULL;
	}

	//Head flag:0xFBFBFBFB 4bytes
	packet_buff[0]=0xFB;
	packet_buff[1]=0xFB;
	packet_buff[2]=0xFB;
	packet_buff[3]=0xFB;

	//Data len: Op + keyid+Encrypted data


	int data_len = encrypt_size+2;
	packet_buff[4] = data_len &0xFF;	
	packet_buff[5] = data_len>>8 &0xFF;
	packet_buff[6] = data_len>>16 &0xFF;
	packet_buff[7] = data_len>>24 &0xFF;

	//printf("data_len:%d packet:[%02x %02x %02x %02x]\n",data_len,packet_len[0],packet_len[1],packet_len[2],packet_len[3]);


	//Op code:1 for update key ,2 for normal upload data

	packet_buff[8] = m_op;
	packet_buff[9] = m_key_id;

	memcpy(packet_buff+10,encrypt_data,encrypt_size);

	//End flag:4 bytes 0xFEFEFEFE

	memset(packet_buff+packet_size-4,0xFE,4);

	m_op = OP_TRANSFER; 

	if(m_debug_mode)
	{
		printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
		for(int i = 0;i<packet_size;i++)
		{
			printf("%02X",packet_buff[i]);
		}
		printf("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");		
	}

	free(encrypt_data);

	*out_len = packet_size;
	return packet_buff;
}


int LED_3SV6::BuildPacket(unsigned char devAddr, unsigned char cmd, char* data, int len, char** dest)
{
    int rc = -1;

    // Head(1) + addr(2 ASCII) + cmd(2 ASCII ) + data(~) + CRC(2 ) + tail(1)
    
    char szFrameAddr[3] = { 0 };
    char szFrameType[3] = { 0 };
    int destLength = 0;
    char* pDest = new char[8 + len * 2 + 1];
    if (pDest == 0) {
        return -1;
    }
    *dest = pDest;


    *pDest++ = (char)FRAME_HEDAD_BYTE;


    sprintf(szFrameAddr, "%02d", (int)devAddr);
    *pDest++ = szFrameAddr[0];
    *pDest++ = szFrameAddr[1];


    sprintf(szFrameType, "%02d", (int)cmd);
    *pDest++ = szFrameType[0];
    *pDest++ = szFrameType[1];




    if (len > 0) 
	{
        rc = encode_frame(data, len, pDest, &destLength);
        if (rc < 0) {
            return -1;
        }
        pDest += destLength;
    }

    int nCRCDataLength = 2 + 2 + len;
    char* pCRCBuffer = new char[nCRCDataLength];
    memcpy(pCRCBuffer + 0, szFrameAddr, 2);
    memcpy(pCRCBuffer + 2, szFrameType, 2);
    if (len > 0) {
        memcpy(pCRCBuffer + 4, data, len);
    }

	
    unsigned short wCRCValue = NVR_GetCRC((unsigned char*)pCRCBuffer, nCRCDataLength);
    *pDest++ = wCRCValue / 256;
    *pDest++ = wCRCValue % 256;

    delete[] pCRCBuffer;


    *pDest++ = (char)FRAME_TAIL_BYTE;

    return (short)(pDest - *dest);

    return rc;
}



int LED_3SV6::make_download_pkt(unsigned char devAddr, char* szFileName, int nFileOffset, char** pFrame)
{
    // 文件名(不定长 ASCII 码字符串) + 文件指针偏移(4字节网络字节序)
    int rc = -1;
    char* pFrameData = NULL;
    // 包含最后\0
    int nFileNameLength = strlen(szFileName) + 1;

    // 文件内容偏移
    unsigned int dwOffset = SWAP_DWORD(nFileOffset);

    int nTotalLength = nFileNameLength + sizeof(dwOffset);
    pFrameData = new char[nTotalLength];
    if (pFrameData == NULL) {
        return -1;
    }
    memcpy(pFrameData, szFileName, nFileNameLength);
    memcpy(pFrameData + nFileNameLength, &dwOffset, sizeof(dwOffset));

    rc = Convert2LedData(devAddr, 9, pFrameData, nTotalLength, pFrame);
    delete[] pFrameData;

    return rc;
}



int LED_3SV6::make_file_data_pkt(unsigned char devAddr, char* szFileName, int nFileOffset, char* data, int len, char** pFrame)
{
    int rc = -1;
    // 文件名(play.lst) + 0x2B + 文件指针偏移(4字节 大端) + 文件内容(不定长)
    int nFileNameLength = 0;
    char* pBuffer = NULL;
    int nTotalLength = 0;
    char* pFrameData = NULL;
    unsigned int dwFileOffsetNetOrder = (unsigned int)nFileOffset;
    if (!((len == 0) || (len > 0 && len <= 2048))) {
        return -1;
    }

    nFileNameLength = strlen(szFileName);
    if (nFileNameLength <= 0) {
        return -1;
    }
    nTotalLength = nFileNameLength + 1 + 4 + len;
    pBuffer = new char[nTotalLength];
    if (pBuffer == NULL) {
        return -1;
    }
    pFrameData = pBuffer;

    // 复制文件名
    memcpy(pBuffer, szFileName, nFileNameLength);
    pBuffer += nFileNameLength;

    // 文件名结束字符:0x2B
    *pBuffer++ = 0x2B;

    // 文件偏移
    dwFileOffsetNetOrder = SWAP_DWORD(dwFileOffsetNetOrder);
    memcpy(pBuffer, &dwFileOffsetNetOrder, 4);
    pBuffer += 4;

    // 文件内容
    if (len > 0) {
        memcpy(pBuffer, data, len);
    }

    //rc = make3sV6Frame(devAddr, 10, pFrameData, nTotalLength, pFrame);
	rc = Convert2LedData(devAddr, 10, pFrameData, nTotalLength, pFrame);	
    delete[] pFrameData;

    return rc;
}








int LED_3SV6::UploadData(char *filedata,char *filename,int filelen)
{
    const int BLOCK_SIZE = 2048;
    int frame_num = filelen / BLOCK_SIZE + 1;
    int len = 0;
    int i, nPktLength;

    char* pFrame = NULL;

    for (i = 0; i < frame_num; i++) 
	{
        int nFileOffset = i * BLOCK_SIZE;
        if (i == frame_num - 1) {
            len = filelen - BLOCK_SIZE * i;
        } else {
            len = BLOCK_SIZE;
        }


		pFrame = nullptr;

        nPktLength = make_file_data_pkt(0, filename, nFileOffset, filedata + nFileOffset, len, &pFrame);

		PrintHex((unsigned char *)pFrame,nPktLength);

		if(pFrame && nPktLength>0)
		{
			if(m_encrypt)
			{
				int out_len = 0;
				unsigned char *encrypt_data = BuildEncryptPacket((unsigned char * )pFrame, nPktLength, &out_len);

				if(encrypt_data == NULL)
				{
					std::cout<<"BuildEncryptPacket get null data"<<std::endl;
					continue;
				}

				NVR_Fly2LED(CMD_UPLOAD,(char *)encrypt_data,out_len);	
				free(encrypt_data);

			}
			else
			{
				NVR_Fly2LED(CMD_UPLOAD,pFrame,nPktLength);				
			}
		
		}

		delete []pFrame;
    }
	
    return 0;
}


int LED_3SV6::TransferData(char *filedata,char *filename,int filelen)
{
    const int BLOCK_SIZE = 2048;
    int frame_num = filelen / BLOCK_SIZE + 1;
    int len = 0,ret = 0;
    int i, nPktLength;

    char* pFrame = NULL;

   for (i = 0; i < frame_num; i++) 
	{
        int nFileOffset = i * BLOCK_SIZE;
        if (i == frame_num - 1) 
		  {
            len = filelen - BLOCK_SIZE * i;
				//m_is_last_packet = true;
        } else {
            len = BLOCK_SIZE;
        }

		pFrame = nullptr;

      nPktLength = make_file_data_pkt(0, filename, nFileOffset, filedata + nFileOffset, len, &pFrame);

		//PrintHex((unsigned char *)pFrame,nPktLength);

		if(pFrame && nPktLength>0)
		{
			printf("Send [%d] packet of total [%d]\n",i+1,frame_num);

			if(m_encrypt)
			{
				int out_len = 0;
				unsigned char *encrypt_data = BuildEncryptPacket((unsigned char * )pFrame, nPktLength, &out_len);

				if(encrypt_data == NULL)
				{
					std::cout<<"BuildEncryptPacket get null data"<<std::endl;
					continue;
				}

				ret = NVR_Fly2LED(CMD_DISPLAY,(char *)encrypt_data,out_len);	
				if(ret <0)
				{
					if(pFrame)
					{
						delete []pFrame;			
					}
					free(encrypt_data);					
					return -1;
				}
				free(encrypt_data);

			}
			else
			{
				ret = NVR_Fly2LED(CMD_DISPLAY,pFrame,nPktLength);				
				if(ret <0)
				{
					if(pFrame)
					{
						delete []pFrame;			
					}
					return -1;
				}			
			}
		
		}

		if(pFrame)
		{
			delete []pFrame;			
		}
	
    }
    return 0;
}



STATUS_CODE LED_3SV6::NVR_SetLED(PLAYLIST *playlist)
{
	std::cout<<"thread id:"<<std::this_thread::get_id()<<std::endl;

	std::cout<< "OSD is:  "<< playlist->screen_items[0].line_items[0].osd_str<<std::endl;

	std::unique_lock<std::mutex> lock(m_led_mutex);

	std::cout<<"Begin execute task>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<std::endl;
		
	std::string led_output;
	int screen_size = playlist->screen_items.size();

	 zlog_info(g_zlog,"NVR_SetLED screen size[%d] task id = [%s] bmsid [%s]",
	 	screen_size,playlist->playlist_id.c_str(),playlist->bmsid.c_str());
	
	 char temp[200] = { 0 };

	snprintf(temp, sizeof(temp) - 1, "[%s]\r\nitem_no=%d\r\n", m_playlist.c_str(), screen_size);

	led_output = temp;

	m_task_id = playlist->playlist_id;			
	m_is_last_packet = false;

	if(m_led_socket>0)
	{
		close(m_led_socket);
		m_led_socket = 0;
		printf("m_led_socket [%d]> 0 need Close socket \n",m_led_socket); 	
		
	}
	
	m_led_socket = NVR_CreateSocket(m_ip.c_str(), m_port);
	if(m_led_socket == -1)
	{
		printf("Failed Cannot connect to led \n");		
		m_led_socket	 = 0;
		FeedBack2Server(m_server_ip, m_server_port,m_bmsid ,m_task_id,ERROR_NETWORK);

		zlog_fatal(g_zlog,"NVR_SetLED NVR_CreateSocket failed ip[%s] port[%d]  bmsid [%s]",
			m_ip.c_str(),m_port,playlist->bmsid.c_str());

		return ERROR_NETWORK;
	}

	for(int i = 0;i<screen_size;i++)
	{
		auto screen = playlist->screen_items[i];
		memset(temp,0,200);

		auto line_size = screen.line_items.size();
		auto j= screen.line_items.size();		

		for(j = 0;j< line_size; j++)
		{
			LINE_ITEM &line = screen.line_items[j];

			if(line.is_image)
			{
				char *pRawContent= new char[line.osd_str.size()];
				int nRawContentLength = f_base64_decode(pRawContent,const_cast<char*>(line.osd_str.c_str()));
				printf("f_base64_decode nRawContentLength=%d\n",nRawContentLength);
				std::string shortname;
				
				char img_sn[50] = {0};

				if( nRawContentLength > 0 )
				{
					sprintf(img_sn,"%03d",i);
					shortname.append("./png/");
					shortname.append(img_sn);
					shortname.append(".png");					
					//shortname = +img_sn+".bmp";
					//shortname = std::to_string(j)+"003";
					std::string img_name = APP_LOG_IMAGE_DIR + playlist->bmsid+"_"+img_sn+".png";
					printf("Save file name[%s]\n",img_name.c_str());
					zlog_info(g_zlog,"[%d] screen type:Image file name[%s] led target name[%s] size[%d]\n",i+1,
						img_name.c_str(),shortname.c_str(),nRawContentLength);
					FILE * fp = fopen(img_name.c_str(),"wb+");
					if(fp)
					{
						fwrite(pRawContent,nRawContentLength,1,fp);
						fclose(fp);
					}
				
					//line_item.image_size = nRawContentLength;
					printf("Image transfer filename[%s] size[%d]\n",shortname.c_str(),nRawContentLength);					
					auto ret = TransferData((char *)pRawContent, (char *)shortname.c_str(), nRawContentLength);
					if(ret == -1)
					{
						delete[]pRawContent;						
						return ERROR_EXEC;
					}
				}
				delete[]pRawContent;
				

				if(j == 0)
				{
					snprintf(temp, sizeof(temp) - 1, "item%d=%d,%d,0,", i, line.display_time * 100, 1);
					led_output+= temp;
				}
				
				//生成播放表
				char szLine[100] = { 0 };
				sprintf(szLine, "\\C%03d%03d\\P%s", line.pos_x, line.pos_y, img_sn);
				led_output+= szLine;
				
			}
			else
			{
				const char* font = line.fontname.c_str();
				int fontSize = line.fontsize;
				char szFont[64] = { 0 };

				if(j == 0)
				{
					snprintf(temp, sizeof(temp) - 1, "item%d=%d,%d,0,", i, line.display_time * 100, 1);
					led_output+= temp;
					
				}
				
				if (strcmp(font, "黑体") == 0) {
				 snprintf(szFont, sizeof(szFont) - 1, "\\fh%02d%02d", fontSize, fontSize);
				} else if (strcmp(font, "楷体") == 0) {
				 snprintf(szFont, sizeof(szFont) - 1, "\\fk%02d%02d", fontSize, fontSize);
				} else if (strcmp(font, "隶书") == 0) {
				 snprintf(szFont, sizeof(szFont) - 1, "\\fl%02d%02d", fontSize, fontSize);
				} else {
				 snprintf(szFont, sizeof(szFont) - 1, "\\fs%02d%02d", fontSize, fontSize);
				}

				char szLine[600] = { 0 };
				char gbk[500] = {0};
				
				UTF8TOGBK((char *)line.osd_str.c_str(),line.osd_str.size(),gbk,500);

				zlog_info(g_zlog,"[%d] screen [%d] line type:text Set OSD [%s] size[%d] fontname[%s]\n",
											i+1,j+1,line.osd_str.c_str(),fontSize,font);

				sprintf(szLine, "\\C%03d%03d%s\\c%s000\\b%s000%s",
					line.pos_x, line.pos_y, szFont, line.fgcolor.c_str(), line.bgcolor.c_str(), gbk);
				 //line.pos_x, line.pos_y, szFont, line.fgcolor.c_str(), line.bgcolor.c_str(), line.osd_str.c_str());
				
				led_output+= szLine;
			}
			
		}
		led_output+="\r\n";

		usleep(1000*20);
		
	}

	if(screen_size == 0 )			//Delete All
	{
		led_output = R"([playlist]
			item_no = 1
			item0 = 500,0,0
		)";
	}

	m_is_last_packet = true;
	
	auto ret = TransferData((char *)led_output.c_str(), (char*)m_playFilename.c_str(), led_output.size());

	zlog_info(g_zlog,"NVR_SetLED ret [%d] [%s] port[%d] content[%s] ",ret,m_ip.c_str(),m_port,led_output.c_str());

	std::cout<<" TransferData content is:"<<led_output<<std::endl;
	if(ret == 0)		
	{
		return ERROR_SUCCESS;
	}
	else
	{
		return ERROR_EXEC;
	}
	
	
}



bool LED_3SV6::SendAsync(unsigned code, std::string &sendData)
{
	char *pFrame = NULL;
	char *data = NULL;
	bool ret  = false;

	if (!sendData.empty()) 
	{
	  data = const_cast<char*>(sendData.c_str());
	}
	int rc = BuildPacket(0, code, data, sendData.size(), &pFrame);
	if (rc < 0) 
	{
	  return false;
	}

	if(m_encrypt)
	{
		int out_len = 0;
		unsigned char *encrypt_data = BuildEncryptPacket((unsigned char * )pFrame, rc, &out_len);

		if(encrypt_data == NULL)
		{
			std::cout<<"BuildEncryptPacket get null data"<<std::endl;
		}
		else
		{
			ret = NVR_Fly2LEDEx(CMD_GETSTATUS,(char *)encrypt_data,out_len);			
			free(encrypt_data);
		}
	}
	else
	{
	    ret = CreateAsyncSocket(m_ip.c_str(),m_port,3);		
		
	}
	std::cout<<"NVR_Fly2LEDEx ret :"<<ret<<std::endl;	
	return ret;
}


bool LED_3SV6::SendCommand(unsigned code, std::string &sendData)
{
	char *pFrame = NULL;
	char *data = NULL;
	bool ret  = false;

	if (!sendData.empty()) 
	{
	  data = const_cast<char*>(sendData.c_str());
	}
	int rc = BuildPacket(0, code, data, sendData.size(), &pFrame);
	if (rc < 0) 
	{
	  return false;
	}

	if(m_encrypt)
	{
		int out_len = 0;
		unsigned char *encrypt_data = BuildEncryptPacket((unsigned char * )pFrame, rc, &out_len);

		if(encrypt_data == NULL)
		{
			std::cout<<"BuildEncryptPacket get null data"<<std::endl;
		}
		else
		{
			ret = NVR_Fly2LEDEx(CMD_GETSTATUS,(char *)encrypt_data,out_len);			
			free(encrypt_data);
		}
	}
	else
	{
	    ret = NVR_Fly2LEDEx(CMD_GETSTATUS,pFrame,rc);		
		
	}
	std::cout<<"NVR_Fly2LEDEx ret :"<<ret<<std::endl;	
	return ret;
}


STATUS_CODE LED_3SV6::NVR_GetLEDState()
{
	if(GetBright() == 0)
	{
		return ERROR_SUCCESS;
	}
	return ERROR_NETWORK;
}

int LED_3SV6::GetBright()
{
	std::string sendData;

	m_op = OP_TRANSFER; 

#if 0
	//01:Get fault info from led, 06:Get brightness info
	if(!SendCommand(1, sendData)) {
	    return -1;
	}
#else
	if(!SendAsync(1, sendData)) {
	    return -1;
	}


#endif

	std::cout<<"OSD_SANSI::GetBright"<<std::endl;


	return 0;
}


int LED_3SV6::GetPlayList()
{
	std::string sendData;

	m_op = OP_TRANSFER; 

	char* pFrame = NULL;
	int ret = make_download_pkt(0, (char *)m_playFilename.c_str(), 0, &pFrame);
	if (ret < 0) 
	{
		printf("make_download_pkt error,m_chAddr=%d remote_filename=%s nFileOffset=%d", 0, m_playFilename.c_str(), 0);
		return -1;
	}

	NVR_Fly2LED(CMD_DOWNLOAD,pFrame,ret); 		

	delete []pFrame;
	
	return 0;
}



std::pair<int ,std::string> LED_3SV6::NVR_GetStatus()
{
	return std::make_pair(m_status,m_fault_msg);
}

std::string LED_3SV6::NVR_GetBrand()
{
	return "3SV6";	
}



int LED_3SV6::NVR_Close(void)
{
	if(m_led_socket)
	{
		close(m_led_socket);
	}

	return 0;
}



REGISTER_CLASS(LED_3SV6);

9.测试代码:

#pragma once
 
#include <string>
using namespace std;
 
#include "ClassReg.h"
 


class LED_XK:public IQMCY
{
public:
    LED_XK() : m_name("a"), m_age(18) {}
 
    void f1()
    {
        std::cout << "f1" << std::endl;
    }
 
    int f2(int a)
    {
        std::cout << "f2" << std::endl;
        return a;
    }
 	 virtual std::string NVR_GetBrand() {return "LED_XK";}
public:
    string m_name;
    int m_age;
};

REGISTER_CLASS(LED_XK);
#if 0

REGISTER_CLASS_FIELD(LED_XK, m_name, string);
REGISTER_CLASS_FIELD(LED_XK, m_age, int);
REGISTER_CLASS_METHOD(LED_XK, f1, void);
REGISTER_CLASS_METHOD(LED_XK, f2, int, int);

#endif

10.使用的实例:

std::shared_ptr<IQMCY> QMCY_APP:: GetLedPointer(const string& brand)
{
	auto protocol = m_basic_info.protocal_table[brand];

	ClassFactory * factory = Singleton<ClassFactory>::instance();

	std::shared_ptr<IQMCY> result (factory->create_class(protocol));

	if(result)
	{
		std::cout<<"result::"<<result.get()<<std::endl;
		return result;
	}
	
#if 0

	string name;
	a->get("m_name", name);
	a->set("m_name", "kitty");

	int age;
	a->get("m_age", age);
	a->set("m_age", 30);

	a->call("f1");
	int num = a->call<int>("f2", 123);
#endif

	return nullptr;	
 }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QMCY_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值