内容来自别人的内容 记录下
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;
}