车端连接和登入车联网后台
#include <pthread.h>
#include <arpa/inet.h>
#include <semaphore.h>
#ifndef CODETEST_SOCKETCLIENT_H
#define CODETEST_SOCKETCLIENT_H
typedef unsigned char UCHAR;
typedef unsigned short int UINT16;
typedef struct{
bool bcm_reg_status; //regist status between MCU and BCM
char ecu_configure[10];
char tcu_function_configure[20];
bool isUpdateing; //TBOX update status
char* tcu_id; //TCU ID
char* vin; //VIN Code
char* mcu_sw_ver; //MCU Software version
char* mcu_hw_ver; //MCU Hardware version
char* develop_id; //DEVELOP ID
int tcuid_len; //TCU ID length
int vin_len; //VIN Code Length
int mcuswver_len; //MCU Software version length
int mcuhwver_len; //MCU Hardware version length
int develop_id_len; //DEVELOP ID length
}McuInfo;
typedef enum{
DF_MSG_SERVER_VEHICLE_LOGIN = 0x01,
DF_MSG_SERVER_REALTIME_DATA = 0x02,
DF_MSG_SERVER_REPLACEMENT_DATA = 0x03,
DF_MSG_SERVER_VEHICLE_LOGOUT = 0x04,
DF_MSG_SERVER_TERMINALTIME = 0x05,
DF_MSG_SERVER_VEHICLE_ALARM = 0x06,
DF_MSG_SERVER_RECORDINFO = 0x07,
DF_MSG_SERVER_HEARTBEAT = 0x09, //20201120 增加企业平台心跳
}DF_SERVER_4G_COMM_E;
typedef enum
{
F_ENCRYPT_TYPE_NONE = 0x00,
F_ENCRYPT_TYPE_RSA = 0x01,
F_ENCRYPT_TYPE_RC4 = 0x02,
E_ENCRYPT_TYPE_NONE = 0x01,
E_ENCRYPT_TYPE_AES128 = 0x03,
E_ENCRYPT_TYPE_RSA = 0x80,
E_ENCRYPT_TYPE_RC4 = 0x81,
E_ENCRYPT_TYPE_EN = 0x82,
E_ENCRYPT_TYPE_COMMON_EN= 0x83,
E_ENCRYPT_TYPE_ERROR = 0xFE,
E_ENCRYPT_TYPE_USELESS = 0xFF
}ENCRYPT_TYPE;
typedef struct SNData{
//char isvalid;
int year; //年
int month; //月
int day; //日
long login_out_number; //登入登出流水号
long vehi_number; //车辆信息流水号
long obd_number; //OBD信息流水号
long remove_number; //拆除信息流水号
//bool isAvailable;
}S_SNData,*PS_SNData;
extern PS_SNData Serial_Number_All; //20201019 增加保存流水号
typedef struct
{
bool isNetCradConnected;//NetCrad status
bool isNetCradConnected_pub;
char *IMEI;
char *IMSI;
char *ICCID;
int imei_len; //IMEI length
int imsi_len; //IMSI length
int iccid_len; //ICCID length
int simCardStatus; //sim status
}ModuleInfo;
class SocketClient {
public:
explicit SocketClient();
bool SendHeartBeatToDfServer(); //20201120 企业平台心跳数据
void printRawData( const char *head,UCHAR const * data, int len);
int VerifyVin(char *VIN, int len);
UCHAR* make_GBframeNew(UCHAR work_id, UCHAR ver_data, UCHAR encrypt_type, UCHAR const * vin, UCHAR const * data, UINT16 data_length);
UCHAR BCC(unsigned char *upCreatBcc_Data, unsigned int uCreatBcc_Data_len);
bool dispatchDataBy4GNet_Df(unsigned short businessID,unsigned char const * data, unsigned short length);
int GetSocketFd_df() const;
bool sendToTspSocket_df(unsigned char const *data,unsigned short length);
void disconnectWithServer_df();
bool connect_server_start_df();
static void* connect_server_run_df(void *arg);
void connect_server_df();
bool CreateSocket_df(int sin_family, int flag, int protocol);
bool SetSocketOption_df(int Level,int OptName,int Second);
bool ConnectServer_df(int sin_family,const char * Ip_Addr , int Port);
static void* receved_run0_df(void* arg);
bool receved_thread_start_df();
void receved_run_df();
bool SendGbLoginReq();
unsigned int getTimeStamp(void);
virtual ~SocketClient();
public:
McuInfo mcuInfo;
int dfSocketFD;
bool isConnected_df;
pthread_mutex_t ConnectMutex_df;
pthread_mutex_t SendCloudMutex_df;
bool isConnecting_df;
pthread_t connect_thread_id_df;
int serverPort_df;
char serverAdrr_df[128];
struct sockaddr_in ServerAddress_df;
sem_t WaitForConnectSEM;
pthread_t thread_receved_id_df;
pthread_mutex_t LoginMutex_df;
bool CustomLoginStatus_df;
ModuleInfo moduleInfo;
};
#endif //CODETEST_SOCKETCLIENT_H
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <csignal>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <cerrno>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include "SocketClient.h"
#define GB_HEAD "\x23\x23"
#define HEAD_GB "\x23\x23"
#define GB_HEAD_LEN 2
#define GB_COMMAND_LEN 1
#define GB_COMMANDRSP_LEN 1
#define GB_VIN_LEN 17
#define GB_VINENCRY_LEN 1
#define GB_USRDATA_LEN 2
#define GB_USRDATA_MAXLEN 1000
#define GB_CRC_LEN 1
//buffer size
#define RECEIVE_BUFFER_SIZE 4096
UCHAR m50_default_vin[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //DFYY_TEST
static int g_iConnectSocketRetryNum_df =0;
PS_SNData Serial_Number_All;
SocketClient::SocketClient() {
mcuInfo.vin = "VINDA24C290A05009";
const char * data = "157.122.73.15";
memcpy(serverAdrr_df,data, strlen(data)+1);
serverPort_df = 6530;
pthread_mutex_init(&ConnectMutex_df,NULL);
sem_init(&WaitForConnectSEM, 0, 0);
isConnecting_df = false;
isConnected_df = false;
pthread_mutex_init(&LoginMutex_df,NULL);
moduleInfo.ICCID = "89860922780035723744";
moduleInfo.iccid_len = 20;
}
SocketClient::~SocketClient() {
}
UCHAR* SocketClient::make_GBframeNew(UCHAR work_id, UCHAR ver_data, UCHAR encrypt_type, UCHAR const * vin, UCHAR const * data, UINT16 data_length)
{
UCHAR* packet = NULL;
UINT16 rsa_encr_len = 0;
unsigned char bcc = 0;
UINT16 length = 0;
int index = 0;
int iret = 0;
UCHAR encrypt_buf[128];
//When use RC4 encrypt or no encrypt, the sending buffer size is data length + protocol length(25)
length = data_length + 25;
if(data == NULL)
{
//LOGD(TAG, "make_frame data is null,so retrun \n");
//return NULL;
}
packet = (UCHAR*)malloc(length);
if(packet)
{
memset(packet, 0, length);
memcpy(packet,GB_HEAD, GB_HEAD_LEN);
index += GB_HEAD_LEN;
memcpy(packet + index, &work_id, GB_COMMAND_LEN);
index += GB_COMMAND_LEN;
memcpy(packet + index, vin , GB_VIN_LEN);
index += GB_VIN_LEN;
memcpy(packet + index, &ver_data, 1);
index += 1;
memcpy(packet + index, &encrypt_type, GB_VINENCRY_LEN);
index += GB_VINENCRY_LEN;
packet[index++] = 0xff&(data_length>>8);
packet[index++] = 0xff&(data_length);
memcpy(packet+index, data, data_length);
index += data_length;
bcc = BCC(packet, index);
memcpy(packet + index, &bcc, GB_CRC_LEN);
}
return packet;
}
UCHAR SocketClient:: BCC(unsigned char *upCreatBcc_Data, unsigned int uCreatBcc_Data_len)
{
int bcc=0;
unsigned int i;
for (i = 2; i<uCreatBcc_Data_len; i++)
bcc ^= upCreatBcc_Data[i];
return bcc;
}
bool SocketClient::SendHeartBeatToDfServer() {
int ulen = 0;
UCHAR Vin_Data[17] = {0};
if(!mcuInfo.vin)
{
memcpy(Vin_Data,m50_default_vin,GB_VIN_LEN);
return false; //20201110 如果没有获取到VIN码 不发数据给平台
}
else
{
/*VIN码校验*/
if(VerifyVin(mcuInfo.vin,GB_VIN_LEN) == 0)
{
memcpy(Vin_Data,mcuInfo.vin,GB_VIN_LEN);
}else{
printf("VIN verify failed!\n");
return false;
}
}
UCHAR * packet = NULL;
packet = make_GBframeNew(DF_MSG_SERVER_HEARTBEAT,0x00,E_ENCRYPT_TYPE_NONE,Vin_Data,NULL,0);
if(packet)
{
dispatchDataBy4GNet_Df(DF_MSG_SERVER_VEHICLE_LOGOUT,packet, ulen + 25 );
printf("send heartbeat data is ok\n");
printRawData("df server heartbeat data:",packet, (ulen + 25));
free(packet);
packet = NULL;
}
return true;
}
void SocketClient::printRawData( const char *head,UCHAR const * data, int len)
{
int i;
char *p;
char *buffer;
int bufferSize = 3 * (len + 1);
buffer = (char*)malloc(bufferSize);
if(!buffer)
{
return;
}
p = buffer;
memset(p, 0, bufferSize);
for(i=0; i<len; i++)
{
sprintf(p, "%02X ", data[i]);
p += 3;
}
printf( "RAW:%s%s\n", head,buffer);
free(buffer);
}
int SocketClient ::VerifyVin(char *VIN, int len)
{
int ret = 0;
for (int i = 0; i < len; i++)
{
if ((VIN[i] >= '0' && VIN[i] <= '9')
|| (VIN[i] >= 'a' && VIN[i] <= 'z')
|| (VIN[i] >= 'A' && VIN[i] <= 'Z'))
{
i++;
}
else
{
ret = -1;
break;
}
}
return ret;
}
int SocketClient:: GetSocketFd_df() const
{
return dfSocketFD;
}
bool SocketClient:: dispatchDataBy4GNet_Df(unsigned short businessID,unsigned char const * data, unsigned short length)
{
if(data == NULL)
{
printf("dispatchDataBy4GNet_Df data is NULL\n");
return false;
}
int SocketFd = GetSocketFd_df();
int usr_dataLen = length - 25;
int send_data_len = 0;
bool dispatchSuccess = false;
unsigned char bcc;
unsigned char data_usr[1024];
unsigned short data_usr_len = 0;
UCHAR command_type = data[2];
UCHAR encrypt_type = data[21];
int i=0;
if((SocketFd > 0) && (isConnected_df == true))
{
dispatchSuccess = sendToTspSocket_df(data,length);
}
else
{
printf("connected %d, socket fd %d\n",isConnected_df,dfSocketFD);
printf("dispatch %d bytes Via 4G network error: connection with server is unavoidable.\n", length);
}
return dispatchSuccess;
}
bool SocketClient::sendToTspSocket_df(unsigned char const *data,unsigned short length)
{
int len = 0;
// UCHAR sendBuf[MSG_PER_FREAM_VEHI] = {0};
signal(SIGPIPE, SIG_IGN);
pthread_mutex_lock(&SendCloudMutex_df);
//20201218测试tcp无网络状态下丢包
int tcp_send_buffer = 0;
ioctl(dfSocketFD, SIOCOUTQ, &tcp_send_buffer);
printf("df_tcp_send_buffer is %d \n",tcp_send_buffer);
//20201218测试tcp无网络状态下丢包
len = send(dfSocketFD, data, length, MSG_NOSIGNAL);
pthread_mutex_unlock(&SendCloudMutex_df);
if(len <= 0)
{
if(errno == EAGAIN)//send超时会触发EAGAIN,超时暂时不做sleep延时处理
{
printf("[sendToServiceSocket_df]TIMEOUT !!! send %d bytes to cloud server error %s! \n", length, strerror(errno));
}
else
{
g_iConnectSocketRetryNum_df++;
printf( "[sendToServiceSocket_df]send %d bytes to cloud server error %s!,sleep [%d] \n", length, strerror(errno),1+g_iConnectSocketRetryNum_df);
//sleep(1+g_iConnectSocketRetryNum_df); //20201229测试网络漏包
}
disconnectWithServer_df();
connect_server_start_df();
return false;
}else
{
g_iConnectSocketRetryNum_df = 0;
printf("[sendToServiceSocket_df]Success dispatch(cmd:0x%x 0x%x) %d bytes Via 4G network\n",data[2],data[3], length);
return true;
}
}
void SocketClient:: disconnectWithServer_df()
{
printf("disconnect With df Server start \n");
pthread_mutex_lock(&ConnectMutex_df);
if(dfSocketFD >= 0)
{
close(dfSocketFD);
}
dfSocketFD = -1;
isConnecting_df = false;
isConnected_df = false;
pthread_mutex_unlock(&ConnectMutex_df);
printf("disconnect With df Server success \n");
}
bool SocketClient ::connect_server_start_df()
{
int ret;
printf("start connect df server\n");
pthread_mutex_lock(&ConnectMutex_df);
if(isConnecting_df || isConnected_df)
{
printf("another connecting thread is running.\n");
pthread_mutex_unlock(&ConnectMutex_df);
return false;
}
ret = pthread_create(&connect_thread_id_df, NULL, connect_server_run_df, this);
if(ret >= 0)
{
isConnecting_df = true;
pthread_detach(connect_thread_id_df);
printf("Connecting_WithDFServer=1\n");
}
else
printf("Connecting_WithDFServer=0\n");
pthread_mutex_unlock(&ConnectMutex_df);
return true;
}
void* SocketClient:: connect_server_run_df(void *arg)
{
SocketClient* myself = (SocketClient*)arg;
myself->connect_server_df();
return NULL;
}
bool SocketClient::CreateSocket_df(int sin_family, int flag, int protocol)
{
dfSocketFD = socket(sin_family,flag,protocol);
if(dfSocketFD < 0)
{
printf("create connect df socket error: %s \n",strerror(errno));
return false;
}
printf("create connect df socket [%d] success! \n",dfSocketFD);
return true;
}
bool SocketClient :: SetSocketOption_df(int Level,int OptName,int Second)
{
struct timeval tv ;
tv.tv_sec = Second;
tv.tv_usec = 0;
if(setsockopt(dfSocketFD,Level,OptName,(char *)&tv,(socklen_t)sizeof(struct timeval)) == -1)
{
printf("set dfsockopt error \n");
return false;
}
else
{
printf("set dfsockopt success \n");
return true;
}
}
bool SocketClient :: ConnectServer_df(int sin_family,const char * Ip_Addr , int Port)
{
printf("begin to connect %d df server \n",dfSocketFD);
memset(&ServerAddress_df,0,sizeof(sockaddr_in));
ServerAddress_df.sin_family = sin_family;
ServerAddress_df.sin_addr.s_addr = inet_addr(Ip_Addr);
ServerAddress_df.sin_port = htons(Port);
if(connect(dfSocketFD,(struct sockaddr *)&ServerAddress_df,sizeof(sockaddr_in)) < 0)
{
printf("connect with df server error [%s:%d] error:%s \n",Ip_Addr,Port,strerror(errno));
return false;
}
else
{
printf("connect with df server [%s:%d] success \n",Ip_Addr,Port);
return true;
}
}
void SocketClient :: connect_server_df()
{
printf("connect Df server thread is runing \n");
char command[128] = {0};
//使用普通socket
struct sockaddr_in addr;
socklen_t addr_len = sizeof(struct sockaddr_in);
CreateSocket_df(AF_INET,SOCK_STREAM, 0);
if(dfSocketFD == -1)
{
return;
}
SetSocketOption_df(SOL_SOCKET, SO_SNDTIMEO, 30);
while(isConnecting_df)
{
if((ConnectServer_df(AF_INET, serverAdrr_df, serverPort_df)) == false)
{
sleep(1);
if(dfSocketFD < 0)
{
disconnectWithServer_df();
connect_server_start_df();
break;
}
}
else
{
if(0 != getsockname(GetSocketFd_df(),(struct sockaddr*)&addr,&addr_len))
{
printf("get Df socket name error \n");
}
if ((GetSocketFd_df() == -1) \
|| (strcmp(inet_ntoa(addr.sin_addr),"0.0.0.0") == 0) \
|| (ntohs(addr.sin_port) == 0))
{
printf("connect_with_df_server=0_%s:%d", serverAdrr_df, serverPort_df);
printf("this socket addr is invalid : %s %d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}
else
{
printf("connect_with_df_server=1_%s:%d", serverAdrr_df, serverPort_df);
printf("this socket addr %s %d successful", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
SetSocketOption_df(SOL_SOCKET, SO_SNDTIMEO, 5);
pthread_mutex_lock(&ConnectMutex_df);
isConnected_df = true; //连接企业平台状态
isConnecting_df = false;
// pthread_cond_broadcast(&connectCond_df);
pthread_mutex_unlock(&ConnectMutex_df);
//20201109
sleep(1);
sem_post(&WaitForConnectSEM);
break;
}
}
}
}
void* SocketClient :: receved_run0_df(void* arg)
{
SocketClient* myself = (SocketClient*)arg;
myself->receved_run_df();
return NULL;
}
bool SocketClient:: receved_thread_start_df()
{
if(pthread_create(&thread_receved_id_df, NULL, receved_run0_df, this) != 0)
{
printf("create df receive thread error \n");
return false;
}
pthread_detach(thread_receved_id_df);
return true;
}
void SocketClient :: receved_run_df()
{
//DFYY_TEST 使用非PKI方式
int h,i;
int len = 0;
int put_len;
int retry = 0;
fd_set socketSet;
UCHAR net_buffer[RECEIVE_BUFFER_SIZE];
struct timeval timeout = {5, 0};
printf("[receved_run_df ] current fd = %d \n",this->dfSocketFD);
while(1)
{
if(dfSocketFD == -1)
{
usleep(50);
continue;
}
FD_ZERO(&socketSet);
FD_SET(dfSocketFD, &socketSet);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
h= select(dfSocketFD + 1, &socketSet, NULL, NULL, &timeout);
if(0 == h)
{
sleep(1);
continue;
}
else if(h < 0)
{
sleep(retry % 15 + 1);
continue;
}
memset(net_buffer,0,RECEIVE_BUFFER_SIZE);
len = recv(dfSocketFD,net_buffer,sizeof(net_buffer),0);
if(len > 0)
{
printf("receive %d bytes from df server: \n", len);
printRawData(" ",net_buffer, len);
// int put_len = CbWrite(net_recv_rbuf_df, net_buffer, len);
//
// if(len != put_len)
// {
// printf("write data to RingBuffer_df error: %d != %d\n", len, put_len);
// }
// printf("CbWritet df success..\n");
}
if(((h == 1) && (len == 0)) || ((h == 1) && (len == -1)))
{
printf("=========receved_run_gov() sem_wait is begin=========\n");
sem_wait(&WaitForConnectSEM);
printf("=========receved_run_gov() sem_wait is end=========\n");
}
usleep(50);
}
}
unsigned int SocketClient:: getTimeStamp(void)
{
struct timespec time;
memset(&time, 0, sizeof(struct timespec));
clock_gettime(CLOCK_REALTIME, &time);
return time.tv_sec;
}
bool SocketClient ::SendGbLoginReq()
{
int len = 0;
int ulen = 0;
UCHAR Custom_Login_Data[512] = {0};
printf("#DFYY_TEST# begin to send GB custom login \n");
pthread_mutex_lock(&LoginMutex_df);
CustomLoginStatus_df = false;
pthread_mutex_unlock(&LoginMutex_df);
static UCHAR tcu_move_time_pre = 0;
static UCHAR tcu_move_time_cur = 0;
// unsigned int time_stamp = getTimeStamp() - 8*60*60; //获得系统时间
unsigned int time_stamp = getTimeStamp();
struct tm *p;
p = localtime((time_t *)&(time_stamp));
tcu_move_time_cur = p->tm_mday;
printf("#DFYY_TEST#GB CustomLogin time[%d-%d-%d %d:%d:%d] \n",1900 + p->tm_year,1 + p->tm_mon,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);
Custom_Login_Data[ulen++] = p->tm_year-100;
Custom_Login_Data[ulen++] = p->tm_mon+1;
Custom_Login_Data[ulen++] = p->tm_mday;
Custom_Login_Data[ulen++] = p->tm_hour;
Custom_Login_Data[ulen++] = p->tm_min;
Custom_Login_Data[ulen++] = p->tm_sec;
//登入流水号
// if(tcu_move_time_cur!=Serial_Number_All->day)
// {
// Serial_Number_All->day = tcu_move_time_cur;
// Serial_Number_All->login_out_number = 0; //20201019 增加保存流水号
// Serial_Number_All->login_out_number++; //20201019 增加保存流水号
// }else{
// Serial_Number_All->login_out_number++; //20201019 增加保存流水号
// }
// Custom_Login_Data[ulen++] = 0xff&(Serial_Number_All->login_out_number >> 8); //20201019 增加保存流水号
// Custom_Login_Data[ulen++] = 0xff&Serial_Number_All->login_out_number; //20201019 增加保存流水号
long login_out_number = 1;
Custom_Login_Data[ulen++] = 0xff&(login_out_number >> 8); //20201019 增加保存流水号
Custom_Login_Data[ulen++] = 0xff&login_out_number; //20201019 增加保存流水号
//IICID
if(!moduleInfo.ICCID)
{
return false;
}
memcpy(&Custom_Login_Data[ulen] , moduleInfo.ICCID, moduleInfo.iccid_len);
ulen += moduleInfo.iccid_len;
UCHAR Vin_Data[17] = {0};
if(!mcuInfo.vin)
{
memcpy(Vin_Data,m50_default_vin,GB_VIN_LEN);
return false; //20201110 如果没有获取到VIN码 不发数据给平台
}
else
{
/*VIN码校验*/
if(VerifyVin(mcuInfo.vin,GB_VIN_LEN) == 0)
{
memcpy(Vin_Data,mcuInfo.vin,GB_VIN_LEN);
}else{
printf("VIN verify failed!\n");
return false;
}
}
printf("#DFYY_TEST# M50VIN = %s \n",mcuInfo.vin);
UCHAR * packet = NULL;
//20200923 v1.02协议版本取消应答标志 增加终端软件版本号
packet = make_GBframeNew(DF_MSG_SERVER_VEHICLE_LOGIN,0x00,E_ENCRYPT_TYPE_NONE,Vin_Data,Custom_Login_Data,ulen);
if(packet)
{
dispatchDataBy4GNet_Df(DF_MSG_SERVER_VEHICLE_LOGIN,packet, ulen + 25 );
//LOGI(TAG,"#DFYY_TEST# GBcustom_login send data ok!!! \n");
printRawData("GBcustom_df_login data: ",packet, (ulen + 25)); //df login
free(packet);
packet = NULL;
//todo
// if(DfheartBeatTimer)
// {
// DfheartBeatTimer->start(DfheartBeatTimer);
// }
// //2021/3/9增加平台登入保存流水号
// m_instance->setSerialNumber(Serial_Number_All);
}
return true;
}
#include <iostream>
#include <unistd.h>
#include "SocketClient.h"
int main() {
SocketClient client;
client.connect_server_start_df();
sleep(1);
client.SendHeartBeatToDfServer();
sleep(1);
client.SendGbLoginReq();
// sleep(1);
client.receved_thread_start_df();
std::cout << "Hello, World!" << std::endl;
sleep(2);
return 0;
}