/* * Module_CabinetParallel.c * * Created on: 2021年9月28日 * Author: 7978 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*標準輸入輸出定義*/ #include /*標準函數庫定義*/ #include /*Unix 標準函數定義*/ #include /*檔控制定義*/ #include /*PPSIX 終端控制定義*/ #include /*錯誤號定義*/ #include #include #include #include #include #include #include #include "../../define.h" #include "Module_EvComm.h" #include "Module_CabinetParallel.h" #include "Config.h" #include "Common.h" //========================================== // Share Memory //========================================== struct SysConfigAndInfo *ShmSysConfigAndInfo; ChargerInfoData *ShmChargerInfo; struct ChargingInfoData *chargingInfo[CONNECTOR_QUANTITY]; PsuGroupCollectionData *ShmGroupCollection; struct PsuData *ShmPsuData; //========================================== // Local Variable //========================================== struct WARNING_CODE_INFO SlaveWarningInfo[MAX_SLAVE_CABINET_QUANTITY]; unsigned char _SCabinetUpdateState = 0; unsigned char PCabinetUpdateRequest[MAX_SLAVE_CABINET_QUANTITY]; int _regReqLen[PARALLEL_CABINET_REG_QUANTITY] = { REG_REQ_LEN_NONE, // reg: 0x00 REG_REQ_LEN_MODELNAME, // reg: 0x01 REG_REQ_LEN_ID, // reg: 0x02 REG_REQ_LEN_REG03, // reg: 0x03 REG_REQ_LEN_STATUS, // reg: 0x04 REG_REQ_LEN_OUTPUT_RELAY, // reg: 0x05 REG_REQ_LEN_AC_CONTACTOR, // reg: 0x06 REG_REQ_LEN_UPDATE, // reg: 0x07 REG_REQ_LEN_PARALLEL_RELAY, // reg: 0x08 }; int _regResLen[PARALLEL_CABINET_REG_QUANTITY] = { REG_RES_LEN_NONE, // reg: 0x00 REG_RES_LEN_MODELNAME, // reg: 0x01 REG_RES_LEN_ID, // reg: 0x02 REG_RES_LEN_REG03, // reg: 0x03 REG_RES_LEN_STATUS, // reg: 0x04 REG_RES_LEN_OUTPUT_RELAY, // reg: 0x05 REG_RES_LEN_AC_CONTACTOR, // reg: 0x06 REG_RES_LEN_UPDATE, // reg: 0x07 REG_RES_LEN_PARALLEL_RELAY, // reg: 0x08 }; void ShowSocketData(struct PACKET_STRUCTURE *packet) { printf("se: %02X, id: %02X, op: %d, len: %3d, reg: %02X", packet->Header.se, packet->Header.id, packet->Header.op, packet->Header.len, packet->Payload.reg); if(packet->Header.len > 1) { printf(", Data:"); for(int i = 0; i < packet->Header.len - 1; i++) { printf(" %02X", packet->Payload.data[i]); } } printf("\n"); } //========================================== // Init all share memory //========================================== int InitShareMemory(void) { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmSysConfigAndInfo NG"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmSysConfigAndInfo NG"); #endif result = FAIL; } else { } if ((MeterSMId = shmget(SM_ChargerInfoKey, sizeof(ChargerInfoData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmat ChargerInfoData NG"); #endif result = FAIL; } else if ((ShmChargerInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ChargerInfoData NG"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmPsuData NG"); #endif result = FAIL; } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmPsuData NG"); #endif result = FAIL; } if(result == PASS) { ShmGroupCollection = &ShmChargerInfo->PsuGrouping.GroupCollection[0]; } return result; } void InitialConnector(void) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { chargingInfo[i] = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData; } } void SlaveCabinetCheckInUpdate(void) { unsigned char slaveCnt = 0; for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus != _DS_None && ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus != _DS_Timeout) { slaveCnt++; } } ShmChargerInfo->ParallelCabinet.PresentParallelCabinetQuantity = slaveCnt; if(slaveCnt > ShmChargerInfo->ParallelCabinet.ParallelCabinetQuantity) { ShmChargerInfo->ParallelCabinet.ParallelCabinetQuantity = slaveCnt; } } void SetSlaveCabinetStatus(unsigned char DeviceIndex, unsigned char status) { if(DeviceIndex < MAX_SLAVE_CABINET_QUANTITY) { switch(status) { case _DS_Identification: case _DS_Alarm: case _DS_Charging: ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].LocalStatus = status; break; case _DS_Idle: if(ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].LocalStatus != status) { ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].ParallelRequest = YES; } ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].LocalStatus = status; break; case _DS_Timeout: memset(&ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex], 0x00, sizeof(SlaveCabinetInfoData)); ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].LocalStatus = status; break; case _DS_None: default: memset(&ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex], 0x00, sizeof(SlaveCabinetInfoData)); break; } } } void SlaveCabinetIpConflictedCheck(void) { unsigned char DuplicatedConfirm[MAX_SLAVE_CABINET_QUANTITY]; struct timespec _Conflicted_Time[MAX_SLAVE_CABINET_QUANTITY]; memset(DuplicatedConfirm, 0x00, MAX_SLAVE_CABINET_QUANTITY); while(1) { for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].IpDuplicatedFlag == true) { if(DuplicatedConfirm[i] == false) { DuplicatedConfirm[i] = true; GetClockTime(&_Conflicted_Time[i]); LOG_INFO("Slave Cabinet %d IP Conflicted Confirm", i + 1); } else { if((GetTimeoutValue(_Conflicted_Time[i]) / mSEC_VAL) >= IP_CONFLICTED_TIME) { // reach here only when MCabinetCommProcess is stopped if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus != _DS_None && ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus != _DS_Timeout) { unsigned char channel = ShmChargerInfo->ParallelCabinet.PCabinet[i].SocketChannel; if(ShmChargerInfo->CabinetConnInfo[channel].Status != _SCONN_FREE) { SetSlaveCabinetStatus(i, _DS_Timeout); SlaveCabinetCheckInUpdate(); memset(&ShmChargerInfo->CabinetConnInfo[channel], 0x00, sizeof(SocketConnInfoData)); LOG_INFO("Cabinet ConnInfo Channel %d Clean", channel); } } ShmChargerInfo->ParallelCabinet.PCabinet[i].IpDuplicatedFlag = false; DuplicatedConfirm[i] = false; LOG_INFO("Slave Cabinet %d IP Conflicted Stop", i + 1); } } } } usleep(500000); } } int ConflictedCabinetCheck(void) { pid_t forkId; forkId = fork(); if(forkId == 0) { SlaveCabinetIpConflictedCheck(); return forkId; } else if(forkId == -1) { LOG_INFO("fork fail"); } return forkId; } int GetFreeSocketChannel(SocketConnInfoData *SocketConn, int Len) { for(int i = 0; i < Len; i++) { if(SocketConn[i].Status == _SCONN_FREE) { return i; } } return FAIL; } bool IsConflictCabinetIp(uint32_t ipAddress) { for(int i = 0; i < ARRAY_SIZE(ShmChargerInfo->CabinetConnInfo); i++) { if(ShmChargerInfo->CabinetConnInfo[i].IpAddress == ipAddress) { int slaveCabinet = ShmChargerInfo->CabinetConnInfo[i].DeviceIndex; if(slaveCabinet < MAX_SLAVE_CABINET_QUANTITY) { if(ShmChargerInfo->ParallelCabinet.PCabinet[slaveCabinet].IpDuplicatedFlag == false) { ShmChargerInfo->ParallelCabinet.PCabinet[slaveCabinet].IpDuplicatedFlag = true; } return true; } } } return false; } bool FindSlaveCabinet(unsigned char DeviceIndex, unsigned char ID) { bool find = false; if(ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].SlaveID == ID) { find = true; } return find; } void SendPacket(int socket, struct PACKET_STRUCTURE *packet) { //ShowSocketData(packet); //send(socket, packet, packet->Header.len + 4, 0); send(socket, packet, packet->Header.len + 4, MSG_NOSIGNAL); } // Reg: 0x01, Slave Cabinet Model Name Handler // allow slave cabinet switch value: 2 ~ 5 // allow slave cabinet ip address: 31 ~ 34 // return legal id: 1 ~ 4 unsigned char MCabinetModelNameHandler(unsigned char connIndex, struct PACKET_STRUCTURE *packet) { unsigned char modelName[64]; unsigned char cabinetId = 0; memset(modelName, 0x00, 64); memcpy(modelName, packet->Payload.data, packet->Header.len - 1); cabinetId = (ShmChargerInfo->CabinetConnInfo[connIndex].IpAddress >> 24) & 0xFF; if(cabinetId <= 30 || cabinetId > (30 + MAX_SLAVE_CABINET_QUANTITY)) { LOG_INFO("Slave Cabinet DeviceID Out Of Range(%d), Model Name: %s", cabinetId, modelName); cabinetId = 0; } else { cabinetId -= 30; LOG_INFO("Slave Cabinet Check In, Device ID: %d, Model Name: %s", cabinetId, modelName); memcpy(ShmChargerInfo->ParallelCabinet.PCabinet[cabinetId - 1].ModelName, modelName, packet->Header.len - 1); ShmChargerInfo->ParallelCabinet.PCabinet[cabinetId - 1].SocketChannel = connIndex; } return cabinetId; } // Reg: 0x01, Slave Cabinet Model Name Response void MCabinetModelNameResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result) { struct PACKET_STRUCTURE sendBuffer; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = 0xFF; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 2; sendBuffer.Payload.reg = _Reg_Dispenser_Model_Name; sendBuffer.Payload.data[0] = result; SendPacket(socket, &sendBuffer); } // Reg: 0x02, Slave Cabinet ID Response void MCabinetIDResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, unsigned char DeviceIndex) { struct PACKET_STRUCTURE sendBuffer; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = 0xFF; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 3; sendBuffer.Payload.reg = _Reg_SCabinet_ID; sendBuffer.Payload.data[0] = result; sendBuffer.Payload.data[1] = ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].SlaveID; SendPacket(socket, &sendBuffer); } // Reg: 0x04, Slave Cabinet Status Handler bool MCabinetStatusHandler(struct PACKET_STRUCTURE *packet, unsigned char DeviceIndex) { bool find = FindSlaveCabinet(DeviceIndex, packet->Header.id); bool chagne = false; struct WARNING_CODE_INFO warning; if(find) { memset(&warning, 0x00, sizeof(struct WARNING_CODE_INFO)); warning.WarningCount = (packet->Header.len - 1) / 6; if(warning.WarningCount > 10) { warning.WarningCount = 10; } for(int i = 0; i < warning.WarningCount; i++) { memcpy(&warning.WarningCode[i][0], &packet->Payload.data[i * 6], 6); } if(SlaveWarningInfo[DeviceIndex].WarningCount != warning.WarningCount) { chagne = true; } else { if(warning.WarningCount != 0) { for(int i = 0; i < warning.WarningCount; i++) { if(strcmp((char *)&SlaveWarningInfo[DeviceIndex].WarningCode[i][0], (char *)&warning.WarningCode[i][0]) != EQUAL) { chagne = true; break; } } } } if(chagne) { memcpy(&SlaveWarningInfo[DeviceIndex], &warning, sizeof(struct WARNING_CODE_INFO)); char strSlaveDeviceStatus[128]; sprintf(strSlaveDeviceStatus, "PCabinet %d, Status Code Len: %d", ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].SlaveID, SlaveWarningInfo[DeviceIndex].WarningCount); if(SlaveWarningInfo[DeviceIndex].WarningCount > 0) { for(int i = 0; i < SlaveWarningInfo[DeviceIndex].WarningCount; i++) { char strTemp[16]; sprintf(strTemp, ", %s", SlaveWarningInfo[DeviceIndex].WarningCode[i]); strcat(strSlaveDeviceStatus, strTemp); } } LOG_INFO("%s", strSlaveDeviceStatus); } } else { // do nothing } return find; } // Reg: 0x04, Slave Cabinet Status Response void MCabinetStatusResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, unsigned char DeviceIndex) { struct PACKET_STRUCTURE sendBuffer; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = packet->Header.id; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 2; sendBuffer.Payload.reg = _Reg_SCabinet_Status; sendBuffer.Payload.data[0] = result; SendPacket(socket, &sendBuffer); } // Reg: 0x05, Output Relay Status Handler bool MCabinetOutputRelayHandler(struct PACKET_STRUCTURE *packet, unsigned char DeviceIndex) { bool find = FindSlaveCabinet(DeviceIndex, packet->Header.id); bool chagne = false; unsigned char relayState[MAX_GROUP_QUANTITY]; unsigned char *slaveRelayState; if(find) { if((packet->Header.len - 1) >= MAX_GROUP_QUANTITY) { slaveRelayState = &ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].GunOutputRelayState[0]; memcpy(relayState, &packet->Payload.data, MAX_GROUP_QUANTITY); for(int i = 0; i < MAX_GROUP_QUANTITY; i++) { if(slaveRelayState[i] != relayState[i]) { chagne = true; break; } } if(chagne) { memcpy(slaveRelayState, relayState, MAX_GROUP_QUANTITY); char strRelayStatus[128]; sprintf(strRelayStatus, "PCabinet %d Output Relay", DeviceIndex + 1); for(int i = 0; i < MAX_GROUP_QUANTITY; i++) { char strTemp[16]; sprintf(strTemp, " Gun %d %3s", i + 1, slaveRelayState[i] > 0 ? "ON" : "OFF"); strcat(strRelayStatus, strTemp); } LOG_INFO("%s", strRelayStatus); } } } else { // do nothing } return find; } // Reg: 0x05, Output Relay Status Response void MCabinetOutputRelayResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, unsigned char DeviceIndex) { struct PACKET_STRUCTURE sendBuffer; unsigned char *slaveRelayState; slaveRelayState = &ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].OutputRelaySetting[0]; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = packet->Header.id; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 6; sendBuffer.Payload.reg = _Reg_OutputRelay_Status; sendBuffer.Payload.data[0] = result; sendBuffer.Payload.data[1] = result == _R_OK ? slaveRelayState[0] : Relay_OFF; sendBuffer.Payload.data[2] = result == _R_OK ? slaveRelayState[1] : Relay_OFF; sendBuffer.Payload.data[3] = result == _R_OK ? slaveRelayState[2] : Relay_OFF; sendBuffer.Payload.data[4] = result == _R_OK ? slaveRelayState[3] : Relay_OFF; SendPacket(socket, &sendBuffer); } // Reg: 0x06, Ac Contactor Status Handler bool MCabinetAcContactorHandler(struct PACKET_STRUCTURE *packet, unsigned char DeviceIndex) { bool find = FindSlaveCabinet(DeviceIndex, packet->Header.id); bool chagne = false; unsigned char contactorState; unsigned char *slaveContactorState; if(find) { if((packet->Header.len - 1) >= 1) { slaveContactorState = &ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].AcContactorState; contactorState = packet->Payload.data[0]; if(*slaveContactorState != contactorState) { chagne = true; } if(chagne) { *slaveContactorState = contactorState; LOG_INFO("PCabinet %d AC Contactor State: %s", DeviceIndex + 1, *slaveContactorState > 0 ? "ON" : "OFF"); } } } else { // do nothing } return find; } // Reg: 0x06, Ac Contactor Status Response void MCabinetAcContactorResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, unsigned char DeviceIndex) { struct PACKET_STRUCTURE sendBuffer; unsigned char slaveContactorState = ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].AcContactorSetting; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = packet->Header.id; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 3; sendBuffer.Payload.reg = _Reg_AcContactor_Status; sendBuffer.Payload.data[0] = result; sendBuffer.Payload.data[1] = result == _R_OK ? slaveContactorState : Relay_OFF; SendPacket(socket, &sendBuffer); } // Reg: 0x07, Slave Cabinet Firmware Upgrade Handler bool MCabinetFwUpgradeHandler(struct PACKET_STRUCTURE *packet, unsigned char DeviceIndex) { bool find = FindSlaveCabinet(DeviceIndex, packet->Header.id); bool chagne = false; unsigned char updateState; unsigned char *slaveUpdateState; char *strUpdate[] = {"Not Update", "Updating", "Updated"}; if(find) { if((packet->Header.len - 1) >= 1) { slaveUpdateState = &ShmChargerInfo->ParallelCabinet.PCUpdateState[DeviceIndex]; updateState = packet->Payload.data[0]; if(*slaveUpdateState != updateState) { chagne = true; } if(chagne) { switch(updateState) { case Updated: ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].UpdateRequest = NO; break; } *slaveUpdateState = updateState; LOG_INFO("PCabinet %d Update State: %s", DeviceIndex + 1, *slaveUpdateState <= Updated ? strUpdate[*slaveUpdateState] : "Unknown"); } } } else { } return find; } // Reg: 0x07, Slave Cabinet Firmware Upgrade Response void MCabinetUpgradeResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, unsigned char DeviceIndex) { struct PACKET_STRUCTURE sendBuffer; unsigned char slaveUpdateRequest = ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].UpdateRequest; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = packet->Header.id; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 3; sendBuffer.Payload.reg = _Reg_SCabinet_FwUpdate; sendBuffer.Payload.data[0] = result; if(result == _R_OK) { sendBuffer.Payload.data[1] = slaveUpdateRequest > 0 ? _R_NeedUpgrade : _R_NoUpgrade; if(slaveUpdateRequest > 0) { int length = strlen(ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].FwFileName); memcpy(&sendBuffer.Payload.data[2], ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].FwFileName, length); sendBuffer.Header.len += length; if(PCabinetUpdateRequest[DeviceIndex] != slaveUpdateRequest) { LOG_INFO("MCabinet >> PCabinet %d Start Upgrade: %s", DeviceIndex + 1, ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].FwFileName); } } PCabinetUpdateRequest[DeviceIndex] = slaveUpdateRequest; } SendPacket(socket, &sendBuffer); } // Reg: 0x08, Parallel Relay Status Handler bool MCabinetParallelRelayHandler(struct PACKET_STRUCTURE *packet, unsigned char DeviceIndex) { bool find = FindSlaveCabinet(DeviceIndex, packet->Header.id); bool chagne = false; unsigned char relayState[MAX_GROUP_QUANTITY]; unsigned char *slaveRelayState; if(find) { if((packet->Header.len - 1) >= MAX_GROUP_QUANTITY) { slaveRelayState = &ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].ParallelRelayState[0]; memcpy(relayState, &packet->Payload.data, MAX_GROUP_QUANTITY); for(int i = 0; i < MAX_GROUP_QUANTITY; i++) { if(slaveRelayState[i] != relayState[i]) { chagne = true; break; } } if(chagne) { memcpy(slaveRelayState, relayState, MAX_GROUP_QUANTITY); char strRelayStatus[128]; sprintf(strRelayStatus, "PCabinet %d Parallel Relay", DeviceIndex + 1); for(int i = 0; i < MAX_GROUP_QUANTITY; i++) { char strTemp[16]; sprintf(strTemp, " Location %d %3s", i + 1, slaveRelayState[i] > 0 ? "ON" : "OFF"); strcat(strRelayStatus, strTemp); } LOG_INFO("%s", strRelayStatus); } } } else { // do nothing } return find; } // Reg: 0x08, Parallel Relay Status Response void MCabinetParallelRelayResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, unsigned char DeviceIndex) { struct PACKET_STRUCTURE sendBuffer; unsigned char *slaveRelayState; slaveRelayState = &ShmChargerInfo->ParallelCabinet.PCabinet[DeviceIndex].ParallelRelaySetting[0]; memset(&sendBuffer, 0x00, sizeof(sendBuffer)); sendBuffer.Header.se = packet->Header.se; sendBuffer.Header.id = packet->Header.id; sendBuffer.Header.op = _Header_Response; sendBuffer.Header.len = 6; sendBuffer.Payload.reg = _Reg_ParallelRelay_Status; sendBuffer.Payload.data[0] = result; sendBuffer.Payload.data[1] = result == _R_OK ? slaveRelayState[0] : Relay_OFF; sendBuffer.Payload.data[2] = result == _R_OK ? slaveRelayState[1] : Relay_OFF; sendBuffer.Payload.data[3] = result == _R_OK ? slaveRelayState[2] : Relay_OFF; sendBuffer.Payload.data[4] = result == _R_OK ? slaveRelayState[3] : Relay_OFF; SendPacket(socket, &sendBuffer); } int BufferRePacket(int dataLength, unsigned char *buffer, struct PACKET_STRUCTURE *packet) { int totalLength = 0, packetCnt = 0, singleLength = 0; struct PACKET_STRUCTURE *tempPacket; while(dataLength > 0) { tempPacket = (struct PACKET_STRUCTURE *)&buffer[totalLength]; singleLength = tempPacket->Header.len + PACKET_HEADER_LENGTH; if(dataLength >= singleLength) { totalLength += singleLength; dataLength -= singleLength; memset(&packet[packetCnt], 0x00, sizeof(struct PACKET_STRUCTURE)); memcpy(&packet[packetCnt], tempPacket, singleLength); packetCnt++; } else { LOG_INFO("Packet[%d] is incomplete(%d/%d)", packetCnt, dataLength, singleLength); dataLength = 0; } } return packetCnt; } void MCabinetPacketHandler(int socketFd, unsigned char socketIndex, struct PACKET_STRUCTURE *packet) { unsigned char ackResult = _R_NG; unsigned char deviceIndex = 0; if(ShmChargerInfo->CabinetConnInfo[socketIndex].Status == _SCONN_WAIT) { // Reg: 0x01, Dispenser model name if(packet->Header.op == _Header_Write && packet->Payload.reg == _Reg_SCabinet_Model_Name) { unsigned char deviceID = MCabinetModelNameHandler(socketIndex, packet); if(deviceID > 0) { ackResult = _R_OK; deviceIndex = deviceID - 1; } MCabinetModelNameResponse(socketFd, packet, ackResult); ShmChargerInfo->CabinetConnInfo[socketIndex].Status = ackResult == _R_OK ? _SCONN_MATCHED : _SCONN_WAIT; ShmChargerInfo->CabinetConnInfo[socketIndex].DeviceIndex = deviceIndex; if(ackResult == _R_OK) { ShmChargerInfo->ParallelCabinet.PCabinet[deviceIndex].SlaveID = deviceID; SetSlaveCabinetStatus(deviceIndex, _DS_Identification); SlaveCabinetCheckInUpdate(); } } else { // do nothing } // do not clear timeout value, then close socket when timeout value exceed SOCKET_RECEIVE_INTERVAL } else if(ShmChargerInfo->CabinetConnInfo[socketIndex].Status == _SCONN_MATCHED) { deviceIndex = ShmChargerInfo->CabinetConnInfo[socketIndex].DeviceIndex; // Reg: 0x01, Dispenser model name if(packet->Header.op == _Header_Write && packet->Payload.reg == _Reg_SCabinet_Model_Name) { ackResult = _R_OK; MCabinetModelNameResponse(socketFd, packet, ackResult); } // Reg: 0x02, Slave Cabinet ID if(packet->Header.op == _Header_Read && packet->Payload.reg == _Reg_SCabinet_ID) { ackResult = _R_OK; SetSlaveCabinetStatus(deviceIndex, _DS_Idle); MCabinetIDResponse(socketFd, packet, ackResult, deviceIndex); } // Reg: 0x04, Slave Cabinet Status if(packet->Header.op == _Header_Write && packet->Payload.reg == _Reg_SCabinet_Status) { if(MCabinetStatusHandler(packet, deviceIndex)) { ackResult = _R_OK; } MCabinetStatusResponse(socketFd, packet, ackResult, deviceIndex); } // Reg: 0x05, Sync Output Relay Status if(packet->Header.op == _Header_Read && packet->Payload.reg == _Reg_OutputRelay_Status) { if(MCabinetOutputRelayHandler(packet, deviceIndex)) { ackResult = _R_OK; } MCabinetOutputRelayResponse(socketFd, packet, ackResult, deviceIndex); } // Reg: 0x06, Sync Ac Contactor Status if(packet->Header.op == _Header_Read && packet->Payload.reg == _Reg_AcContactor_Status) { if(MCabinetAcContactorHandler(packet, deviceIndex)) { ackResult = _R_OK; } MCabinetAcContactorResponse(socketFd, packet, ackResult, deviceIndex); } // Reg: 0x07, Fw Update if(packet->Header.op == _Header_Read && packet->Payload.reg == _Reg_SCabinet_FwUpdate) { if(MCabinetFwUpgradeHandler(packet, deviceIndex)) { ackResult = _R_OK; } MCabinetUpgradeResponse(socketFd, packet, ackResult, deviceIndex); } // Reg: 0x08, Sync Parallel Relay Status if(packet->Header.op == _Header_Read && packet->Payload.reg == _Reg_ParallelRelay_Status) { if(MCabinetParallelRelayHandler(packet, deviceIndex)) { ackResult = _R_OK; } MCabinetParallelRelayResponse(socketFd, packet, ackResult, deviceIndex); } } } void MCabinetCommProcess(int socketFd, struct sockaddr_in clientInfo, unsigned char socketIndex) { int rxLen = 0, packetCnt = 0; unsigned char dataBuffer[MAX_DATA_BUFFER_LEN]; struct PACKET_STRUCTURE packetBuffer[MAX_PACKET_BUFFER_LEN]; struct timespec _MCabinet_timeout; LOG_INFO("Start Slave Cabinet Communication Process, IP %s connection(%d), PID = %d", (inet_ntoa(clientInfo.sin_addr)), socketIndex, getpid()); GetClockTime(&_MCabinet_timeout); while(1) { if((rxLen = recv(socketFd, &dataBuffer[0], MAX_DATA_BUFFER_LEN, MSG_DONTWAIT )) > 0) { packetCnt = BufferRePacket(rxLen, &dataBuffer[0], &packetBuffer[0]); if(packetCnt > 0) { //LOG_INFO("Socket[%d] %d packet received", socketIndex, packetCnt); for(int i = 0; i < packetCnt; i++) { //ShowSocketData(&packetBuffer[i]); MCabinetPacketHandler(socketFd, socketIndex, &packetBuffer[i]); } if(ShmChargerInfo->CabinetConnInfo[socketIndex].Status == _SCONN_MATCHED) { // clear timeout value GetClockTime(&_MCabinet_timeout); } } } else { usleep((SOCKET_RECEIVE_INTERVAL * 1000)); } if(GetTimeoutValue(_MCabinet_timeout) / uSEC_VAL >= MASTER_SLAVE_CABINET_TIMEOUT) { //timeout LOG_INFO("Slave Cabinet IP: %s, Socket %d Communication Timeout", (inet_ntoa(clientInfo.sin_addr)), socketIndex); if(ShmChargerInfo->CabinetConnInfo[socketIndex].Status == _SCONN_MATCHED) { SetSlaveCabinetStatus(ShmChargerInfo->CabinetConnInfo[socketIndex].DeviceIndex, _DS_Timeout); SlaveCabinetCheckInUpdate(); } break; } if(ShmChargerInfo->CabinetConnInfo[socketIndex].Status == _SCONN_MATCHED) { if(ShmChargerInfo->ParallelCabinet.PCabinet[ShmChargerInfo->CabinetConnInfo[socketIndex].DeviceIndex].IpDuplicatedFlag == true) { LOG_INFO("Slave Cabinet %d has been kick", ShmChargerInfo->CabinetConnInfo[socketIndex].DeviceIndex + 1); SetSlaveCabinetStatus(ShmChargerInfo->CabinetConnInfo[socketIndex].DeviceIndex, _DS_Timeout); SlaveCabinetCheckInUpdate(); break; } } } } void InitMasterCabinetInfo(void) { for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { memset(&SlaveWarningInfo[i], 0x00, sizeof(struct WARNING_CODE_INFO)); } } bool IsReadyAcceptSlaveCabinet(void) { bool ready = true; for(int i = 0; i < ShmChargerInfo->Control.MaxConnector; i++) { if (chargingInfo[i]->SystemStatus != S_IDLE && chargingInfo[i]->SystemStatus != S_MAINTAIN) { ready = false; break; } } return ready; } int MasterCabinetProcess(void) { int sockFd = 0; int clientSockFd = 0; int connIndex = 0; int bindStatus = 0; int reuseaddr = 1; pid_t forkId; bool isConflict = false, isReady = false, preReady = false; struct sockaddr_in serverInfo, clientInfo; socklen_t addrlen = sizeof(clientInfo); sockFd = socket(AF_INET, SOCK_STREAM, 0); if(sockFd == -1) { LOG_INFO("InitSocketServer NG\n"); sleep(5); return FAIL; } setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); InitMasterCabinetInfo(); bzero(&serverInfo,sizeof(serverInfo)); serverInfo.sin_family = PF_INET; serverInfo.sin_addr.s_addr = htonl(INADDR_ANY); serverInfo.sin_port = htons(MASTER_TCP_LISTEN_PORT); bindStatus = bind(sockFd, (struct sockaddr *)&serverInfo, sizeof(serverInfo)); if(bindStatus < 0) { LOG_INFO("Master Cabinet socket bind fail"); return FAIL; } listen(sockFd, CONNECTION_LIMIT); LOG_INFO("Master Cabinet Server Start"); signal(SIGCHLD, SIG_IGN); if(ConflictedCabinetCheck() <= 0) { // child process return here return 0; } // Main loop while(1) { clientSockFd = accept(sockFd, (struct sockaddr*) &clientInfo, &addrlen); isReady = IsReadyAcceptSlaveCabinet(); if(isReady) { LOG_INFO("Slave Cabinet ip: %s is accepted at port: %d", inet_ntoa(clientInfo.sin_addr), clientInfo.sin_port); } else { // not ready if(preReady != isReady) { LOG_INFO("MCabinet Is Not Ready To Paralleling"); } close(clientSockFd); preReady = isReady; continue; } preReady = isReady; connIndex = GetFreeSocketChannel(ShmChargerInfo->CabinetConnInfo, ARRAY_SIZE(ShmChargerInfo->CabinetConnInfo)); if(connIndex >= 0) { isConflict = IsConflictCabinetIp(clientInfo.sin_addr.s_addr); if(isConflict == false) { ShmChargerInfo->CabinetConnInfo[connIndex].Status = _SCONN_WAIT; ShmChargerInfo->CabinetConnInfo[connIndex].IpAddress = clientInfo.sin_addr.s_addr; forkId = fork(); if(forkId == 0) { // child process MCabinetCommProcess(clientSockFd, clientInfo, connIndex); close(clientSockFd); memset(&ShmChargerInfo->CabinetConnInfo[connIndex], 0x00, sizeof(SocketConnInfoData)); return 0; } else if(forkId == -1) { LOG_INFO("Slave Cabinet Process Fork Fail"); } } else { if(isConflict) { // conflict ip address LOG_INFO("Conflict Slave Cabinet IP address, Close Socket"); } close(clientSockFd); memset(&ShmChargerInfo->CabinetConnInfo[connIndex], 0x00, sizeof(SocketConnInfoData)); } } else { // no free channel LOG_INFO("No Free Cabinet Channel, Close Socket"); close(clientSockFd); } usleep(10000); } return 0; } // ****************************** Slave ****************************** // unsigned char _modelNameAck = 0; unsigned char _idAck = 0; unsigned char _header_SE = 0; struct timespec _regQreuyTime[PARALLEL_CABINET_REG_QUANTITY]; int _regTimeout[PARALLEL_CABINET_REG_QUANTITY] = { REG_RSEND_TIME_NONE, // reg: 0x00 REG_RSEND_TIME_MODELNAME, // reg: 0x01 REG_RSEND_TIME_ID, // reg: 0x02 REG_RSEND_TIME_REG03, // reg: 0x03 REG_RSEND_TIME_STATUS, // reg: 0x04 REG_RSEND_TIME_OUTPUT_RELAY, // reg: 0x05 REG_RSEND_TIME_AC_CONTACTOR, // reg: 0x06 REG_RSEND_TIME_UPDATE, // reg: 0x07 REG_RSEND_TIME_PARALLEL_RELAY, // reg: 0x08 }; int ConnectToMasterCabinet(void) { int sockFd = 0; struct sockaddr_in serverInfo; struct timeval tv; sockFd = socket(AF_INET, SOCK_STREAM, 0); if(sockFd < 0) { LOG_INFO("Create Slave Cabinet Socket Fail"); return -1; } tv.tv_sec = 3; tv.tv_usec = 0; setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); //設定等待3s setsockopt(sockFd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); //設定傳送3s bzero(&serverInfo,sizeof(serverInfo)); serverInfo.sin_family = AF_INET; serverInfo.sin_addr.s_addr = inet_addr(MASTER_ETH1_IP); serverInfo.sin_port = htons(MASTER_TCP_LISTEN_PORT); if(connect(sockFd, (struct sockaddr *)&serverInfo, sizeof(serverInfo)) < 0) { //LOG_INFO("Connect To Master Cabinet Error[%d]", errno); close(sockFd); return -1; } return sockFd; } void SendParallelPacket(int fd, unsigned char opCode, unsigned char length, unsigned char reg, unsigned char *data) { struct PACKET_STRUCTURE packet; packet.Header.se = _header_SE++; packet.Header.id = ShmChargerInfo->SCabinetControl.SCabinetID; packet.Header.op = opCode; packet.Header.len = length; packet.Payload.reg = reg; if(length > 1) { memcpy(packet.Payload.data, data, length - 1); } SendPacket(fd, &packet); } // reg: 0x01, Slave Cabinet Write Model Name void SCabinetWriteModelName(int fd) { if(GetTimeoutValue(_regQreuyTime[_Reg_SCabinet_Model_Name]) / mSEC_VAL >= _regTimeout[_Reg_SCabinet_Model_Name]) { SendParallelPacket( fd, _Header_Write, strlen((char *)ShmSysConfigAndInfo->SysConfig.ModelName) + 1, _Reg_SCabinet_Model_Name, ShmSysConfigAndInfo->SysConfig.ModelName); GetClockTime(&_regQreuyTime[_Reg_SCabinet_Model_Name]); //LOG_INFO("SCabinet Write Model Nname..."); } } // reg: 0x01, Slave Cabinet Model Name Handler unsigned char SCabinetModelNameHandler(struct PACKET_STRUCTURE *packet) { unsigned char ack = _R_NG; if(packet->Header.len >= _regResLen[_Reg_SCabinet_Model_Name]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; if(_modelNameAck != ack) { LOG_INFO("SCabinet Write Model Name %s", ack == _R_OK ? "OK" : "NG"); } _modelNameAck = ack; } return ack; } // reg: 0x02, Slave Cabinet Read ID void SCabinetReadID(int fd) { if(GetTimeoutValue(_regQreuyTime[_Reg_SCabinet_ID]) / mSEC_VAL >= _regTimeout[_Reg_SCabinet_ID]) { SendParallelPacket( fd, _Header_Read, _regReqLen[_Reg_SCabinet_ID], _Reg_SCabinet_ID, 0); GetClockTime(&_regQreuyTime[_Reg_SCabinet_ID]); //LOG_INFO("SCabinet Read ID..."); } } // reg: 0x02, Slave Cabinet ID Handler unsigned char SCabinetIDHandler(struct PACKET_STRUCTURE *packet) { unsigned char ack = _R_NG; unsigned char id = 0; if(packet->Header.len >= _regResLen[_Reg_SCabinet_ID]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; if(ack == _R_OK) { id = packet->Payload.data[1]; if(ShmChargerInfo->SCabinetControl.SCabinetID != id && id != 0) { ShmChargerInfo->SCabinetControl.SCabinetID = id; LOG_INFO("Get SCabinet ID: %d", ShmChargerInfo->SCabinetControl.SCabinetID); } } if(_idAck != ack) { LOG_INFO("SCabinet Read ID %s", ack == _R_OK ? "OK" : "NG"); } } return ack; } // reg: 0x04 void SCabinetWriteStatus(int fd) { bool chagne = false; unsigned char statusCode[256]; if(ShmSysConfigAndInfo->SysWarningInfo.WarningCount != SlaveWarningInfo[0].WarningCount) { chagne = true; } else { if(ShmSysConfigAndInfo->SysWarningInfo.WarningCount != 0) { for(int i = 0; i < ShmSysConfigAndInfo->SysWarningInfo.WarningCount; i++) { if(strcmp((char *)&SlaveWarningInfo[0].WarningCode[i][0], (char *)&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i][0]) != EQUAL) { chagne = true; break; } } } } if(chagne) { memcpy(&SlaveWarningInfo[0], &ShmSysConfigAndInfo->SysWarningInfo, sizeof(struct WARNING_CODE_INFO)); } if(GetTimeoutValue(_regQreuyTime[_Reg_SCabinet_Status]) / mSEC_VAL >= _regTimeout[_Reg_SCabinet_Status] || chagne) { for(int i = 0; i < ShmSysConfigAndInfo->SysWarningInfo.WarningCount; i++) { memcpy(&statusCode[i * 6], &ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i][0], 6); } SendParallelPacket( fd, _Header_Write, (ShmSysConfigAndInfo->SysWarningInfo.WarningCount * 6) + 1, _Reg_SCabinet_Status, &statusCode[0]); GetClockTime(&_regQreuyTime[_Reg_SCabinet_Status]); //LOG_INFO("SCabinet Write Status..."); } } // reg: 0x04, Slave Cabinet Status Handler unsigned char SCabinetStatusHandler(struct PACKET_STRUCTURE *packet) { unsigned char ack = _R_NG; if(packet->Header.id != ShmChargerInfo->SCabinetControl.SCabinetID) { return ack; } if(packet->Header.len >= _regResLen[_Reg_SCabinet_Status]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; } return ack; } // reg: 0x05 void SCabinetReadOutputRelay(int fd) { unsigned char outputRelay[GENERAL_GUN_QUANTITY] = {0}; if(GetTimeoutValue(_regQreuyTime[_Reg_OutputRelay_Status]) / mSEC_VAL >= _regTimeout[_Reg_OutputRelay_Status]) { memcpy(&outputRelay[0], &ShmChargerInfo->SCabinetControl.SOutputRelay[0], GENERAL_GUN_QUANTITY); SendParallelPacket( fd, _Header_Read, _regReqLen[_Reg_OutputRelay_Status], _Reg_OutputRelay_Status, &outputRelay[0]); GetClockTime(&_regQreuyTime[_Reg_OutputRelay_Status]); //LOG_INFO("SCabinet Read OutputRelay..."); } } // reg: 0x05, Slave Cabinet Output Relay Handler unsigned char SCabinetOutputRelayHandler(struct PACKET_STRUCTURE *packet) { bool chagne = false; unsigned char ack = _R_NG; if(packet->Header.id != ShmChargerInfo->SCabinetControl.SCabinetID) { return ack; } if(packet->Header.len >= _regResLen[_Reg_OutputRelay_Status]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; if(ack == _R_OK) { for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { if(packet->Payload.data[i + 1] != ShmChargerInfo->SCabinetControl.SOutputRelay[i]) { chagne = true; } } memcpy(&ShmChargerInfo->SCabinetControl.SOutputRelay[0], &packet->Payload.data[1], GENERAL_GUN_QUANTITY); if(chagne) { LOG_INFO("SCabinet[%d] Need Set OutputRelay: %3s %3s %3s %3s", ShmChargerInfo->SCabinetControl.SCabinetID, ShmChargerInfo->SCabinetControl.SOutputRelay[0] > 0 ? "ON" : "OFF", ShmChargerInfo->SCabinetControl.SOutputRelay[1] > 0 ? "ON" : "OFF", ShmChargerInfo->SCabinetControl.SOutputRelay[2] > 0 ? "ON" : "OFF", ShmChargerInfo->SCabinetControl.SOutputRelay[3] > 0 ? "ON" : "OFF"); } } } return ack; } // reg: 0x06 void SCabinetReadAcContactor(int fd) { unsigned char acContactor = 0; if(GetTimeoutValue(_regQreuyTime[_Reg_AcContactor_Status]) / mSEC_VAL >= _regTimeout[_Reg_AcContactor_Status]) { acContactor = ShmChargerInfo->SCabinetControl.SAcContactor; SendParallelPacket( fd, _Header_Read, _regReqLen[_Reg_AcContactor_Status], _Reg_AcContactor_Status, &acContactor); GetClockTime(&_regQreuyTime[_Reg_AcContactor_Status]); //LOG_INFO("SCabinet Read AcContactor..."); } } // reg: 0x06, Slave Cabinet Ac Contactor Handler unsigned char SCabinetAcContactorHandler(struct PACKET_STRUCTURE *packet) { bool chagne = false; unsigned char ack = _R_NG; if(packet->Header.id != ShmChargerInfo->SCabinetControl.SCabinetID) { return ack; } if(packet->Header.len >= _regResLen[_Reg_AcContactor_Status]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; if(ack == _R_OK) { if(packet->Payload.data[1] != ShmChargerInfo->SCabinetControl.SAcContactor) { chagne = true; } ShmChargerInfo->SCabinetControl.SAcContactor = packet->Payload.data[1]; if(chagne) { LOG_INFO("SCabinet[%d] Need Set AC Contactor: %3s", ShmChargerInfo->SCabinetControl.SCabinetID, ShmChargerInfo->SCabinetControl.SAcContactor > 0 ? "ON" : "OFF"); } } } return ack; } // reg: 0x07 void SCabinetReadFwUpdate(int fd) { bool chagne = false; if(_SCabinetUpdateState != ShmChargerInfo->SCabinetControl.UpgradeState) { chagne = true; } _SCabinetUpdateState = ShmChargerInfo->SCabinetControl.UpgradeState; if(GetTimeoutValue(_regQreuyTime[_Reg_SCabinet_FwUpdate]) / mSEC_VAL >= _regTimeout[_Reg_SCabinet_FwUpdate] || chagne) { SendParallelPacket( fd, _Header_Read, _regReqLen[_Reg_SCabinet_FwUpdate], _Reg_SCabinet_FwUpdate, &_SCabinetUpdateState); GetClockTime(&_regQreuyTime[_Reg_SCabinet_FwUpdate]); } } // reg: 0x07, Slave Cabinet FW Update Handler unsigned char SCabinetFwUpdateHandler(struct PACKET_STRUCTURE *packet) { bool chagne = false; unsigned char update = _R_NoUpgrade; unsigned char ack = _R_NG; unsigned char image[128]; if(packet->Header.id != ShmChargerInfo->SCabinetControl.SCabinetID) { return ack; } if(packet->Header.len >= _regResLen[_Reg_SCabinet_FwUpdate]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; if(ack == _R_OK) { update = packet->Payload.data[1] == _R_NeedUpgrade ? _R_NeedUpgrade : _R_NoUpgrade; if(update == _R_NeedUpgrade && ShmChargerInfo->SCabinetControl.UpgradeState == Not_Update) { if(packet->Header.len > _regResLen[_Reg_SCabinet_FwUpdate]) { memset(&image[0], 0x00, sizeof(image)); memcpy(&image[0], &packet->Payload.data[2], packet->Header.len - _regResLen[_Reg_SCabinet_FwUpdate]); } else { LOG_INFO("SCabinet[%d] %s image length fail: %d", ShmChargerInfo->SCabinetControl.SCabinetID, packet->Header.len); update = _R_NoUpgrade; } } if(update != ShmChargerInfo->SCabinetControl.NeedUpgrade) { chagne = true; } ShmChargerInfo->SCabinetControl.NeedUpgrade = update; if(chagne) { LOG_INFO("SCabinet[%d] Update Indicator [%s]", ShmChargerInfo->SCabinetControl.SCabinetID, ShmChargerInfo->SCabinetControl.NeedUpgrade == _R_NeedUpgrade ? "Need Upgrade" : "No Update"); if(ShmChargerInfo->SCabinetControl.UpgradeState == Not_Update && ShmChargerInfo->SCabinetControl.NeedUpgrade == _R_NeedUpgrade) { LOG_INFO("SCabinet[%d] Get Image: [%s]", ShmChargerInfo->SCabinetControl.SCabinetID, image); memcpy(ShmChargerInfo->SCabinetControl.FwFileName, image, sizeof(image)); ShmSysConfigAndInfo->SysInfo.FirmwareUpdate = YES; } if(ShmChargerInfo->SCabinetControl.UpgradeState == Updated && ShmChargerInfo->SCabinetControl.NeedUpgrade == _R_NoUpgrade) { LOG_INFO("MCabinet & SCabinet[%d] upgrade completed", ShmChargerInfo->SCabinetControl.SCabinetID); } } } } return ack; } // reg: 0x08 void SCabinetReadParallelRelay(int fd) { unsigned char parallelRelay[GENERAL_GUN_QUANTITY] = {0}; if(GetTimeoutValue(_regQreuyTime[_Reg_ParallelRelay_Status]) / mSEC_VAL >= _regTimeout[_Reg_ParallelRelay_Status]) { memcpy(¶llelRelay[0], &ShmChargerInfo->SCabinetControl.SParallelRelay[0], GENERAL_GUN_QUANTITY); SendParallelPacket( fd, _Header_Read, _regReqLen[_Reg_ParallelRelay_Status], _Reg_ParallelRelay_Status, ¶llelRelay[0]); GetClockTime(&_regQreuyTime[_Reg_ParallelRelay_Status]); //LOG_INFO("SCabinet Read ParallelRelay..."); } } // reg: 0x08, Slave Cabinet Parallel Relay Handler unsigned char SCabinetParallelRelayHandler(struct PACKET_STRUCTURE *packet) { bool chagne = false; unsigned char ack = _R_NG; if(packet->Header.id != ShmChargerInfo->SCabinetControl.SCabinetID) { return ack; } if(packet->Header.len >= _regResLen[_Reg_ParallelRelay_Status]) { ack = packet->Payload.data[0] == _R_OK ? _R_OK : _R_NG; if(ack == _R_OK) { for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { if(packet->Payload.data[i + 1] != ShmChargerInfo->SCabinetControl.SParallelRelay[i]) { chagne = true; } } memcpy(&ShmChargerInfo->SCabinetControl.SParallelRelay[0], &packet->Payload.data[1], GENERAL_GUN_QUANTITY); if(chagne) { LOG_INFO("SCabinet[%d] Need Set ParallelRelay: %3s %3s %3s %3s", ShmChargerInfo->SCabinetControl.SCabinetID, ShmChargerInfo->SCabinetControl.SParallelRelay[0] > 0 ? "ON" : "OFF", ShmChargerInfo->SCabinetControl.SParallelRelay[1] > 0 ? "ON" : "OFF", ShmChargerInfo->SCabinetControl.SParallelRelay[2] > 0 ? "ON" : "OFF", ShmChargerInfo->SCabinetControl.SParallelRelay[3] > 0 ? "ON" : "OFF"); } } } return ack; } void SCabinetPacketHandler(struct PACKET_STRUCTURE *packet) { // Reg: 0x01, Dispenser model name if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_SCabinet_Model_Name) { SCabinetModelNameHandler(packet); } // Reg: 0x02, Slave Cabinet ID if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_SCabinet_ID) { SCabinetIDHandler(packet); } // Reg: 0x04, Slave Cabinet Status if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_SCabinet_Status) { SCabinetStatusHandler(packet); } // Reg: 0x05, Sync Output Relay Status if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_OutputRelay_Status) { SCabinetOutputRelayHandler(packet); } // Reg: 0x06, Sync Ac Contactor Status if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_AcContactor_Status) { SCabinetAcContactorHandler(packet); } // Reg: 0x07, Fw Update if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_SCabinet_FwUpdate) { SCabinetFwUpdateHandler(packet); } // Reg: 0x08, Sync Parallel Relay Status if(packet->Header.op == _Header_Response && packet->Payload.reg == _Reg_ParallelRelay_Status) { SCabinetParallelRelayHandler(packet); } } int SlaveCabinetProcess(void) { int slavefd = 0, rxLen = 0, packetCnt = 0; //struct PACKET_STRUCTURE receiveBuffer; unsigned char dataBuffer[MAX_DATA_BUFFER_LEN]; struct PACKET_STRUCTURE packetBuffer[MAX_PACKET_BUFFER_LEN]; unsigned char Status = 0xFF, preStatus = 0xFF; struct timespec _slaveCabinetStatus_time; struct timespec _SCabinet_timeout; ShmChargerInfo->SCabinetControl.SCabinetStatus = _DeviceStatus_DisConnect; ShmChargerInfo->SCabinetControl.SCabinetID = 0xFF; _modelNameAck = 0; _idAck = 0; _header_SE = 0; ShmChargerInfo->SCabinetControl.SCabinetID = 0xFF; slavefd = socket(AF_INET, SOCK_STREAM, 0); if (slavefd == -1) { LOG_INFO("Create Slave Cabinet Socket Fail"); return -1; } LOG_INFO("Slave Cabinet Client Start, PID = %d", getpid()); while(1) { // **************************************** transmit **************************************** Status = ShmChargerInfo->SCabinetControl.SCabinetStatus; //LOG_INFO("SCabinet Status: %d", Status); switch(Status) { case _DeviceStatus_DisConnect: if(preStatus != Status) { _modelNameAck = 0; _idAck = 0; _header_SE = 0x00; ShmChargerInfo->SCabinetControl.SCabinetID = 0xFF; memset(&SlaveWarningInfo[0], 0x00, sizeof(struct WARNING_CODE_INFO)); LOG_INFO("Slave Cabinet [Disconnect]"); GetClockTime(&_slaveCabinetStatus_time); } slavefd = ConnectToMasterCabinet(); if(slavefd > 0) { GetClockTime(&_SCabinet_timeout); ShmChargerInfo->SCabinetControl.SCabinetStatus = _DeviceStatus_Identification; LOG_INFO("Connecting to MCabinet..."); break; } if(GetTimeoutValue(_slaveCabinetStatus_time) / uSEC_VAL >= DISCONNECT_PROMPT) { LOG_INFO("SCabinet Connecting..."); GetClockTime(&_slaveCabinetStatus_time); } break; case _DeviceStatus_Identification: if(preStatus != Status) { _modelNameAck = 0; _idAck = 0; _header_SE = 0x00; ShmChargerInfo->SCabinetControl.SCabinetID = 0xFF; memset(&SlaveWarningInfo[0], 0x00, sizeof(struct WARNING_CODE_INFO)); GetClockTime(&_SCabinet_timeout); LOG_INFO("Slave Cabinet [Identification]"); GetClockTime(&_slaveCabinetStatus_time); } if(_modelNameAck != _R_OK) { SCabinetWriteModelName(slavefd); } if(ShmChargerInfo->SCabinetControl.SCabinetID == 0xFF || ShmChargerInfo->SCabinetControl.SCabinetID == 0) { SCabinetReadID(slavefd); } if(_modelNameAck == _R_OK && ShmChargerInfo->SCabinetControl.SCabinetID != 0xFF && ShmChargerInfo->SCabinetControl.SCabinetID != 0) { ShmChargerInfo->SCabinetControl.SCabinetStatus = _DeviceStatus_Idle; } break; case _DeviceStatus_Idle: if(preStatus != Status) { LOG_INFO("Slave Cabinet [Idle]"); GetClockTime(&_slaveCabinetStatus_time); } SCabinetWriteStatus(slavefd); SCabinetReadOutputRelay(slavefd); SCabinetReadAcContactor(slavefd); SCabinetReadFwUpdate(slavefd); SCabinetReadParallelRelay(slavefd); break; case _DeviceStatus_Alarm: if(preStatus != Status) { LOG_INFO("Slave Cabinet [Alarm]"); GetClockTime(&_slaveCabinetStatus_time); } break; case _DeviceStatus_Charging: break; case _DeviceStatus_Timeout: if(preStatus != Status) { LOG_INFO("Slave Cabinet Retry [Timeout]"); GetClockTime(&_slaveCabinetStatus_time); } ShmChargerInfo->SCabinetControl.SCabinetStatus = _DeviceStatus_RetryWait; break; case _DeviceStatus_RetryWait: if(preStatus != Status) { LOG_INFO("Slave Cabinet Retry [Wait]"); GetClockTime(&_slaveCabinetStatus_time); } if(GetTimeoutValue(_slaveCabinetStatus_time) / uSEC_VAL >= 3) { ShmChargerInfo->SCabinetControl.SCabinetStatus = _DeviceStatus_DisConnect; } break; default: break; } preStatus = Status; // **************************************** receive **************************************** if(ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_DisConnect && ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_Timeout && ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_RetryWait) { if((rxLen = recv(slavefd, &dataBuffer[0], MAX_DATA_BUFFER_LEN, MSG_DONTWAIT )) > 0) { packetCnt = BufferRePacket(rxLen, &dataBuffer[0], &packetBuffer[0]); if(packetCnt > 0) { //LOG_INFO("SCabinet %d packet received", packetCnt); for(int i = 0; i < packetCnt; i++) { //ShowSocketData(&packetBuffer[i]); SCabinetPacketHandler(&packetBuffer[i]); } // clear timeout value GetClockTime(&_SCabinet_timeout); } } } // **************************************** timeout **************************************** if(ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_DisConnect && ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_Timeout && ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_RetryWait) { if(GetTimeoutValue(_SCabinet_timeout) / uSEC_VAL >= MASTER_SLAVE_CABINET_TIMEOUT) { if(slavefd > 0) { close(slavefd); } LOG_INFO("SCabinet timeout, close socket..."); ShmChargerInfo->SCabinetControl.SCabinetStatus = _DeviceStatus_Timeout; } } usleep((SOCKET_RECEIVE_INTERVAL * 1000)); } return 0; } int main(void) { if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage LOG_ERROR("InitShareMemory NG"); #endif sleep(5); return 0; } InitialConnector(); // wait for self test completed while(ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING || ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_COMPLETE || ShmChargerInfo->Control.CabinetRole == _CROLE_SINGLE) { sleep(1); } if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { MasterCabinetProcess(); } else if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE) { SlaveCabinetProcess(); } return 0; }